gkjohnson / three-mesh-bvh

A BVH implementation to speed up raycasting and enable spatial queries against three.js meshes.
https://gkjohnson.github.io/three-mesh-bvh/example/bundle/raycast.html
MIT License
2.53k stars 265 forks source link

SkinnedMesh acceleratedRaycast #547

Open ashconnell opened 1 year ago

ashconnell commented 1 year ago

In Three v0.152.0 they introduced a raycast method on SkinnedMesh (see: https://github.com/mrdoob/three.js/pull/25791)

This causes it to no longer inherit the three-mesh-bvh accelerated raycast added to Mesh.

I changed my setup from:

// Add the extension functions
THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
THREE.Mesh.prototype.raycast = acceleratedRaycast;

To this:

// Add the extension functions
THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
THREE.Mesh.prototype.raycast = acceleratedRaycast;
THREE.SkinnedMesh.prototype.raycast = acceleratedRaycast;

And it seems to have fixed the slow raycasting issues I was having.

Does it make sense for this to be the new setup in the README? If so, I will make a PR.

gkjohnson commented 1 year ago

Hello! Can you explain your use case? The BVH generated by computeBoundsTree is static with no bone transforms applied so it's never been intended to be used with SkinnedMesh.

ashconnell commented 1 year ago

In our virtual world platform people can drop GLTF models into the world in realtime, including avatars.

Before placing them in the world, every mesh calls .computeBoundsTree() so that our gaze and camera bumper raycasts are ultra fast.

This also included SkinnedMeshes since they extend Mesh. We only generate a BVH once for these though, which means its only approximate but is "good enough".

Now that ThreeJS has added a raycast method to SkinnedMesh, our code continues to work but whenever you look at a SkinnedMesh the performance tanks hard because it no longer inherits the accelerated raycast from three-mesh-bvh.

makc commented 1 year ago

@ashconnell you could as well do

THREE.SkinnedMesh.prototype.raycast = function(){};

since what you did will not produce correct result any way

gkjohnson commented 1 year ago

I'd be hesitant to imply this is supported at all since there are common cases where the result will not at all be correct such as when the bone skeleton is rotated 90 degrees from the original model pose or significantly offset. I'm happy to leave this open in case others have thoughts but I think for the moment this has to be an unsupported expert use case / workaround.