Convex collider hit another convex collider makes the screen froze

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.

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 (9.9 KB)

Here is the video

Which cannon is used by react-three-cannon? In the past I’ve used cannon-es and it has specific requirement for convex shapes (see the one that is in bold):

ConvexPolyhedron

A set of polygons describing a convex shape.

The shape MUST be convex for the code to work properly. No polygons may be coplanar (contained in the same 3D plane), instead these should be merged into one polygon.

https://pmndrs.github.io/cannon-es/docs/classes/ConvexPolyhedron.html

Hey Parvel,

Thanks for replying. I use the useConvexPolyhedron hook from react three cannon to build the collider tho. Basically, I add the convexpolyhedron collider to every mesh of the object.

I just tried to lower the vertices of the mesh geometry and it become more smooth, But still seems a bit stuck. Not sure is just this reason.

The docs you posted seems really useful I will check for a bit.

You may temporarily use box shapes instead of convex shapes. If the program freezes again, then the problem is not in the shape, but in the program logic. If it works fine with a box, then the convex shape is not OK.

I tested before. if box-convex collide, it’s all good. Also, shpere-convex collide is good as well.
Just convex-convex cause the slowly issue. :smiling_face_with_tear:

So, it is not freezing. Something with the convex shape is slowing down. Either it does not follow the cannon requirements, or the shape is simply too complex. When I use convex shapes, I see no slowing down:

In my case there are 32 convex shapes, but each shape has around 20 vertices and 15 faces. How many vertices/shapes are generated by SimplifyModifier? If you force the modifier to make very simple shapes, will it work faster?

1 Like