CannonJs ConvexPolyhedron shape is vibrating and intersecting static bodies

I have created a Dodecahedron shape using ThreeJs and Cannon-es but the shape is intersecting and going through a static body (the ground in the animation) this is causing it to endlessly vibrate.
Like this -
image

Why is this happening is there something wrong in the code -

      const t = (1 + Math.sqrt(5)) / 2;
const r = 1 / t;

const vertices = [
  new CANNON.Vec3(-1, -1, -1),
  new CANNON.Vec3(-1, -1, 1),
  new CANNON.Vec3(-1, 1, -1),
  new CANNON.Vec3(-1, 1, 1),
  new CANNON.Vec3(1, -1, -1),
  new CANNON.Vec3(1, -1, 1),
  new CANNON.Vec3(1, 1, -1),
  new CANNON.Vec3(1, 1, 1),
  new CANNON.Vec3(0, -r, -t),
  new CANNON.Vec3(0, -r, t),
  new CANNON.Vec3(0, r, -t),
  new CANNON.Vec3(0, r, t),
  new CANNON.Vec3(-r, -t, 0),
  new CANNON.Vec3(-r, t, 0),
  new CANNON.Vec3(r, -t, 0),
  new CANNON.Vec3(r, t, 0),
  new CANNON.Vec3(-t, 0, -r),
  new CANNON.Vec3(t, 0, -r),
  new CANNON.Vec3(-t, 0, r),
  new CANNON.Vec3(t, 0, r)
];

const indices = [
  [3, 11, 7], [3, 7, 15], [3, 15, 13],
  [7, 19, 17], [7, 17, 6], [7, 6, 15],
  [17, 4, 8], [17, 8, 10], [17, 10, 6],
  [8, 0, 16], [8, 16, 2], [8, 2, 10],
  [0, 12, 1], [0, 1, 18], [0, 18, 16],
  [6, 10, 2], [6, 2, 13], [6, 13, 15],
  [2, 16, 18], [2, 18, 3], [2, 3, 13],
  [18, 1, 9], [18, 9, 11], [18, 11, 3],
  [4, 14, 12], [4, 12, 0], [4, 0, 8],
  [11, 9, 5], [11, 5, 19], [11, 19, 7],
  [19, 5, 14], [19, 14, 4], [19, 4, 17],
  [1, 12, 14], [1, 14, 5], [1, 5, 9]
];

      // Create a ConvexPolyhedron shape from the vertices and faces
      const dodecahedronShape = new CANNON.ConvexPolyhedron({
        vertices: vertices,
        faces: indices,
      })

      const dodecahedronBody = new CANNON.Body({
        mass: 2, // Set mass
        shape: dodecahedronShape,
        position: new CANNON.Vec3(x, 10, z),
        friction: -1,
        restitution: 5,
      })

code for the ground-

    const groundBody = new CANNON.Body({
      shape: new CANNON.Box(new CANNON.Vec3(15, 15, 0.1)),
      type: CANNON.Body.STATIC,
      material: groundPhysMat,
    })
    groundBody.material.friction = 1
    groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
    world.addBody(groundBody)

Physics simulations are very finicky about how they are set up. If you start an object out intersecting with the world, the physics solver can’t always figure out where to push the object to get it out of the surface, so it just makes guesses every frame, and that can result in that kind of oscillating behavior.

Also if your objects move very fast, they can move Inside an object in a single frame step, and cause the same situation. The solution is to make sure you’re objects aren’t moving so fast (lower gravity or lower the velocity… make the objects thicker so they have longer to collide with each other… OR increase the number of substeps in the physics simulation.) Getting a stable physics simulation can take a lot of tweaking.

2 Likes

I have quite limited experience with CannonES (is it the same as CannonJs?). When I used convex polyhedrons, it was important to have consistent vertex winding of all faces. When some of the faces had wrong winding, the collisions did not work well – the engine uses the face orientation to guess what is inside and what is outside an object. Are your faces well oriented?

Also, collisions were detected only when the engine had time to detect them. If an object suddenly appeared inside another object, the engine got dramatically confused (this is what @manthrax says). Sometimes the stuck objects started to oscillate, in other cases they just catapulted to infinity. It was fun to watch.

1 Like

According to our friend @manthrax , most of the time objects vibrate because they are inside another physical object, or one of the objects was created by widely spaced triangles.
try to paint a box around the ground and the object to see if they are inside each other, place the object above the ground on the y axis, it will fall with gravity.

1 Like

@manthrax , Could you please check the code, I have changed the scale of the bodies so that the bodies are not intersecting the ground but it still keeps on vibrating for the icosahedron in this code -

const t = (1 + Math.sqrt(5)) / 2;
const scaleFactor = 0.5;
const verticesIcosa = [
    new CANNON.Vec3(-1, t, 0).scale(scaleFactor), new CANNON.Vec3(1, t, 0).scale(scaleFactor),
    new CANNON.Vec3(-1, -t, 0).scale(scaleFactor), new CANNON.Vec3(1, -t, 0).scale(scaleFactor),
    new CANNON.Vec3(0, -1, t).scale(scaleFactor), new CANNON.Vec3(0, 1, t).scale(scaleFactor),
    new CANNON.Vec3(0, -1, -t).scale(scaleFactor), new CANNON.Vec3(0, 1, -t).scale(scaleFactor),
    new CANNON.Vec3(t, 0, -1).scale(scaleFactor), new CANNON.Vec3(t, 0, 1).scale(scaleFactor),
    new CANNON.Vec3(-t, 0, -1).scale(scaleFactor), new CANNON.Vec3(-t, 0, 1).scale(scaleFactor)
];

// Faces
const facesIcosa = [
    [0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11],
    [1, 5, 9], [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8],
    [3, 9, 4], [3, 4, 2], [3, 2, 6], [3, 6, 8], [3, 8, 9],
    [4, 9, 5], [2, 4, 11], [6, 2, 10], [8, 6, 7], [9, 8, 1]
];

// Create a ConvexPolyhedron shape from the vertices and faces
const icosahedronShape = new CANNON.ConvexPolyhedron({
    vertices: verticesIcosa,
    faces: facesIcosa
});


      let x = xCoordinateShared == null ? xCoordinate : xCoordinateShared
      let z = zCoordinateShared == null ? zCoordinate : zCoordinateShared
      let y = yCoordinateShared == null ? 10 : yCoordinateShared


      const icosahedronBody = new CANNON.Body({
        mass: 2, // Set mass
        shape: icosahedronShape,
        position: new CANNON.Vec3(x, y, z),
        friction: -1,
        restitution: 5,
      })

cannon convexpoly is imo not fit for production because it’s very, very slow, also buggy. in rapier you have performant hull and trimesh rigid bodies. Rapier physics - CodeSandbox you can use rapier.js in vanilla just like you use cannon.

I have quite limited experience with CannonES (is it the same as CannonJs?).

cannon-es is the maintained fork we made with pmndrs. cannon hasn’t been maintained for maybe 8-9 years, bugs aren’t fixed, pr’s aren’t merged. cannon-es merged outstanding pr’s, fixed some bugs (among them bug fixes for convexpoly), added types and a modern flatbundle. but the underlying engine is so old and slow it wouldn’t make much sense to use it much longer. we have moved focus on rapier and jolt.

2 Likes