Search code examples
three.jsgame-physicscannon.js

Cannon.js - How to prevent jittery/shaky blocks?


I'm using Cannon.js with Three.js. I have set a scene which has 5 columns of 4 blocks stacked on top of each other.

I want these to be interactable with other objects I'm planning on adding to the scene. However, the blocks in the columns seem to be causing lots of micro-collisions and over time, jitter out of position. I want them to stay exactly in line until they're interacted with.

If you view the codepen and wait for about 20/30 seconds you'll see the blocks start to move. Is there something specific I need to set on these blocks to prevent this from happening?

Here is an example I've put together - https://codepen.io/danlong/pen/XxZROj

As an aside, there's also quite a big performance drop when there are these blocks in the scene which I wasn't expecting. I plan to add more objects to the scene and not sure why the performance drops?

Is it something to do with the below in my animate() loop?

this.world.step(1 / 30);

Code specifically to set up my 'Cannon world' and 'columns' is below:

Cannon World:

this.world = new CANNON.World();

this.world.defaultContactMaterial.contactEquationStiffness = 1e6;    
this.world.defaultContactMaterial.contactEquationRegularizationTime = 3;

this.world.solver.iterations = 20;

this.world.gravity.set(0,-25,0);

this.world.allowSleep = true;

this.world.broadphase = new CANNON.SAPBroadphase(this.world);

Columns:

var geometry = new THREE.BoxBufferGeometry(5,5,5);
var material = new THREE.MeshNormalMaterial();
var shape = new CANNON.Box(new CANNON.Vec3(5/2, 5/2, 5/2));

for (var rows = 0, yPos = 2.5; rows < 4; rows++, yPos+=5) {

    for (var i = -20; i <= 20; i+=10) {

        // physics
        var body = new CANNON.Body({
            mass: 0.5,
            position: new CANNON.Vec3(i, yPos, 0),
            friction: 0.1,
            restitution: 0.3
        });

        body.allowSleep = true;
        body.sleepSpeedLimit = 0.01;
        body.sleepTimeLimit = 1.0;

        body.addShape(shape);

        this.world.addBody(body);
        this.bodies.push(body);

        // material
        var mesh = new THREE.Mesh(geometry, material);

        this.scene.add(mesh);
        this.meshes.push(mesh);
    }
}

Solution

  • Try this? body.sleepSpeedLimit = 1.0;