2

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);
    }
}
1
  • For anyone checking the Codepen, the approved solution has been implemented on line 125. Commented Mar 29, 2021 at 15:55

1 Answer 1

5

Try this? body.sleepSpeedLimit = 1.0;

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer - that worked perfectly. It also seemed to improve the performance, so thanks! I did change it to 0.5 for my scenario, but it works!
Cool :) Sleep parameter tells the physics engine that the total velocities of the objects in the sim have fallen below a threshhold and can therefor stop being simulated... as soon as something big enough collides again, causing velocities to spike above that threshhold, the sim will fire up again. This mechanism is how we can have giant simulations without having to update Every object every frame. If the threshhold is too high, you'll start to see problems with like.. objects stopping moving when standing on an edge or similar...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.