Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Get the rope REAL particle index on colliision
#1
I have this oncollision code:

private void Solver_OnCollision(ObiSolver s, ObiSolver.ObiCollisionEventArgs e)
{
    var world = ObiColliderWorld.GetInstance();
    foreach (var contact in e.contacts)
    {
        if (contact.distance < 0.025f)
        {
            var collision = world.colliderHandles[contact.bodyB].owner;
...


            var particleIndex = solver.simplices[contact.bodyA];
            var contactedRope = (ObiRope)solver.particleToActor[particleIndex].actor;


and after

private int GetParticleNeighborIndex(int particleIndex, int offset)
{
    var solverIndex = rope.solverIndices[particleIndex];
    var elementCount = rope.elements.Count;
    int index;

    var e = 0;
    for (; e < elementCount; ++e)
        if (rope.elements[e].particle1 == solverIndex)
            break;

    if (e == elementCount - 1 && offset > 0)
        index = rope.elements[e].particle2;
    else
    {
        var n = Mathf.Clamp(e + offset, 0, elementCount - 1);
        index = rope.elements[n].particle1;
    }

    if (index > _lastParticleIndex && offset > 0) index = _lastParticleIndex;

    return index;
}


But as soon as I have 2 ropes in the same Solver, I get a crash:

IndexOutOfRangeException: Index was outside the bounds of the array.
 CreateClimbableObiRope2D.GetParticleNeighborIndex (System.Int32 particleIndex, System.Int32 offset) (at Assets/KLGames/ClimbObiRope/Scripts/CreateClimbableObiRope2D.cs:699)

What is the probleme here?


the crash is in this line


var solverIndex = rope.solverIndices[particleIndex];

IndexOutOfRangeException: Index was outside the bounds of the array.
(particleIndex is 130 but the solverIndices.length is only 87)

How can get back the REAL PARTICLE INDEX?

Thanks
Reply
#2
(02-10-2023, 07:58 AM)lacasrac Wrote: var particleIndex = solver.simplices[contact.bodyA];

Hi,

As explained in the manual, you can only assume simplices are the same as particles in case none of the ropes in your solver use surface collisions. In all other cases, the code above will retrieve the wrong index. See "Retreving the particle involved in a contact" for sample code that correctly retrieves all particles in the simplex.

Another problem is that the particle indices you retrieve from solver.simplices are already expressed relative to the solver. If you pass that to GetParticleNeighborIndex() - which assumes you pass the index of a particle in an actor- its first line will attempt to use it to access the actor's solverIndices array:

Code:
var solverIndex = rope.solverIndices[particleIndex];

Leading to an out of bounds access most of the time since the solver always has more particles than a single actor. Assuming you leave GetParticleNeighborIndex unmodified, you must do this:

Code:
// take the index of the bodyA's first particle in the solver:
var particleIndex = solver.simplices[contact.bodyA];

// then use it retrieve the index of that particle in the actor and pass it to GetParticleNeighborIndex
GetParticleNeighborIndex(solver.particleToActor[particleIndex].indexInActor);

instead of

Code:
// take the index of the particle in the solver, then pass it to GetParticleNeighborIndex (which assumes you pass the index of that particle in the actor, causing an exception:
var particleIndex = solver.simplices[contact.bodyA];
GetParticleNeighborIndex(particleIndex);

kind regards,
Reply