Richard Mansell
Richard Mansell

Reputation: 91

ray.interstectObjects not intersecting correctly after geometry is dynamically modified

My ray.intersectObjects works really well with the objects in my scene until I dynamically modify the geometry of the object. Although the renderer is showing the objects as being modified (vertices moved and faces changed), when an intersect is tried on the modified object, it produces strange results. I need the intersect to work even on the modified geometry!

To help debug and track how the intersect is working in my scene, I've added a function: makeMiniSphere(). This makes a new sphere object in the scene at the point where the intersection occurs. Using this, you can see that after the cube is modified, sometimes the intersect hits the cube and sometimes it goes right through (mostly the faces that have been modified). It isn't a random problem, but the more you click around the modified cube, the more you can see a pattern develop. It is almost as if the renderer for the visuals of the scene know which direction the cube was modified, but the ray.intersectObjects thinks that it has been modified in a different direction!

Here is a link to the test website: http://www.littledrop.net/html/cadiverse/HelloWorld.html

Directions to show problem:

  1. Left click on cube to show intersect points. Mini spheres will be created wherever Three.js sees an intersect. The color of the selected object will change to yellow if not already selected.

  2. Click on any face of the cube. This will A. Turn it yellow if it isn't already yellow. B. It will select the face of the cube, although the selected face won't look any different from the rest of the cube.

  3. Press the "Right" arrow key to move the selected face to the right. This will dynamically change the geometry of the cube.

Now try to click on the cube--especially in the area that it has been modified. Again the Mini spheres will show where the software thinks the intersects are occurring.

Here is the intersect code:

function onDocumentMouseDown (event)
{
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
//event.preventDefault();   
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
document.getElementById('message1').innerHTML = window.innerHeight;
var isinworkingarea = window.innerHeight-menubarh;

if (event.clientY<=isinworkingarea)
{
    var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
    projector.unprojectVector( vector, camera );
    //var ray = new THREE.ReusableRay();
    var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
    // create an array containing all objects in the scene with which the ray intersects
    //  use this to select anything in the scene: 
    var intersects = ray.intersectObjects( scene.children );
    if ( intersects.length > 0 )
    {
        if (cadjectNow)
            cadjects[cadjectNow].material.color.setHex(cadjects[cadjectNow].oldColor);
        if (intersects[0].object.cadNum)                                                
            cadjectNow = intersects[0].object.cadNum;
        SELECTEDface=intersects[0].face;
        if (cadjectNow)
            cadjects[cadjectNow].material.color.setHex( selectColor );
        document.getElementById('message1').innerHTML = cadjects[cadjectNum].cadNum;

        ///// Information about selected /////
        var facestring = intersects[0].face.a  + " " + intersects[0].face.b + " " + intersects[0].face.c;
        if(intersects[0].face instanceof THREE.Face4) 
        {
            facestring=facestring + " " + intersects[0].face.d;
        }

        copyGeometry=cadjects[cadjectNow].geometry;
        //makeCopy(copyGeometry,cadjects[cadjectNow].position.x,cadjects[cadjectNow].position.y,cadjects[cadjectNow].position.z);
        makeMiniSphere(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z);

        document.getElementById('message1').innerHTML = facestring;
        //document.getElementById('message2').innerHTML = cadjects[cadjectNow].geometry.vertices[SELECTEDface.a].x + " " + cadjects[cadjectNow].geometry.vertices[intersects[0].face.a].y + " " + cadjects[cadjectNow].geometry.vertices[intersects[0].face.a].z;
        document.getElementById('message2').innerHTML = intersects[0].point.x + " " + intersects[0].point.y + " " + intersects[0].point.z;

    }
}
}

Here is the modify code:

if ( keyboard.pressed("right"))
{
    document.getElementById('message1').innerHTML = mouseMode;
    cadjects[cadjectNow].geometry.vertices[SELECTEDface.a].x+=10;
    cadjects[cadjectNow].geometry.vertices[SELECTEDface.b].x+=10;
    cadjects[cadjectNow].geometry.vertices[SELECTEDface.c].x+=10;
    if(SELECTEDface instanceof THREE.Face4) 
    {
        cadjects[cadjectNow].geometry.vertices[SELECTEDface.d].x+=10;
    }
    cadjects[cadjectNow].geometry.verticesNeedUpdate = true;
    cadjects[cadjectNow].geometry.elementsNeedUpdate = true;
    cadjects[cadjectNow].geometry.normalsNeedUpdate = true;
}

Thank you to everyone who has posted past questions and given the answers. By perusing past questions, I've been able to get this far---so you guys have already been a great help. Thanks in advance for help on this one. (As this is my first question to post here, any suggestions on how to better present a question are also more than welcome.)

Update (3/21/13)--I've migrated to r57 as suggested and the updated code is shown above. I've also debugged it so that it is working at least as well as it was before. So now the geometry is still visually being changed dynamically, but the intersect is not detecting the change properly. Thanks @WestLangley for the encouraging posts so far.

Upvotes: 2

Views: 2627

Answers (2)

Reimund
Reimund

Reputation: 2375

I was having a similar issue with a modified BufferGeometry.

I got raycasting working by calling geometry.computeBoundingSphere() and geometry.computeBoundingBox() after modifying the array with vertex positions.

Setting verticesNeedUpdate was not needed.

Running r112.

Upvotes: 1

Richard Mansell
Richard Mansell

Reputation: 91

Now working correctly. Here is how I did it (thanks to Westlangley for guidance).

  1. Upgrade Three.js to latest revision (r57 from r49).
  2. Migrate my present code to work with r57.
  3. Remove all former code attempting to update the object.
  4. Added the following code to "modify object" section:

    cadjects[cadjectNow].geometry.verticesNeedUpdate = true; cadjects[cadjectNow].geometry.normalsNeedUpdate = true; cadjects[cadjectNow].geometry.computeFaceNormals(); cadjects[cadjectNow].geometry.computeVertexNormals(); cadjects[cadjectNow].geometry.computeBoundingSphere();

Upvotes: 7

Related Questions