schteppe / p2.js

JavaScript 2D physics library
Other
2.64k stars 330 forks source link

Objects overlap even when stiffness set to MAX_VALUE #202

Open leaf-node opened 8 years ago

leaf-node commented 8 years ago

When contact stiffness is set to Number.MAX_VALUE in the circles demo, there often are a few circles that overlap quite a bit, even after they've all settled down. In the restitution demo I noticed that the circle on the left is occasionally drawn intersecting with the block below it.

My hope is that these stiff objects might never overlap, overlap by very tiny amounts, or (at least) overlap for brief durations only.

diff --git a/demos/circles.html b/demos/circles.html
index 10a0a59..bacef54 100644
--- a/demos/circles.html
+++ b/demos/circles.html
@@ -47,6 +47,9 @@
             // Enables sleeping of bodies
             world.sleepMode = p2.World.BODY_SLEEPING;

+            var circleMaterial = new p2.Material();
+            world.addContactMaterial(new p2.ContactMaterial(circleMaterial, circleMaterial, {restitution: 0.1, stiffness: Number.MAX_VALUE}));
+
             // Create circle bodies
             for(var i=0; i<N; i++){
                 for(var j=M-1; j>=0; j--){
@@ -56,7 +59,9 @@
                         mass: 1,
                         position: [x, y],
                     });
-                    p.addShape(new p2.Circle({ radius: r }));
+                    var circle = new p2.Circle({ radius: r });
+                    circle.material = circleMaterial;
+                    p.addShape(circle);
                     p.allowSleep = true;
                     p.sleepSpeedLimit = 1;  // Body will feel sleepy if speed<1 (speed is the norm of velocity)
                     p.sleepTimeLimit = 1;   // Body falls asleep after 1s of sleepiness
schteppe commented 8 years ago

Hi, We all want the overlap to be as small as possible :) Even thought the stiffness has a role in this problem, the time step size is probably worse.

To move bodies forward in time, this is the formula used:

x += v * dt

Let's say you have a configuration where a body is very close to another body, but not overlapping. The body is moving towards the other body with a velocity v. Next time step, the bodies will overlap by v * dt length units, no matter the value of stiffness.

If you're lucky, your configuration will yield some smaller overlap. If you choose the time step parameter to be small, you can make the overlaps smaller.

You can also make sure to limit the velocities of things in the world (this is a common gamedev trick). For example, less gravity value will give you less speedy objects.

Related is the experimental CCD feature in p2. But this is only helps if your objects move VERY fast. What it does is choosing a time step so that the bodies move forward to the time of impact and not more. It's sequential and slow, and not energy preserving, so it's probably not a solution for you.

// CCD
x += v * timeOfImpact
leaf-node commented 8 years ago

This type of error seems fine to me, as long as I set the interval low enough.

What about cases where stacked circles occasionally overlap by ~10% when all bodies are at rest?

schteppe commented 8 years ago

That can be fixed (to some extent) by tweaking stiffness + relaxation + contactSkinSize of the contact materials. Reducing gravity also helps. Stacking problems are difficult to solve perfectly.