Applying Simple Joints To 2D Particles

Started by
3 comments, last by Cowboy Coder 17 years, 1 month ago
I've got my particle system nailed down and I wanted to start working on joints. My first plan was to simply make a joint that kept two particles at a set distance apart. My implementation seems logical, but the joint behaves very strange. I'm using two particles with equal mass, but one always seems to swing around the other during collisions.
public override void Update(float dt)
		{
			Vector2 d = p1.position - p2.position;

			if (d.LengthSquared() != (length * length))
			{
				//calculate each particle's "influence" on the joint
				float p1Influence = p1.mass;
				float p2Influence = p2.mass;

				//figure out the total "influence" the joint has
				float totalInfluence = p1Influence + p2Influence;

				//get the percentage of influence for both particles.
				//notice the reversal of the particle influence for
				//the percentage. this percentage is the percentage
				//of the correction distance each particle must move.
				//hence the particle with the highest influence, has the
				//lowest percentage it must move.
				float p1Percentage = p2Influence / totalInfluence;
				float p2Percentage = p1Influence / totalInfluence;

				//get the correction distance and vector
				float correctionDistance = d.Length() - length;
				Vector2 correctionVector = p1.position - p2.position;
				correctionVector.Normalize();

				//move the particles
				p1.position -= correctionVector * (p1Percentage * correctionDistance);
				p2.position += correctionVector * (p2Percentage * correctionDistance);
			}
		}
Advertisement
How are you handling the velocity change?
Quote:Original post by Cowboy Coder
How are you handling the velocity change?


I totally forgot about that. Thanks. I'll go back through and try to do it with forces.
So I tried again. I used the f=ma and p=v/t equations to come to equation f=pm/t2 (t-squared). Using this I applied it to my joint update method:

public override void Update(float dt)		{			Vector2 d = p1.position - p2.position;			if (d.LengthSquared() != (length * length))			{				//calculate each particle's "influence" on the joint				float p1Influence = p1.mass;				float p2Influence = p2.mass;				//figure out the total "influence" the joint has				float totalInfluence = p1Influence + p2Influence;				//get the percentage of influence for both particles.				//notice the reversal of the particle influence for				//the percentage. this percentage is the percentage				//of the correction distance each particle must move.				//hence the particle with the highest influence, has the				//lowest percentage it must move.				float p1Percentage = p2Influence / totalInfluence;				float p2Percentage = p1Influence / totalInfluence;				//get the correction distance and vector				float correctionDistance = d.Length() - length;				Vector2 correctionVector = p1.position - p2.position;				correctionVector.Normalize();				//apply the forces				p1.ApplyForce(-(correctionVector * (correctionDistance * p1Percentage)) * p1.mass / (dt * dt));				p2.ApplyForce(correctionVector * (correctionDistance * p2Percentage) * p2.mass / (dt * dt));			}		}


It works to a degree. It looks better than it did before, but my particles now never come to rest and actually appear to shiver. In my main physics code, I do a loop three times that first updates all the particles, checks for terrain collision, and then handles the joint problems. Any ideas where I'm going wrong?

Edit:
I've combined my methods and compensated for the fact that this is called three times per frame by making the last part into this:
				p1.position -= correctionVector * (p1Percentage * correctionDistance);				p2.position += correctionVector * (p2Percentage * correctionDistance);				p1.ApplyForce(-(correctionVector * (correctionDistance * p1Percentage)) * p1.mass / (dt * dt) / 3f);				p2.ApplyForce(correctionVector * (correctionDistance * p2Percentage) * p2.mass / (dt * dt) / 3f);

So now my joints act correctly, but it still seems to never want to completely come to rest. I thought about using a velocity cutoff in my particles, but I couldn't implement it properly. My particles usually reach a point where they are (visually) at rest, but when I use joints, I can clearly see it shivering.

[Edited by - NickGravelyn on March 19, 2007 5:39:08 PM]
Well,
if (d.LengthSquared() != (length * length))
is never going to return false, so they are never going to settle. You need some kind of epsilon range if you want them to actually stop.

You might also want to look at verlet integration for this kind of thing. For example, see my blob code.

This topic is closed to new replies.

Advertisement