Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Collision detection with particles (strange behaviour)
#1
Code:
    private void Solver_OnCollision(ObiSolver s, ObiSolver.ObiCollisionEventArgs e)
    {
        var world = ObiColliderWorld.GetInstance();
        foreach (Oni.Contact contact in e.contacts)
        {
            // this one is an actual collision:
            if (contact.distance < 0.025f)
            {
                ObiColliderBase col = world.colliderHandles[contact.bodyB].owner;

                if (col != null && col.gameObject.layer==LayerMask.NameToLayer("CarFrontCollider"))
                {
                    // get the index of the particle involved in the contact:
                    int particleIndex = solver.simplices[contact.bodyA];
                    ObiRope contactedRope = solver.particleToActor[particleIndex].actor as ObiRope;
                    contactedRope.GetComponent<SpecificRopeTearer>().TearRope(particleIndex);        
                }
            }
        }
    }

Code:
public void TearRope(int particleIndex)
        {
        this.GetComponent<RopeBehaviour>().enabled = false;

        if (this.didTear == false)
        {
            BusSystem.CallOnRopeToreApart(this.endParticle.target.GetComponent<FuelLineEndController>());
            StartCoroutine(DestroyRope());
                        this.rope.stretchingScale = 1f;
                        this.endParticle.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
                        this.endParticle.target = this.rope.transform;
                        this.startParticle.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
                        this.startParticle.target = this.rope.transform;

                        this.didTear = true;
        }

        this.TearAtIndex(particleIndex);
    }

void TearAtIndex(int index)
    {
        Debug.Log(index);

        if (index < rope.elements.Count)
        {
            this.rope.Tear(rope.elements[index]);
        }


        this.rope.RebuildConstraintsFromElements();
    }


Hi ! I am working on a project and using ObiRope. I have problem with detecting collision with particles. I read documents and tried to use them as best as I can. 

I need to know which particle collided with a object that has specific layer. And I want to tear the rope at collided particles. Here is some screenshots for explaining it better. At right (teared rope) image behaviour acts like I want. But after I spawn new ropes it doesn't work. When I am Debug.Log the shown indexes are beyond existing particle count (I may be wrong in here.).


If you need any additional info please tell me, I don't want to scare people with a long post  Sonrisa

Thank you !

I think I solved it Gran sonrisa. Just changed parameter "particleIndex" to "this.solver.particleToActor[particleIndex].indexInActor"  Sonrisa I think I solved it Gran sonrisa. Still don't have idea why it didn't work.

Code:
    private void Solver_OnCollision(ObiSolver s, ObiSolver.ObiCollisionEventArgs e)
    {
        var world = ObiColliderWorld.GetInstance();
        foreach (Oni.Contact contact in e.contacts)
        {
            // this one is an actual collision:
            if (contact.distance < 0.025f)
            {
                ObiColliderBase col = world.colliderHandles[contact.bodyB].owner;

                if (col != null && col.gameObject.layer==LayerMask.NameToLayer("CarFrontCollider"))
                {
                    // get the index of the particle involved in the contact:
                    int particleIndex = solver.simplices[contact.bodyA];
                    ObiRope contactedRope = solver.particleToActor[particleIndex].actor as ObiRope;
                    contactedRope.GetComponent<SpecificRopeTearer>().TearRope(this.solver.particleToActor[particleIndex].indexInActor); ;
                }
            }
        }
    }


Attached Files Thumbnail(s)
       
Reply
#2
(05-08-2021, 09:09 PM)immrkuby Wrote: Just changed parameter "particleIndex" to "this.solver.particleToActor[particleIndex].indexInActor"  Sonrisa I think I solved it Gran sonrisa. Still don't have idea why it didn't work.

particleIndex is the index of a particle in the solver. this.solver.particleToActor[particleIndex].indexInActor is the index of the particle in an actor. It's two entirely different things. From the manual, scripting particles section:

Quote:Actor particle indices run from 0 to the amount of particles in that actor. However, since particle data for an actor might be scattered across the solver arrays, you need to map from actor index to solver index.

Say you have 3 actors: the first one has 5 particles, the second one has 3, and the third one has 4. Actor particle indices for them are 0-4, 0-2 and 0-3. But the solver (that stores all particle data) might have assigned completely different indices for them. Particles for the first actor might have their data stored at indices 21,33,34 and 36, the second one 3,5 and 9, and the third one 1,2,4 and 6, in the solver arrays. To access per-actor data you'd use actor indices (particleIndex in your case). To access the main solver arrays (positions, velocities, orientations, etc) you'd use solver indices.

Also, your TearAtIndex() method doesn't make any sense. You're using the index of a particle in the actor to look up an array of elements. If this works, it's purely out of luck. Will result in an out of bounds exception most of the time.

Code:
if (index < rope.elements.Count)
{
            this.rope.Tear(rope.elements[index]); //<---can't access elements using a particle index!!
}

Elements are the "edges" in between particles, that hold them together. Each element joins exactly two particles together, so it has two solver indices in it. You should iterate trough all elements until you find the one that references your particle. Like so:

Code:
void TearAtIndex(int index) //<---pass a solver index here, that is your particleIndex.
{
foreach(var element in rope.elements)
{
    if (element.particle1 == index){
        this.rope.Tear(element);
         break;
    }
}
this.rope.RebuildConstraintsFromElements();
}
Reply
#3
(06-08-2021, 08:14 AM)josemendez Wrote: particleIndex is the index of a particle in the solver. this.solver.particleToActor[particleIndex].indexInActor is the index of the particle in an actor. It's two entirely different things. From the manual, scripting particles section:


Say you have 3 actors: the first one has 5 particles, the second one has 3, and the third one has 4. Actor particle indices for them are 0-4, 0-2 and 0-3. But the solver (that stores all particle data) might have assigned completely different indices for them. Particles for the first actor might have their data stored at indices 21,33,34 and 36, the second one 3,5 and 9, and the third one 1,2,4 and 6, in the solver arrays. To access per-actor data you'd use actor indices (particleIndex in your case). To access the main solver arrays (positions, velocities, orientations, etc) you'd use solver indices.

Also, your TearAtIndex() method doesn't make any sense. You're using the index of a particle in the actor to look up an array of elements. If this works, it's purely out of luck. Will result in an out of bounds exception most of the time.

Code:
if (index < rope.elements.Count)
{
            this.rope.Tear(rope.elements[index]); //<---can't access elements using a particle index!!
}

Elements are the "edges" in between particles, that hold them together. Each element joins exactly two particles together, so it has two solver indices in it. You should iterate trough all elements until you find the one that references your particle. Like so:

Code:
void TearAtIndex(int index) //<---pass a solver index here, that is your particleIndex.
{
foreach(var element in rope.elements)
{
    if (element.particle1 == index){
        this.rope.Tear(element);
         break;
    }
}
this.rope.RebuildConstraintsFromElements();
}

Thank you very much ! I was confused at "But the solver (that stores all particle data) might have assigned completely different indices for them." and now things become clearer ! 
Reply