Verlet Physics: Help!
Greeting all,
I've been trying to implement some Verlet physics stuff, as described in the "Advanced Character Physics" article.
The problem I've come across is this:
For test purposes, I just create a tetrahedron with a particle at each corner and joined together by infinitely stiff springs. Gravity is then applied at each particle and collision is done with a ground plane. My simple algo goes as follows:
-> Update the positions of the 4 particles using Verlet integration.
-> See if any of the particles are below the ground plane, if so, project
them out (using the ground plane normal).
-> Satisfy the 6 stick constraints which hold them together.
-> Render the particles as points and the stick constraints as lines.
-> Repeat the above steps in a loop.
Now this all seems to work fine at first; the tetrahedron hits the ground and rotates a bit, slowing down. However it never completely slows down and keeps spinning slowly.
I think that this is caused by the satisfying of the stick constraints, whereby a stick constraint "pulls" on a particle which is not constrained, which in turn causes its neighbour to be pulled and so on. I've been at this for quite some time now, and have no clue as to how to solve this. I wonder how it works in Hitman and other games using the Verlet system. If anyone knows how to solve this or has any ideas, please help.
Thanks in advance,
Francis Xavier
Thanks for the reply. Well, no, I actually don't. But my integrator looks like this:
So with this I expect it to come to a halt after some time. Or is there something glaringly wrong in this code?
[Edited by - FrancisXavier on January 17, 2005 11:10:08 AM]
void RigidBody::IntegratePositions(float dt){ const float Kd = 0.99f; // Damping constant // Integrate the particles' positions FLOAT3 tmpPos; for(int i=0; i < m_numBasicParticles; i++) { tmpPos = m_p.pos; m_p.pos = m_p.pos + (m_p.pos - m_p.prevPos) * Kd + m_p.Force * m_p.invMass * dt * dt; m_p.prevPos = tmpPos; // Clear out the force m_p.Force = FLOAT3(0.0f); }}
So with this I expect it to come to a halt after some time. Or is there something glaringly wrong in this code?
[Edited by - FrancisXavier on January 17, 2005 11:10:08 AM]
Your code looks fine. I've also experienced the same "drift" implementing this method. The simple solution is to just put the rigid body to sleep once the sum of energy/velocity of all the particles falls below a threshold. Also, make sure you include some sort of friction in your collision response - this will help (one way is to compute the velocity at the time of the collision, then split it into collision plane parallel/perpendicular components. Scale the parallel component by some friction coefficient < 1, and reflect the perpendicular component by some elasticity < 1. Re-combine the components, then update the previous position to assign this new velocity).
Here's a verlet paper that describes the same method, but also applies it to the "orientation" of the particle too (so you only need one particle to simulate a rigid body).
http://www.gdconf.com/archives/2004/baltman_rick.pdf
The math turns outs to be faster (but slightly more complicated) than just using 4 particles + 6 stick constraints. If you read the paper, it also describes the "drift" problem in more detail and shows you the equations to solve it.
[Edited by - sbroumley on January 17, 2005 7:24:16 PM]
Here's a verlet paper that describes the same method, but also applies it to the "orientation" of the particle too (so you only need one particle to simulate a rigid body).
http://www.gdconf.com/archives/2004/baltman_rick.pdf
The math turns outs to be faster (but slightly more complicated) than just using 4 particles + 6 stick constraints. If you read the paper, it also describes the "drift" problem in more detail and shows you the equations to solve it.
[Edited by - sbroumley on January 17, 2005 7:24:16 PM]
Thanks for the reply. I tried putting the rigid body to "sleep" when its movement was negligent, but I couldn't get it right. Then thing is, what basis do I use for putting the rigid body to "sleep" and "waking" it up?
-> I tried putting it to sleep when the changes in position were minor. But this leads to the object going to sleep sometimes prematurely. Eg. If I throw the rigid body up, just before it begins to fall down, it goes to sleep in the air.
-> Using the above method itself, I tried decreasing the "sleep" threshold. But the above problem was still there in some cases. Also, while on the ground, the drift was large enough to overcome "sleeping" when the threshold was too small.
-> Then I tried looking at the engergy (force) of the object along with the position. But the problem there was that gravity is always acting on the object, so the energy of the object will always be some value greater than the threshold value for "sleeping". Also this is not such a good method because, suppose some other forces are acting on the object also, then the energy of the object is great, but it's not supposed to move. An example of this is stacking.
I'm sure many of you guys have implemented simple verlet systems. Didn't anyone run into this problem caused by the stick constraints before?
-> I tried putting it to sleep when the changes in position were minor. But this leads to the object going to sleep sometimes prematurely. Eg. If I throw the rigid body up, just before it begins to fall down, it goes to sleep in the air.
-> Using the above method itself, I tried decreasing the "sleep" threshold. But the above problem was still there in some cases. Also, while on the ground, the drift was large enough to overcome "sleeping" when the threshold was too small.
-> Then I tried looking at the engergy (force) of the object along with the position. But the problem there was that gravity is always acting on the object, so the energy of the object will always be some value greater than the threshold value for "sleeping". Also this is not such a good method because, suppose some other forces are acting on the object also, then the energy of the object is great, but it's not supposed to move. An example of this is stacking.
I'm sure many of you guys have implemented simple verlet systems. Didn't anyone run into this problem caused by the stick constraints before?
Sorry - by energy I meant kinetic energy (0.5 * Mass * VelocitySquared), not force.
To avoid the body freezing in the air at the top of an arc, simply increment a timer when the velocity/energy is below your threshold, and set it to zero when it's not. Then - only freeze the body when the timer has reached say 2 seconds or something. You could also add other conditions into the freezing, like only freeze if there is a contact etc.
To wake up the body, clear the "frozen" flag and set the timer to zero in any function that applies an impulse to the body (eg. from an explosion or something).
For games, it's all about cheating :)
BTW - I have used this method successfully in Midway's first-person-shooter Area51 (coming soon).
[Edited by - sbroumley on January 17, 2005 9:35:15 PM]
To avoid the body freezing in the air at the top of an arc, simply increment a timer when the velocity/energy is below your threshold, and set it to zero when it's not. Then - only freeze the body when the timer has reached say 2 seconds or something. You could also add other conditions into the freezing, like only freeze if there is a contact etc.
To wake up the body, clear the "frozen" flag and set the timer to zero in any function that applies an impulse to the body (eg. from an explosion or something).
For games, it's all about cheating :)
BTW - I have used this method successfully in Midway's first-person-shooter Area51 (coming soon).
[Edited by - sbroumley on January 17, 2005 9:35:15 PM]
Hey that's major cool info, thanks. I never thought of doing it like that. Also, you've successfully implemented it in Area51, eh? Then I've definitely got to check the game out. I love 'em physics based games.
I'll try and implement that now, and if I still can't get it right, I'll come back to trouble you some more. :)
Thanks again,
Francis Xavier
I'll try and implement that now, and if I still can't get it right, I'll come back to trouble you some more. :)
Thanks again,
Francis Xavier
No problem, anytime.
Yes for Area51 I originally implemented the ragdoll using Jackobsen's method (don't be fooled by the paper - it may look simple, but wait until you get to the rotational constraints!).
I actually re-wrote the final ragdoll in Area51 using an impulse method based on this paper (and lot's of help from Danny Chapman - MrRowl ):
http://www.cs.ubc.ca/~rbridson/docs/rigid_bodies.pdf
Believe it or not, it turns out that the constraints are much easier to code using the impulse method and the results are much more realistic (static friction + rotation around limb axis makes ragdolls look so much better).
Still, the verlet method has proved to be nice and cheap (and it solves resting contact so elegantly) for "coke cans" and "barrels" in the game -modeled with just 2 spheres and 1 stick constraint! (rolling is faked). Also, the cloth in the game (flags etc) is done using the verlet method.
Yes for Area51 I originally implemented the ragdoll using Jackobsen's method (don't be fooled by the paper - it may look simple, but wait until you get to the rotational constraints!).
I actually re-wrote the final ragdoll in Area51 using an impulse method based on this paper (and lot's of help from Danny Chapman - MrRowl ):
http://www.cs.ubc.ca/~rbridson/docs/rigid_bodies.pdf
Believe it or not, it turns out that the constraints are much easier to code using the impulse method and the results are much more realistic (static friction + rotation around limb axis makes ragdolls look so much better).
Still, the verlet method has proved to be nice and cheap (and it solves resting contact so elegantly) for "coke cans" and "barrels" in the game -modeled with just 2 spheres and 1 stick constraint! (rolling is faked). Also, the cloth in the game (flags etc) is done using the verlet method.
Doing some more experiments at the moment. Putting the object to "sleep" does seem to give better results, but can't help feeling that it's not THE way to do it.
And whoever said it is right, using the traditional rigid body equations is easier (although I haven't managed to get resting contacts completely right). But somehow the particles and constraints approach seems to be more right.
I was just thinking, in real world physics, everything is made out of particles. And whole rigid bodies are made up of many particles all staying together due to an attractive force. So, all movement (translational and rotational) comes from the simple fact that the particles try to stay together, as they move. I think that the Verlet method is somewhat closer to this than the traditional way of doing rigid body physics.
Just some thoughts, I may / may not be right about this. This is getting pretty frustrating for me; it's been a long time now and I haven't been able to come up with a single stable implementation of rigid body physics till now. If anyone has any ideas or thoughts to share, please do! I'm all ears.
Thanks for listening,
Francis Xavier
And whoever said it is right, using the traditional rigid body equations is easier (although I haven't managed to get resting contacts completely right). But somehow the particles and constraints approach seems to be more right.
I was just thinking, in real world physics, everything is made out of particles. And whole rigid bodies are made up of many particles all staying together due to an attractive force. So, all movement (translational and rotational) comes from the simple fact that the particles try to stay together, as they move. I think that the Verlet method is somewhat closer to this than the traditional way of doing rigid body physics.
Just some thoughts, I may / may not be right about this. This is getting pretty frustrating for me; it's been a long time now and I haven't been able to come up with a single stable implementation of rigid body physics till now. If anyone has any ideas or thoughts to share, please do! I'm all ears.
Thanks for listening,
Francis Xavier
From my experiences simply damping the velocity doesn't work reliably unless you run your physics at a constant rate - otherwise if you have a small timestep (physics update gets called more often) you'll be reducing the velocity at a faster rate than if you call it less frequently (a slow framerate). Another great reason to use fixed timesteps - cheap and dodgy damping :-)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement