Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tear after changing length with cursor
#1
Hi all!
Is it possible to tear after changing length?
Here is my code for tearing:

Code:
    void Solver_OnCollision(object sender, ObiSolver.ObiCollisionEventArgs e)
    {
        var world = ObiColliderWorld.GetInstance();

        // just iterate over all contacts in the current frame:
        foreach (Oni.Contact contact in e.contacts)
        {
            // if this one is an actual collision:
            if (contact.distance > 0.01) continue;

            ObiColliderBase col = world.colliderHandles[contact.bodyB].owner;
            TearRope(col, contact);
        }
    }

    private void TearRope(ObiColliderBase col, Oni.Contact contact)
    {
        if (!col || !col.CompareTag(StaticData.tear)) return;

        ObiSolver.ParticleInActor pa = solver.particleToActor[contact.bodyA];
        if (pa == null) return;

        var actor = pa.actor as ObiRope;
        if (!actor) return;
       
        if (pa.indexInActor >= actor.elements.Count) return;

        actor.Tear(actor.elements[pa.indexInActor]);
        actor.RebuildConstraintsFromElements();
    }

It works for pre-created rope, but when I change length, it cuts somewhere at the end, not at collision point.
Please help.
Reply
#2
Your code is incorrect:

You're indexing the solver.particleToActor array using a simplex index. You need to use a particle index instead. Check the manual to see how to retrieve a particle index from a simplex: http://obi.virtualmethodstudio.com/tutor...sions.html

In case you're not using surface collisions, you can do:

Code:
int particleIndex = solver.simplices[contact.bodyA];

Then, you can do:

Code:
ObiSolver.ParticleInActor pa = solver.particleToActor[particleIndex];

However this last bit is not necessary: you don't need to know the index in the actor to tear an element, see below:

You're also indexing the elements array with a particle index:
Code:
actor.Tear(actor.elements[pa.indexInActor]);

If this works, is just pure luck, as most often will result in an out of bounds exception. You need to determine which element in the elements array references your particle, and tear that. Iterate over all elements until you find an element such that element.particle1 = particleIndex, then use that element.


Wrapping up, the code should be:

Code:
// find particle for this simplex:
int particleIndex = solver.simplices[contact.bodyA];

// find an element that references this particle, and tear it.
foreach (var elm in rope.elements)
if (elm.particle1 == particleIndex)
rope.Tear(elm);

// rebuild constraints
rope.RebuildConstraintsFromElements();
Reply
#3
I tried doing this way at first, but got same results.
Code:
int particleIndex = solver.simplices[contact.bodyA];

But now, with iteration over elements, everything worked out!
Thank you very much!
Reply
#4
another question (don't know if I should create a new thread).
Can I tear a rope created with obi mesh renderer? I made my rope, but when I try to tear it, it just becomes stiff like a stick and behaves strangely. Read/Write enabled.
Reply
#5
(13-05-2021, 04:06 PM)luvjungle Wrote: another question (don't know if I should create a new thread).
Can I tear a rope created with obi mesh renderer? I made my rope, but when I try to tear it, it just becomes stiff like a stick and behaves strangely. Read/Write enabled.

ObiRopeMeshRenderer does not support tearing/resizing, because that would involve retopologizing the mesh which isn't cheap nor simple. Only extruded and line renderer do.
Reply
#6
Thanks!
Reply