pmndrs / use-cannon

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

Convex collider hit another convex collider makes the screen froze #435

Open Charles19901210 opened 1 year ago

Charles19901210 commented 1 year ago

Hey,

Now I am applying the react-three-cannon to do the collision.

I grab a object to hit another object. After two objects collided, the collide events were triggered. But after that, it became really slow when I try to move the first person camera. Seems like jump into loop.

This two objects are all using useConvexPolyhedron from react three cannon to create convex colliders. At first,I have the error that "Cannot read property 'x' of undefined".

But After I use the Quickhull.js provided on the other master to create the face value, It's alright.

Although it still performance too bad after two objects hit together. Did anyone face this before and have some solutions or suggestions for it ?

It will be a good help for me, Thanks!

I will attached code snippet and Quickhull.js file.

Code snippet

const getCollide = (child, transform) => {
      console.log(child.geometry.attributes.position);
      console.log(child.geometry.attributes.position.count);

      let geo = child.geometry.clone();
      const modifier = new SimplifyModifier();

      const count = Math.floor(
        geo.attributes.position.count < 500
          ? 0
          : geo.attributes.position.count > 500 &&
            geo.attributes.position.count < 2500
          ? geo.attributes.position.count * 0.05
          : geo.attributes.position.count > 2500 &&
            geo.attributes.position.count < 5000
          ? geo.attributes.position.count * 0.1
          : geo.attributes.position.count > 2500 &&
            geo.attributes.position.count < 5000
          ? geo.attributes.position.count * 0.15
          : geo.attributes.position.count > 5000 &&
            geo.attributes.position.count < 15000
          ? geo.attributes.position.count * 0.18
          : geo.attributes.position.count > 15000 &&
            geo.attributes.position.count < 30000
          ? geo.attributes.position.count * 0.2
          : geo.attributes.position.count > 30000 &&
            geo.attributes.position.count < 40000
          ? geo.attributes.position.count * 0.4
          : geo.attributes.position.count > 40000 &&
            geo.attributes.position.count < 45000
          ? geo.attributes.position.count * 0.5
          : geo.attributes.position.count > 45000
          ? geo.attributes.position.count * 0.6
          : geo.attributes.position.count * 0.7
      ); // number of vertices to remove
      geo = modifier.modify(geo, count);

      const geometry = new Geometry().fromBufferGeometry(geo);

      // Apply parentTransform to the geometry
      geometry.applyMatrix4(transform);

      geometry.translate(child.position.x, child.position.y, child.position.z);
      geometry.scale(child.scale.x, child.scale.y, child.scale.z);
      geometry.scale(scale[0], scale[1], scale[2]);
      geometry.rotateX(child.rotation._x);
      geometry.rotateY(child.rotation._y);
      geometry.rotateZ(child.rotation._z);

      geometry.computeFaceNormals();
      geometry.computeFlatVertexNormals();
      geometry.computeVertexNormals();

      const vertices = geometry.vertices.map((v) => new Vector3().copy(v));
      const faces = QuickHull.createHull(vertices);

      return (
        <CollideModelMesh
          id={id}
          position={position}
          rotation={rotation}
          scale={scale}
          gltf={gltf}
          args={[vertices, faces]}
          triggerClick={triggerClick}
          hasBehaviours={hasBehaviours}
          grabPosition={grabPosition}
        />
      );
    };
const CollideModelMesh = ({
  id,
  position,
  rotation,
  scale,
  gltf,
  args,
  triggerClick,
  hasBehaviours,
  grabPosition,
}) => {
  const [ref, api] = useConvexPolyhedron(() => ({
    type: "Dynamic",
    position: position,
    rotation: rotation,
    scale: scale,
    args: args,
    onCollide: (e) => {
      console.log("hit");
      console.log(id);
      if (hasBehaviours) {
        triggerClick();
      }
    },
  }));

  useEffect(() => {
    api.velocity.set(grabPosition[0], grabPosition[1], grabPosition[2]);
  }, [grabPosition]);

  return (
    <>
      {gltf && (
        <mesh
          ref={ref}
          position={position}
          rotation={rotation}
          scale={scale}
          castShadow
          receiveShadow
        >
          <primitive object={gltf.scene} />
        </mesh>
      )}
    </>
  );
};

QuickHull.zip

Here is the link to check the video https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExanJxdjVxd2hucnZoazBjMDRvenNpb2Zvem1ybzdiMWFlc2Fqcnd0cyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/zXnOyKRopV9qSCmWzg/giphy-downsized-large.gif