Reputation: 196
I'm trying to add pointer events to a GLTF file loaded in react-three-fiber using GLTFJSX. However, the pointer events don't fire, and I can't figure out why.
I have tried adding the same events into other similar code sandboxes, and it works — so why wouldn't it work in this example, if I'm doing basically the same thing?
https://codesandbox.io/s/hopeful-brook-h8rhs?file=/src/App.js
onPointerMissed
event ever fires.Sometimes, the onPointerOver
and onPointerOut
events do work. This seems to work at random — sometimes it works, but most of the time it just doesn't.
Am I missing something obvious?
When changed to mesh
, the pointer events work. So the issue is related directly to skinnedMesh
not detecting pointer events.
Upvotes: 2
Views: 4136
Reputation: 28472
The problem is that SkinnedMesh
modifies the vertex positions in the graphics card (GPU), so the JavaScript side doesn't know that the vertices have been moved when performing the hit-test (also known as Raycasting). Take a look at the screenshots below:
When you use Mesh
, the vertices show up where geometry.attributes.position
indicates. The shape is small and far away, but your mouse-events work as expected.
When you use SkinnedMesh
, the vertices are translated in the GPU to be much closer, but the raycasting calculation still uses the original geometry.attributes.position
coordinates to perform the hit-test. That's why you only get the expected mouse events in a very small area inside the red box.
The solution varies based on your use-case but you could do any of the following:
Mesh
, and update the mesh.position
property to move it closer to the camera.SkinnedMesh
, try to keep the skeleton displacements small enough so their skinned positions don't deviate far from their original positions.var hitGeom = new THREE.BoxBufferGeometry(1, 1, 1);
var hitMat = new THREE.MeshBasicMaterial({visible: false});
// ...
<mesh geometry={hitGeom} material={hitMat}>
Upvotes: 2