简体   繁体   中英

three.js make object dynamically on double click

I made a site that has graphical 3d made by three.js.

It has so many square box and user can add more boxes.

When user double clicks the scene anywhere the box will be added dynamically at that point. (mouse cursor's point)

My code is here:

// Define Variables
var myElement = document.getElementById("threejs");
let camera, scene, renderer;
const mouse = new THREE.Vector2();
const clickMouse = new THREE.Vector2();
const target = new THREE.Vector2();
const windowHalf = new THREE.Vector2( window.innerWidth / 2, window.innerHeight / 2 );
const moveState = {forward: 0, back: 0};
const moveVector = new THREE.Vector3( 0, 0, 0 );


onMouseMove = (event) => {
  mouse.x = ( (event.clientX/2) - (windowHalf.x/2) );
  mouse.y = ( (event.clientY/2) - (windowHalf.y/2) );

}

onResize = (event) => {
  const width = window.innerWidth;
  const height = window.innerHeight;

  windowHalf.set( width / 2, height / 2 );

  camera.aspect = width / height;
  camera.updateProjectionMatrix();
  renderer.setSize( width, height );
}

init = () => {
  camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1500 );
  camera.position.x = 0;
  camera.position.y = 0;
  camera.position.z = 200;

  scene = new THREE.Scene();

  const geometry = new THREE.BoxBufferGeometry();
  const material = new THREE.MeshNormalMaterial({ transparent: true });

  const object = new THREE.Mesh( geometry, material );
  object.position.x = Math.random() * 80 - 40;
  object.position.y = Math.random() * 80 - 40;
  object.position.z = Math.random() * 80 - 40;
  scene.add(object);

  renderer = new THREE.WebGLRenderer( { antialias: true } );
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  // Event handler
  document.addEventListener('mousemove', onMouseMove, false);
  document.addEventListener('dblclick', onClickScene, false);
  window.addEventListener('resize', onResize, false);


  function onClickScene(event) {
    clickMouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    clickMouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    console.log(clickMouse.x);

    const test = new THREE.Mesh( geometry, material );
    test.position.x = clickMouse.x;
    test.position.y = clickMouse.y;
    scene.add(test);
  }

  animate = () => {
    // For camera follow mouse cursor
    target.x = ( 1 - mouse.x ) * 0.002;
    target.y = ( 1 - mouse.y ) * 0.002;
    camera.rotation.x += 0.05 * ( target.y - camera.rotation.x );
    camera.rotation.y += 0.05 * ( target.x - camera.rotation.y );

    if(isMobile) {
      controls.update();
    }
    switch(hold) {
      case 1:
        camera.position.z -= 2;
        break;
      case 3:
        camera.position.z += 2;
        break;
    }
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
  }
  // Run
  animate();
}
// Run
init();

Look at the function onClickScene(event) .

I defined:

clickMouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
clickMouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
console.log(clickMouse.x);

const test = new THREE.Mesh( geometry, material );
test.position.x = clickMouse.x;
test.position.y = clickMouse.y;
scene.add(test);

So when I double click the scene, mouse point's x value and y value was printed to console.

And it's value is depend on scene's location.

But when I double click the scene, object created at same location.

I want to make object at the double clicked scene's location.

Why object created at the same position?

Is there any solution to this?

Thanks.

Object is created at the same position because you assign window plane coordinates. You probably want to raycast from mouse position to a plane https://threejs.org/docs/#api/en/core/Raycaster .

( event.clientX / window.innerWidth ) * 2 - 1

These are the coordinates on a 2D window, not in your 3D scene. Take a look at this example https://threejs.org/examples/?q=voxel#webgl_interactive_voxelpainter .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM