mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.47k stars 35.36k forks source link

Raycacting on moving instances of InstancedMesh doesn't work anymore #29349

Closed Robpayot closed 1 month ago

Robpayot commented 1 month ago

Description

Hello,

When raycasting an InstancedMesh using raycaster.intersectObject(instancedMesh) and moving an instance it doesn't work anymore.

Weirdly it is only working if the instance was already intersecting with the Raycaster at the creation of the InstancedMesh.

It used to work well in previous versions, I have 2 jsfiddle with the exact same code, version 168 is not triggering and version 149 is working well (see logs)

Reproduction steps

  1. Create an InstancedMesh, and a Raycaster in the direction of the mesh
  2. Offset the position mesh
  3. Move instance mesh on update
  4. check intersections raycaster.intersectObject(instancedMesh) on update
  5. intersections are not triggered

Live example

Version 168 (not working) https://jsfiddle.net/zfpyg64c/ Version 149 (working) https://jsfiddle.net/ugkv8zcq/

Mugen87 commented 1 month ago

Since r151, InstancedMesh supports bounding volume computation. When you transform instances, you have to make sure to recompute bounding volumes via:

mesh.computeBoundingSphere();
mesh.computeBoundingBox();

Otherwise things like raycasting or view frustum culling won't properly work. It's the same like transforming the position attribute of geometries. In this case, you also have to recompute bounding volumes so they reflect the new state of the geometry data.

Robpayot commented 1 month ago

@Mugen87 adding computeBoundingSphere() and computeBoundingBox() after changing the matrix made the fix, thanks!

But it seems to me that calling these at every render should impact the performance more than the previous versions right?

Mugen87 commented 1 month ago

The methods are fast so the additional performance overhead should be minor. Besides, the previous version of InstancedMesh had view frustum culling disabled and ray casting was slower as well (because there was no early out testing with bounding volumes). Overall, it should be the more correct approach than previously.

If you still have performance considerations, you can manually set the bounding volumes once to a large size so the transformed instanced are always enclosed by them. However, the performance of other logic in the engine (like view frustum culling or raycasting) could be affected by this approach.