azura
azura copied to clipboard
Regarding long range attachment constraint
Thank you so much for sharing your repo with us. Here is the main code for the long range attachment (file: SolvingPass_Cloth_ApplyConstraint.cs.slang)
const float invMassA = constraintBlock.invMasses[dist.indexA];
const float invMassB = constraintBlock.invMasses[dist.indexB];
const float invMassSum = (invMassA + invMassB);
const float invMassFactor1 = invMassA / invMassSum;
const float invMassFactor2 = invMassB / invMassSum;
const float3 x12 = (clothDataBlock.projectedPos[dist.indexA] - clothDataBlock.projectedPos[dist.indexB]);
const float lengthDelta = length(x12) - dist.restLength;
if (lengthDelta > 0) {
const float3 delta1 = (computeUBOBlock.longRangeStiffness * -1.0 * invMassFactor1 * (lengthDelta)) * normalize(x12);
const float3 delta2 = (computeUBOBlock.longRangeStiffness * invMassFactor2 * (lengthDelta)) * normalize(x12);
AtomicAddDeltaX(dist.indexA, delta1.x);
AtomicAddDeltaY(dist.indexA, delta1.y);
AtomicAddDeltaZ(dist.indexA, delta1.z);
AtomicAddDeltaX(dist.indexB, delta2.x);
AtomicAddDeltaY(dist.indexB, delta2.y);
AtomicAddDeltaZ(dist.indexB, delta2.z);
}
and here is the distance constraint code given in the same file
const float invMassA = constraintBlock.invMasses[dist.indexA];
const float invMassB = constraintBlock.invMasses[dist.indexB];
const float invMassSum = (invMassA + invMassB);
if (invMassSum > EPSILON) {
const float invMassFactor1 = invMassA / invMassSum;
const float invMassFactor2 = invMassB / invMassSum;
const float3 x12 = (clothDataBlock.projectedPos[dist.indexA] - clothDataBlock.projectedPos[dist.indexB]);
const float3 delta1 = (computeUBOBlock.stretchStiffness * -1.0 * invMassFactor1 * (length(x12) - dist.restLength)) * normalize(x12);
const float3 delta2 = (computeUBOBlock.stretchStiffness * invMassFactor2 * (length(x12) - dist.restLength)) * normalize(x12);
AtomicAddDeltaX(dist.indexA, delta1.x);
AtomicAddDeltaY(dist.indexA, delta1.y);
AtomicAddDeltaZ(dist.indexA, delta1.z);
AtomicAddDeltaX(dist.indexB, delta2.x);
AtomicAddDeltaY(dist.indexB, delta2.y);
AtomicAddDeltaZ(dist.indexB, delta2.z);
}
I see that you are comparing the current length with the rest length and finding if the difference is greater than 0 which would mean that the particle is moving away and should have the constraint applied to it. But my main concern is that you are takign the mass ratios. For long range attachment the one of the masses will be 0 since its a fixed point. Also since one of the points is fixed the correction cannot be applied on both points.
From what I understand, long range attachment needs an attachment point and it is applied only to the given point. You calculate the rest distance of the long range attachment point at initialization. Then you check how far the particle predicted position is from the attachment position. If the distance is greater than the rest distance, you apply an exact correction to move it to the rest distance. Also the correction needs to be applied to only one particle since the other particle is an attachment which should have a mass of 0. So I guess the long range attachment should be implemented as follows. I am giving it in pseudocode form so you will know how to implement it:
id = currentParticleID;
predPos = projectedPos[id]
attachPos = attachPositions[attachID[id]];
restDistance = attachDistances[id] * longRangeStiffness
delta = predPos - attachPos
currentDistance = delta.length()
if (currentDistance > restDistance)
{
correction = -delta + (delta/currentDistance) * restDistance;
atomicAdd( delta, id, correction)
}