Search code examples
three.jsgame-physicscannon.js

Cannon.js - How to prevent objects clipping 'floor' on update


I'm using Cannon.js with Three.js.

I've created a scene which consists of 1 heightfield and 5 balls. I want the balls to roll around the heightfield, using the cannon.js physics.

On mouse move, I rotate the heightfield along the y-axis to make the spheres roll back and forth.

I have an update loop, which copies the sphere position & quaternion from cannon.js and applies to the visual sphere of three.js. The heightfield is also updated at the same time as the three.js visual floor. Both of these run in a for loop, in requestAnimationFrame.

updateMeshPositions() {

    for (var i = 0; i !== this.meshes.length; i++) {
        this.meshes[i].position.copy(this.bodies[i].position);
        this.meshes[i].quaternion.copy(this.bodies[i].quaternion);

        this.hfBody.position.copy(this.mesh.position);
        this.hfBody.quaternion.copy(this.mesh.quaternion);
    }
}

However, the problem is that when the 'floor' is rotating back and forth, the spheres are getting stuck and sometimes even falling through the floor. Here is an example on codepen - https://codepen.io/danlong/pen/qJwMBo

Move the mouse up and down on the screen to see this in action.

Is there a better or different way I should be rotating the 'floor' whilst keeping the sphere's moving?


Solution

  • Directly (i.e. "instantly") setting position/rotation is likely to break collision handling in all physics engines, including cannon.js . Effectively you are teleporting things through space, causing objects to get stuck in or pass through each other.

    What you should do is

    • Set the velocity (both .velocity and .angularVelocity) or apply forces to the Cannon.js bodies
    • Copy the transform of those bodies to your visual meshes (notices this is exactly the other way around of what you are currently doing in the code)

    Determining the right amount of force to apply to get the desired visual behavior is usually the tricky part.