06-04-2024, 03:53 AM
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 .
I'm using the following logic:
Then I'm increasing the length whenever the real length deviates too far from the intended rest length:
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.
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 .
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.