pmndrs / use-cannon

👋💣 physics based hooks for @react-three/fiber
https://cannon.pmnd.rs
2.73k stars 153 forks source link

Rotation reset when useTrimesh deps change #388

Closed pfarnach closed 2 years ago

pfarnach commented 2 years ago

I can't say for certain this is the cause of the issue but it seems like when the useTrimesh hook (and possibly others) receives updated deps, the current rotation (api.rotation) is overwritten/reset. In this repro demo, there's a plane that is rotated every frame via useFrame(...). In the demo, clicking the plane generates a new geometry which is then passed into the useTrimesh hook's deps array. Often, but not always, this will flash the updated geometry at the default rotation for one frame before being set to the correct rotation again on the next frame via useFrame(...).

If this is the intended functionality, what's the best way to avoid the jitter?

FF 100.0

https://user-images.githubusercontent.com/8879452/170170756-55925e22-aec9-423e-8f12-b246979618e5.mov

mz8i commented 2 years ago

I think this is the intended functionality. A new body's state depends only on the object returned inside the useTrimesh call. But that object can actually contain a position, rotation etc. To overcome the jitter, you can save the rotation in a ref and restore it when the body is recreated. Like so:

  const rotationRef = useRef<Triplet>([0, 0, 0]);

  const [physicsRef, api] = useTrimesh(
    () => ({
      args: [geometry.attributes.position.array, geometry.index.array],
      type: 'Kinematic',
      rotation: rotationRef.current // restoring rotation here
    }),
    undefined,
    [geometry],
  )

  useFrame(({ clock }) => {
    const t = clock.getElapsedTime();
    const rotation : Triplet = [Math.cos(t * 0.5) * 0.1, 0, Math.sin(t * 0.5) * 0.1];
    rotationRef.current = rotation; // saving rotation here to restore later

    api.rotation.set(...rotation)
  })

Note that doing the same with a quaternion instead of rotation doesn't work currently. It's a bug that I've bumped recently into and am about to file.

pfarnach commented 2 years ago

Thanks, that helps a lot! I'm not sure why I didn't think to pass a ref into the rotation but that does avoid the issue.