# Angular constraints

This topic is 4915 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello all, I'm seeking a way to have a solid angular constraint for my 2D verlet-based physics sim, it's for making arms and legs not bending in the wrong direction. The search for this has reached near mystical proportions, as I'm now stumped after trying all ideas I can come up with. Finding if the angle is outside it's boundary is simple, but responding to it always make the entire body being jerked, as the other constraints try to compensate for it. I've searched a lot for answers on this topic, but I haven't been able to find any answers, or even a pointer in the right direction, perhaps angles isn't the way to go at all, but I just can't seem to wrap my head around this one - possibly something very simple that I'm just overlooking.. but I need some fresh idea at this point. I bet some of you've seen this floating around the internet: http://pekkasandborg.com/portfolio/?id=2 There's some solid looking angular constraints, and it uses the same base as I do, except that the famous Jacobssen article he mentions doesn't actually stretch as far as explaining angular constraints, so I guess he solved it himself. Any ideas, pointers? Much appreciated.

##### Share on other sites
Unless I'm missing something, I believe I've tried that, and it sends "shivers" through the rest of the character as it's settling down. Forcefully moving a particle is the same thing as introducing a force, right, so instead of just stopping the particle when it goes to far, it's jerking it back violently, creating wild bounces of the limb in question. I tried moving the "old position" an equal ammount as to preserve velocity, but that didn't seem to help either.. I can't really tell why this is a problem.

edit:
There are 3 particles involved, t1, t2, t3 in this func, for example t1=shoulder joint, t2=elbow, t3=wrist, with vector properties pos, oldpos etc. for verlet
	Vector top = t1.pos - t2.pos; // vector of upper arm	Vector bot = t2.pos - t3.pos; // vector of wrist	float da = top.AngleBetween(bot); // returns angle from -PI to PI	if (da>0) // ie. more than 180 degrees	{		float len = bot.Length(); // store length of wrist		bot = top.UnitVector();   // set to same angle as upper arm		bot.Mult(-len);           // restore length of wrist		t3.pos = t2.pos+bot;      // move wristpoint to elbow+wrist	}

Well, that's what I have at the moment, very jerky indeed :) When the lower limb moves beyond the constraint, there's a violent kick backwards, which brings the entire character with it.

[Edited by - LGAB on August 5, 2005 1:12:21 PM]

##### Share on other sites
I was using 4, for no particular reason, but even up to 20 there's no change in this particular behaviour..
The code is based on the Jacobsen article, so you can find pseudo code of it there, I've just adapted it to my needs, the integration part is the same, and the part where constraints are satisfied goes something like this..

if (any particles, or any constraints)  for number_of_iterations    for all constraints      case constraint.type        NONE: (do nothing)        NAIL: CnsNail(params)        SPRING: CnsSpring(params)        etc, etc.      /case    /for  /for/if

Nothing spectacular here :)

##### Share on other sites

Sure no problem, let me know if I was being to unspecific, and I'll elaborate for you! Just trying to spare you from somewhat longish pieces of source code :)

I commented out the Verlet() part of the update, and you're right! It's like dragging the character through mud, but the constrain really works, it stays straight when it should, and bends when it should, so that was very useful!

Now to figure out how to correct this problem with the velocity.. is there a flaw in the integration described by Jacobsen?

##### Share on other sites

I've tried a bunch of things, but mocking about with the velocity/oldpos invariably results in either violent spinning, or unnatural slow-downs of the feet/hands, so they drag behind instead. I think I've seen all kinds of weird behaviour!
Looking at the code in my second post, how would you change it to take velocity in to account?

##### Share on other sites

I'm afraid I've tried every conceivable combination of what've talked about, none works any better than the original code.
So I'm sort of back to square one with this. I can't help but think there's a different approach to angular constraints, one that's stable and solid regardless of velocities :) I need to do some serious algo-sketching and think this over one more time.

skittleo, your input on this is much, much appreciated! This battle aint over :)

##### Share on other sites
I've solved the angular constraint problem in 3d:
1) a "keep 2 particles at least a min distance apart" constraint for min angle
2) a "keep particle on one side of a plane" constraint for max angle.

You could easily apply a similar solution for the 2d case:

1) a "keep 2 particles at least a min distance apart" constraint for min angle
2) a "keep particle on one side of a line" constraint for max angle.

For example, to keep the lower leg from bending the knee backwards, stop the foot particle from going on the outer side of the upper leg line (hip -> knee particle). To do this, just compute the normal pointing out from the hip->knee line and check to see which side (via the dot product) the foot particle is. Also instead of just moving the foot particle to correct the error, move the foot particle 50% one direction and the knee particle 50% the other direction, otherwise you'll introduce rotational velocity (taking particle mass into account is a simple extension - the ratios will no longer be 50% each)

The big advantage of a "keep on side of plane/line" constraint for a max angle is that it is always stable (ie. the normal of the plane/line never flips). The only tricky part is computing the line/plane normals from the particle configuration, but it all boils down to simple math (cross products in 3d).

Does this make sense?

See this thread for my 3d implementation source:
http://www.gamedev.net/community/forums/topic.asp?topic_id=324795

hope that helps-Steve.

##### Share on other sites
That made a lot of sense! Moving back the knee was the solution! Thanks a lot, I'll see if using your plane/line method is faster or better, but detecting the angle in radians works fine too :)

The revised code is this, in case someone might find it useful in the future:

Vector top = t1.pos - t2.pos;     // thigh/upper armVector bot = t2.pos - t3.pos;     // lower leg/wristfloat da = top.AngleBetween(bot); // angle in -PI to PIif (da>0){	float l = bot.Length();   // store length of wrist	bot = top.UnitVector();   // copy orientation	bot.Mult(-l);             // scale to original length        // difference of where it is, and where it should be:	Vector diff = t3.pos - (t2.pos+bot);        // scale it to half length:	diff.Mult(0.5);        // give knee and foot one push each in opposite dirs:	t3.pos = t3.pos - diff;	t2.pos = t2.pos + diff;}

It's rock solid, thanks a bunch!!!

##### Share on other sites
Cool - glad that worked out.

Isn't it funny how the paper skips the hardest part! I burnt many hours of my life getting verlet ragdolls working - you can keep on tweaking for ever...

##### Share on other sites
Very true.. my ragdoll feels pretty competent now, and I can have hundreds flying around, getting their limbs blasted off :)

  Doll.SplitDoll();  BloodSquirt(Doll.GetJoint(4));

:)

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 9
• 11
• 9
• 9
• ### Forum Statistics

• Total Topics
634135
• Total Posts
3015754
×