Sleep

Official forum for the Chipmunk2D Physics Library.
Post Reply
dc443
Posts: 20
Joined: Sun Dec 02, 2007 3:54 am
Contact:

Sleep

Post by dc443 »

One thing that I've noticed is kinda lacking from this already exceedingly excellent library is some sort of sleep parameter so objects get disabled when they have reached a stable equilibrium state and are awakened when an object near it (or near an object connected to it thru a joint or constraint or even contact collision) collides with it.

I was reminded of this while running the Box2D demo, where a gigantic pyramid stack can be made to go to sleep even after you've screwed around with it. If you can get this working well with the spatial hashing, slembcke, it could provide huge performance increases for certain applications (huge environments with many many objects spread over large distances) without needing to make custom code for disabling certain parts of the simulation. I'd write something to attempt this, but i'm a noob and it would take me forever.

Also, on a somewhat related note, stacking of objects with a greater than zero elasticity seems to not be implemented; i'm sure this will be fixed/completed in due time... any suggestions for a temporary way around this limitation? In fact, it looks like this will need to be dealt with before the sleeping, otherwise sleep will only work on objects with zero elasticity...
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Sleep

Post by slembcke »

Yeah. Sleep would would definitely be an order of magnitude improvement for a lot of scenes. The problem is that it's not trivial to implement well. I had working code at one point for sleeping bodies, but waking up a bodies neighbors was never implemented. Hit the bottom box out of a pile and the rest stay floating.

I know how to fix stacking for elastic objects, the problem is how to implement it nicely. Basically you treat collisions and contacts in separate solver phases. The collision phase is basically what I'm doing now. Meant to deal with the high amounts of energy in objects when objects first collide. The contact phase is applied afterwards when most of the energy is gone. You reapply all the collision with an elasticity of zero, so that any new velocity introduced by the integration step doesn't case tiny bounce. (That's an awkward explanation of this paper: http://physbam.stanford.edu/~fedkiw/pap ... 003-01.pdf)
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
dc443
Posts: 20
Joined: Sun Dec 02, 2007 3:54 am
Contact:

Re: Sleep

Post by dc443 »

I guess you'd need some sort of way to store or keep track of a collection of objects that are in contact with one another in order to awaken them all when one of them comes out of sleep. It should be fairly simple especially if you have a special solver phase for contact. That way, moving something from under a stack will awaken the entire stack and anything touching it or connected to it, so nothing is left hanging in the air. I've also seen implementations of this where the objects don't hang, but have a sort of delay before realizing that they're floating, so that its like a cascade effect (read: unrealistic), this should take care of that too.

I guess a way to "hack it" at the moment is to change an object's elasticity to zero, except the problem with that is, if another object lands on a stationary stacked object that's supposed to have an e of 1.0, it's laying there with an e of 0.0 and the subsequent interaction won't make sense. Gotta have the elasticity done on a per-collision basis (basically from what I can tell, all you gotta do is if the collision impulse is smaller than a certain threshold just change the elasticities in that particular collision to zero)... perhaps i could implement this using a collision callback..?

Anyway, great work on the library, I'm looking forward to the updates!
dc443
Posts: 20
Joined: Sun Dec 02, 2007 3:54 am
Contact:

Re: Sleep

Post by dc443 »

Hey Scott, have you thought about this? I'm not very proficient in C or programming, but I'm looking at your cpSpaceStep function:

Code: Select all

// Run the impulse solver.
	for(int i=0; i<space->iterations; i++){
		for(int j=0; j<arbiters->num; j++)
			cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j]);
		for(int j=0; j<joints->num; j++){
			cpJoint *joint = (cpJoint *)joints->arr[j];
			joint->applyImpulse(joint);
		}
	}
okay, it would seem that what i'm looking for is in cpArbiterApplyImpulse():

Code: Select all

...
// Calculate and clamp the normal impulse.
		cpFloat jn = -(con->bounce + vrn)*con->nMass;
		cpFloat jnOld = con->jnAcc;
		con->jnAcc = cpfmax(jnOld + jn, 0.0f);
		jn = con->jnAcc - jnOld;
		
		// Calculate the relative tangent velocity.
		cpVect t = cpvperp(n);
		cpFloat vrt = cpvdot(cpvadd(vr, arb->target_v), t);
		
		// Calculate and clamp the friction impulse.
		cpFloat jtMax = arb->u*con->jnAcc;
		cpFloat jt = -vrt*con->tMass;
		cpFloat jtOld = con->jtAcc;
		con->jtAcc = cpfmin(cpfmax(jtOld + jt, -jtMax), jtMax);
		jt = con->jtAcc - jtOld;

		// Apply the final impulse.
		cpVect j = cpvadd(cpvmult(n, jn), cpvmult(t, jt));
		cpBodyApplyImpulse(a, cpvneg(j), r1);
		cpBodyApplyImpulse(b, j, r2);
...
Uh, so it looks like when the impulses are lower than some certain amount we can just set them to zero (to simulate an elasticity of zero). But gravity poses an interesting problem because we still need impulses to keep it from falling down, right? So theoretically there would never be an impulse of zero even with objects of zero elasticity because theres still a normal force equal and opposite to gravity, keeping it stationary...

So i guess I need to single out the part of the impulse which is proportional to the elasticity constant. So i scrolled up and found it in cpArbiterPreStep:

Code: Select all

		// Calculate the target bounce velocity.
		cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(con->r1), a->w));
		cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(con->r2), b->w));
		con->bounce = cpvdot(con->n, cpvsub(v2, v1))*arb->e;
You call cpArbiterPreStep inside cpSpaceStep, so i guess i missed it earlier.. I'm guessing that if I just add an if test:

Code: Select all

con->bounce = cpvdot(con->n, cpvsub(v2, v1))*arb->e;
if (abs(con->bounce) < .00001)
	con->bounce = 0;
we can perhaps end up getting some better behavior for stacking bouncy objects?

The thing is, I tried all of this and the behavior is quite weird. The friction seems to not be working correctly, and the jitter didn't go away. It still looks very unrealistic with Demo2 with all the blocks having e = 0.5..

I also found it weird that your con->bounce is a negative number a lot of the time... why is that?

edit-update: Well, the stuff will not stabilize until i changed it to like if (abs(con->bounce) < 20), but at that point it doesnt look very realistic because it just jitters a lot and then suddenly settles quickly.

edit--again: It just looks like stuff is way too bouncy when e is more than like 0.3. And if I have a stack of blocks falling down, it just seems like a huuuge amount of extra energy is added as the top ones fly back up because of the bounce...

edit...: Okay, well previously i was running it at a timestep of 1/60 second, so I changed it to 1/600 (10 per frame) and it's a bit more stable. But my if-test solution seems to be creating more random bad jitter than without it. Perhaps it's causing stuff to penetrate more. But how? How could it possibly introduce more jitter if i'm selectively setting certain contact elasticities to zero....

edit: Alright, I give up... I just simply dont have a good enough grasp of how all this stuff works.
Post Reply

Who is online

Users browsing this forum: No registered users and 27 guests