Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Further to my previous question on fixed joints, I am now going toe-to-toe with hinge joints in 2D physics. Though the answer to the previous question was excellent, I have come across a few problems in extending it to hinge joints.

My approach was to extend that given here by implementing the following algorithm:

  1. Find the 'target' point for both hinge points by taking the midpoint between them (I actually use mass to give a ratio here but assume the bodies are of equal mass -- in my simulation they all are). The target point is labelled T in the diagram below.
  2. For body a, find the angle between the hinge point A and the target point T. This is done by transforming T from global space to local space, then taking the difference of Atan2(y, x) for each point - this should return the angle between them.
  3. The body a is then rotated by a matrix created from this angle, so that A and T now lie along the same vector. a is then translated by T-A; now A should be at T.
  4. Repeat steps 2 and 3 for body b.

The algorithm seems logical to me, but I have found that there is some kind of stability issue whereby the bodies will stay constrained for a short time, then as the angle between the two bodies becomes slightly more acute (in either direction), they will both shoot off at high velocity. The number of constraint iterations is not the issue as far as I can tell - the same problems occur at 1 iteration as at 10.

Diagram depicting two bodies with one hinge joint

Pseudocode to my algorithm given below:

// EntityA and EntityB are the two objects
// HingeA and HingeB are represented as vectors relative to their local transforms
Transform tA = EntityA.Transform;
Transform tB = EntityB.Transform;

Vector2 delta = tA.LocalToGlobal(HingeA) - tB.LocalToGlobal(HingeB);

// Locate the target in global space by finding the midpoint of the delta vector A-B
// then translating it by B
Vector2 Target = (delta * 0.5) + tB.LocalToGlobal(HingeB);

// Locate target in Entity A's local space
Vector2 TargetA = tA.GlobalToLocal(Target);

// Avoid undefined behaviour for Atan2
if (TargetA != Vector2.Zero && HingeA != Vector2.Zero)
{
   // Get the angular difference between A and T
   float angleA = Math.Atan2(TargetA.Y, TargetA.X) - Math.Atan2(HingeA.Y, HingeA.X);
   tA.Angle += angleA;
}

// Re-convert the target to local co-ordinates and translate EntityA towards it
tA.Pos += tA.GlobalToLocal(Target) - HingeA;

// Repeat for entity B...

Am I on the right track with this algorithm? Is there some minor detail I have missed that is aggravating the simulation?

share|improve this question
add comment

2 Answers 2

This is an interesting question

Just thinking out load ( well writing it down)

you know the position of A, Vector2 you know the position of B, also Vector2

you can calculate the distance between A and B => C = SQRT( (Bx - Ax)² + (By - Ay)²)

the equal distance between the 2 points is C/2.

mmm. I'v been drawing up to 10 different triangles and I think I come to the same conclusion, that T's position is always ( in 2D)

in pseudo code :

Tx = ABS(Bx-Ax) /2;

Ty = ABS(By-Ay) /2;

TA_Angle = tan( Tx /Ty);

TB_Angle = 90 - TA_Angle;

Maybe this could help ?

Or maybe it is too early and I completely missed the ball :/

T.

share|improve this answer
    
Locating the target point is not the issue - in the simple case of a 1:1 ratio it is the 'average' of the two hinge points. –  Alex Oct 5 '11 at 15:03
add comment

As is the way with most things, I had my Eureka moment at 5:30am after roughly 10 hours of debugging, head-scratching, beer-drinking etc.

My error was in the line

// Re-convert the target to local co-ordinates and translate EntityA towards it
tA.Pos += tA.GlobalToLocal(Target) - HingeA;

This translates the object along the local vector towards the target, but is translated in global space. For some bizarre mathematical reasons that I don't even want to begin to think about, this was fine up to +/- 45 degrees - at which point the sim blew up.

By replacing the line with

tA.Pos += Target - tA.LocalToGlobal(HingeA);

We have our hinge joint :)

share|improve this answer
    
However - the original question still stands - is this the best approach to hinge joints in position-based (verlet integration) physics? –  Alex Oct 6 '11 at 18:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.