0
\$\begingroup\$

I have some problems with hinge joint chain movement calculations...

Here is my algorithm for segments location/rotation adjustments after a previous segment update (C#):

void AdjustLocation()
{
    float halfWidth = Size.Width / 2;
    
    // Translations
    Vector parentBack = PrevSegment.Center - (halfWidth * new Vector(Cos(PrevSegment.Rotation), Sin(PrevSegment.Rotation))); // Green on the pic
    Vector front = this.Center + (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation))); // Blue on the pic
    
    // Const spacing between segments
    float spacing = *some_value*;
    
    Vector dv = parentBack - front;
    float k = spacing / dv.Length;
    
    // New front location
    front = parentBack - (dv * k);
    // New rotation
    dv = front - this.Center;
    this.Rotation = Atan2(dv.Y, dv.X);
    
    // Translate back to the center
    this.Center = front - (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation)));
    
    NextSegment?.AdjustLocation();
}

It's working (partially), but it seems I'm missing something as it doesn't behave like a chain. Segments always move one by another although they should not always do this. Also overlapped sections of a long chain form a "knot" going all the way to the end of the chain before its "untangling". What am I missing?

Btw: everything screws up with negative spacing values.

P.S. Tried to visualize the algorithm on the picture: img

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

I figured it out myself.

void AdjustLocation()
{
    float halfWidth = Size.Width / 2;

    // Current segment back positions
    Vector offset = (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation)));
    Vector backPos = this.Center - offset;

    Vector newFrontPos;
    if (SegmentsSpacing > 0)
    {
        // Current segment front position
        Vector frontPos = this.Center + offset;

        // Parent segment back position
        offset = (halfWidth * new Vector(Cos(PrevSegment.Rotation), Sin(PrevSegment.Rotation)));
        Vector parentBackPos = PrevSegment.Center - offset;

        // Find delta
        Vector dv = parentBackPos - frontPos;
        float k = SegmentsSpacing / dv.Length;

        // Calculate new front position
        newFrontPos = parentBackPos - (dv * k);
    }
    else
    {
        // Calculate new front position
        offset = ((halfWidth + SegmentsSpacing) * new Vector(Cos(PrevSegment.Rotation), Sin(PrevSegment.Rotation)));
        newFrontPos = PrevSegment.Center - offset;
    }

    // Calculate new rotation
    Vector dv = newFrontPos - backPos;
    this.Rotation = Atan2(dv.Y, dv.X);
    // Translate back to center
    this.Center = newFrontPos - (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation)));

    NextSegment?.AdjustLocation();
}

My mistake was that I calculated the rotation using wrong points (it should be equal to the angle between the new front position and the old back position of a segment).
As for spacing, everything's much simplier with negative values (because you can simply move the front position of a segment to the joint position), otherwise, you must find the correct point on the line between the front position of a segment and the back position of its parent segment.

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .