3

I have a 3D scatter plot with spheres to represent the points and I'm trying to display information from the points when clicked. Based on answers to a couple different questions here on SO, I think I'm on the right track. Here is my onCanvasMouseDown:

        event.preventDefault();
        mouse.x = ( (event.clientX - renderer.domElement.offsetLeft) / renderer.domElement.width ) * 2 - 1;
        mouse.y = - ( (event.clientY - renderer.domElement.offsetTop) / renderer.domElement.height ) * 2 + 1;
        mouse.z = 0.5;

        projector.unprojectVector( mouse, camera);
        raycaster.setFromCamera( mouse, camera);

        var intersects = raycaster.intersectObjects( scene.children );

        if( intersects.length > 0 ) {
            intersects.map(function(d) {
                if(d.object.name === "sphere") {
                           //etc...
                }
            })

        }

But intersects keeps coming back empty. I have a feeling the problem has something to do with the way I'm setting up the mouse coordinates, but I'm not sure how to resolve the issue.

EDIT: I seem to be able to find a sphere if I rotate the plot so that I am looking at it from above (but I need to be able to detect it regardless of the rotation). Does this indicate anything specific?

P.S.
  • 75
  • 1
  • 2
  • 8
  • 1
    just a note. `setFromCamera()` takes 2d mouse coords (from https://threejs.org/docs/api/core/Raycaster.html). The problem might be the `renderer.domElement.offset` so try your code without that first. – gaitat Nov 18 '16 at 01:32
  • 1
    just to make sure, have you tried logging `interects` right after it's defined, before the loop ? If not, what does it return ? – Console-buche Nov 18 '16 at 07:20
  • Returns an empty array. – P.S. Nov 18 '16 at 17:16
  • `mouse.z = 0.5;`?? In all examples about intersection I've ever seen, `mouse` is always`THREE.Vector2()`, never `THREE.Vector3()` – prisoner849 Nov 18 '16 at 22:12
  • Try to use `recursive` parameter of `intersectObjects` method: `var intersects = raycaster.intersectObjects( scene.children, true );`. – prisoner849 Nov 18 '16 at 22:28

2 Answers2

7

If your objects (points) belong to, for example, THREE.Group(), which is a child of the scene, then

var intersects = raycaster.intersectObjects( scene.children );

will give you negative result of intersection.

To reach group's children it's better to use

var intersects = raycaster.intersectObjects( scene.children, true );

Or you can try a different option: put the objects you want to check for intersection into an array and then pass the array to intersectObjects method.

var objects = [];
for(i=0; i<10; i++){
    ...
    var meshobj = new THREE.Mesh(...);
    scene.add(meshobj); // or group.add(meshobj);
    objects.push(meshobj);
}

...

var intersects = raycaster.intersectObjects( objects ); // here you don't need recursive parameter, as you have the array with objects you indeed want to check for intersection
prisoner849
  • 16,894
  • 4
  • 34
  • 68
1

if you have offset, use the the boundingRect.

var rect = renderer.domElement.getBoundingClientRect();
mouse.x = ( ( event.clientX - rect.left ) / ( rect.width - rect.left ) ) * 2 - 1;
mouse.y = - ( ( event.clientY - rect.top ) / ( rect.bottom - rect.top) ) * 2 + 1;

see the demo of my answer.

Community
  • 1
  • 1
LF00
  • 27,015
  • 29
  • 156
  • 295