3
votes

I'm using version 68 of three.js.

I would like to click somewhere and get the X, Y, and Z coordinates. I followed the steps here, but they give me a Z value of 0: Mouse / Canvas X, Y to Three.js World X, Y, Z

Basically, if I have a mesh in the scene, and I click in the middle of it, I'm hoping to be able to calculate the same values as the position of that mesh. This is just an example. I know I could use raycasting and see if I collided with a mesh and then just check its position. However, I want this to work even if I didn't click a mesh.

Is this possible? Here is a jsfiddle: http://jsfiddle.net/j9ydgyL3/

In that jsfiddle, if I could manage to click in the center of that square, I'm hoping to calculate 10, 10, 10 for the X, Y, and Z values respectively because those are the coordinates of the square's position. Here are the two functions of concern:

function getMousePosition(clientX, clientY) {
    var mouse2D = new THREE.Vector3();
    var mouse3D = new THREE.Vector3();
    mouse2D.x = (clientX / window.innerWidth) * 2 - 1;
    mouse2D.y = -(clientY / window.innerHeight) * 2 + 1;
    mouse2D.z = 0.5;
    mouse3D = projector.unprojectVector(mouse2D.clone(), camera);
    return mouse3D;
    //var vector = new THREE.Vector3(
    //( clientX / window.innerWidth ) * 2 - 1,
    //- ( clientY / window.innerHeight ) * 2 + 1,
    //0.5 );

    //projector.unprojectVector( vector, camera );
    //var dir = vector.sub( camera.position ).normalize();
    //var distance = - camera.position.z / dir.z;
    //var pos = camera.position.clone().add( dir.multiplyScalar( distance ) );
    //return pos;
}

function onDocumentMouseUp(event) {
    event.preventDefault();

    var mouse3D = getMousePosition(event.clientX, event.clientY);
    console.log(mouse3D.x + ' ' + mouse3D.y + ' ' + mouse3D.z);
}

I left some of the other code I tried commented out. Please note that this commented-out code didn't work in the jsfiddle website, maybe because they're still using version 54 of three.js. It works fine on my machine with version 68.

Edit: To clarify, I would like to be able to get the coordinates no matter where the mouse is. I just used a mesh in this example because it's easy to verify if it works by seeing if the calculated coordinates are the same as the mesh's. What I would really like is for it to work without using raycasting on a mesh. For example, we could have it always printing the calculated coordinates to the console every time the mouse moves, no matter what is in the scene.

1
How are you going to find the Z coordinate without something like a mesh to click on? It could be anywhere from -Inf to +Inf. You really need something in there which provides coordinates to test for, and as per the answer you'd use the raycaster to check that.Leeft
@Leeft I'm not sure, that's why I asked if it's possible. if it really isn't possible, then feel free to post it as an answer and I'll accept it =)Programmer_D

1 Answers

1
votes

You should use a THREE.Raycaster for this. When you set a list of intersectObjects you will be able to get an array of objects that intersected with the ray. So you can get the position from the 'clicked' object from returned list. Check the updated fiddle here. I also changed your Three.js to version R68

For more advanced use of THREE.RayCaster check the examples at Threejs.org/examples like this example with interactive cubes.

Relevant code from the updated fiddle:

function getMousePosition(clientX, clientY) {
    var mouse2D = new THREE.Vector3();
    var mouse3D = new THREE.Vector3();
    mouse2D.x = (clientX / window.innerWidth) * 2 - 1;
    mouse2D.y = -(clientY / window.innerHeight) * 2 + 1;
    mouse2D.z = 0.5;
    mouse3D = projector.unprojectVector(mouse2D.clone(), camera);
    return mouse3D;
    var vector = new THREE.Vector3(
    (clientX / window.innerWidth) * 2 - 1, -(clientY / window.innerHeight) * 2 + 1,
    0.5);

    projector.unprojectVector(vector, camera);
    var dir = vector.sub(camera.position).normalize();
    var distance = -camera.position.z / dir.z;
    var pos = camera.position.clone().add(dir.multiplyScalar(distance));
    return pos;
}

function onDocumentMouseUp(event) {
    event.preventDefault();

    var mouse3D = getMousePosition(event.clientX, event.clientY);
    console.log(mouse3D.x + ' ' + mouse3D.y + ' ' + mouse3D.z);

var vector = new THREE.Vector3( mouse3D.x, mouse3D.y, 1 );    
    raycaster.set( camera.position, vector.sub( camera.position ).normalize() );

    var intersects = raycaster.intersectObjects(scene.children );
    if(intersects.length > 0){
        console.log(intersects[0].object.position);
    }
}

function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    renderer.render(scene, camera);
}