25-08-2023, 03:13 PM
(This post was last modified: 25-08-2023, 03:53 PM by sebjf.
Edit Reason: Updated attached script
)
I've managed to get it almost completely working now.
Instead of adding constraints, I find if there is an existing constraint for that solver index. If there is, I update the batch's array properties and activate the index. Similarly, instead of removing constraints they are deactivated.
What is odd is that even after this, when I created constraints on-demand (if they were not found), I would get occasions where the lists would lose sync still! However, if I pre-create a constraint for each actor particle's solver index in Start(), then it works correctly (which makes me think it is something to do with growing the array between activations/deactivations).
I prefer this solution regardless as it avoids reallocations.
The only thing I don't like is needing to search the particleIndices when activating a constraint. Though my cloth has very few particles, I will try and use the m_ID and m_IDToIndex to persistently associate solver particles with an identity.
This is what I have so far,
And then to look up the constraint from the solver index:
However this fails, and I need for now to get the constraintIndex by iterating the particles:
If I can get the above to work I can do away with the lists entirely and just store flags for each actor particle, which would be much nicer.
Instead of adding constraints, I find if there is an existing constraint for that solver index. If there is, I update the batch's array properties and activate the index. Similarly, instead of removing constraints they are deactivated.
Code:
bool found = false;
for (int i = 0; i < adhesionBatch.constraintCount; i++)
{
if (adhesionBatch.particleIndices[i] == solverIndex)
{
adhesionBatch.pinBodies[i] = Dummy.Handle;
adhesionBatch.colliderIndices[i] = Dummy.Handle.index;
adhesionBatch.offsets[i] = positionOffset;
adhesionBatch.restDarbouxVectors[i] = orientationOffset;
// And everything else is the same...
found = true;
adhesionBatch.ActivateConstraint(i);
break;
}
}
What is odd is that even after this, when I created constraints on-demand (if they were not found), I would get occasions where the lists would lose sync still! However, if I pre-create a constraint for each actor particle's solver index in Start(), then it works correctly (which makes me think it is something to do with growing the array between activations/deactivations).
I prefer this solution regardless as it avoids reallocations.
The only thing I don't like is needing to search the particleIndices when activating a constraint. Though my cloth has very few particles, I will try and use the m_ID and m_IDToIndex to persistently associate solver particles with an identity.
This is what I have so far,
Code:
private void Start()
{
actor.solver.OnCollision += Solver_OnCollision;
graspBatch = new ObiPinConstraintsBatch();
adhesionBatch = new ObiPinConstraintsBatch();
// Pre-create the adhesion constraints
actorIndexToConstraintId = new List<int>();
for (int i = 0; i < actor.particleCount; i++)
{
var solverIndex = actor.solverIndices[i];
adhesionBatch.AddConstraint(
solverIndex,
Dummy,
Vector3.zero,
Quaternion.identity,
0,
0,
0.1f
);
actorIndexToConstraintId.Add(i);
}
}
And then to look up the constraint from the solver index:
Code:
// Lookup the constraint index
var i = adhesionBatch.GetConstraintIndex(actorIndexToConstraintId[actor.solver.particleToActor[solverIndex].indexInActor]);
However this fails, and I need for now to get the constraintIndex by iterating the particles:
Code:
for (int j = 0; j < adhesionBatch.constraintCount; j++)
{
if (adhesionBatch.particleIndices[j] == solverIndex)
{
if(i != j)
{
Debug.Log("Constraint Id Changed");
}
i = j;
break;
}
}
If I can get the above to work I can do away with the lists entirely and just store flags for each actor particle, which would be much nicer.