Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Rope resolution inconsistency resulting in larger forces required
#9
Hi Jose,
I thought I'd return and offer my experience trying to implement this.
I think I've managed to acheive the behaviour I was looking for thanks to your pointers above Sonrisa . 
I'm using the following logic:

Code:
private void ChangeVisualRopeLength(float newLength)
{
    if (!rope.isLoaded)
        return;

    // Current IPD is? (Ignore the start/end, they have pinned particles
    var endElementRestLength = rope.elements[0].restLength;
    endElementRestLength += rope.elements[rope.elements.Count - 1].restLength;
    var targetOtherElementLength = newLength - endElementRestLength;

    // Calculate the new IPD
    var currentIPD = rope.ropeBlueprint.interParticleDistance;
    var maxIPD = Mathf.Max(maxDesiredIPD, currentIPD);
    var stretchIPD = targetOtherElementLength / (rope.elements.Count - 2); // Don't touch the first and last elements
    stretchIPD = Mathf.Clamp(stretchIPD, 0, maxDesiredIPD);

    // Iterate trough all distance elements and update their rest lengths.
    var solver = rope.solver;
    var newElementRestLength = stretchIPD;
    rope.ropeBlueprint.interParticleDistance = newElementRestLength;
    int elementCount = rope.elements.Count;
    for (int i = 0; i < elementCount; ++i)
    {
        if (i == 0 || i == elementCount - 1)
        {
            // don't change rest lengths of first and last elements
            continue;
        }
        // Never shorten an element in this way (delete them instead)
        rope.elements[i].restLength = Mathf.Max(newElementRestLength, rope.elements[i].restLength);
    }
    // Update the mass of particles across the rope (except the ends)
    float totalActiveMass = newLength * massPerMeter;
    float massPerParticle = totalActiveMass / rope.particleCount;
    for (int i = 0; i < rope.particleCount; ++i)
    {
        if (i < 2 || i > rope.particleCount - 2)
        {
            // don't change rest lengths of first and last elements
            continue;
        }
        var solverIndex = rope.solverIndices[i];
        solver.invMasses[solverIndex] = ObiUtils.MassToInvMass(massPerParticle);
    }

    // Recalculate rest length as the cached value is used during ChangeLength
    rope.RecalculateRestLength();

    // Finally, tell ObiCursor to add/remove particles as required
    ropeCursor.ChangeLength(newLength);
}

Then I'm increasing the length whenever the real length deviates too far from the intended rest length:
Code:
private void FixedUpdate()
{
    float actualLength = rope.CalculateLength();
    float restLength = rope.restLength;
    if (actualLength - restLength > stretchThreshold)
    {
        if (restLength < maxLength)
        {
            float newLength = Mathf.Min(maxLength, actualLength + extensionRate * Time.fixedDeltaTime);
            ChangeVisualHoseLength(newLength);
        }
    }
}

Thanks for your help!
I'd be interested in any feedback you have on the above code if you observe any obvious problems.
Again, thanks for your help.
Reply


Messages In This Thread
RE: Rope resolution inconsistency resulting in larger forces required - by inbilla - 06-04-2024, 03:53 AM