Raycast fails after modifying the instance matrices

Using Three 0.152.0

I got a few instances and I’m using the Raycaster on them which is working fine until I modify the instance matrices. Here’s some code to reproduce

const geometry = new THREE.IcosahedronGeometry(0.5, 3);
const material = new THREE.MeshPhongMaterial({ color: 0xffffff });

const mesh = new THREE.InstancedMesh(geometry, material, 100);
for (let x = 0; x < 100; x++) {
    let matrix = new THREE.Matrix4().identity();
    matrix.setPosition(x, 0, 0);
    mesh.setMatrixAt(x, matrix);
}

scene.add(mesh);

const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();

domContainer.addEventListener('mouseup', (e) => {
    pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
    pointer.y = - (e.clientY / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(pointer, camera);
    const intersects = raycaster.intersectObjects(scene.children);
    console.log(intersects)
});

setTimeout(()=>{
    mesh.count = 100;
    for (let x = 0; x < 100; x++) {

        let matrix = new THREE.Matrix4().identity();
        matrix.setPosition(-x, 0, 0);
    
        mesh.setMatrixAt(x, matrix);
    
    }
    mesh.instanceMatrix.needsUpdate = true;
},1000)

The instances that move via setMatrixAt are not picked up by the raycaster reliably anymore. They actually are picked up, sometimes, depending on the camera angle.

Anybody know what I’m missing?

1 Like

For anyone with the same issue, the problem is that the raycaster first checks intersection with the overall bounding sphere of the InstancedMesh so the issue is fixed with a call to InstancedMesh#computeBoundingSphere.

Seems like that could be documented or perhaps instanceMatrix.needsUpdate = true could force the bounding sphere of the InstancedMesh to be invalidated

6 Likes

Yes you are right, and it’s a global practice not exclusive to instances and raycasting
The same goes for any low-level changes or attempt to get accurate data.

  • instanceMatrix.needsUpdate = true (instance)
  • myObject.updateMatrix(); (3D object)
  • myMesh.geometry.computeVertexNormals(); (normals)
  • myMesh.geometry.attributes.position.needsUpdate = true; (vertex position)
  • myLight.target.updateMatrixWorld(); (lights target)
  • myMesh.material.map.needsUpdate = true; (material/map/texture)

…and the list goes on forever :sweat_smile: , but these ones are the usual suspects who may cause trouble if not refreshed after an edit.

1 Like

Thanks! I was having the same problem.

2 Likes