Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Multiple Rope Cursors on single rope
#1
So I've been playing around with the rope cursor, and I've come across a situation where i would like to have multiple cursors on my rope, so that i can have different addition and deletion speeds on two sides of a handle or pin tether constraint.

While the deletion works fine, the addition seems to be adding particles only at the first cursor. 
Any thoughts on using multiple cursors? Is this even supposed to be achievable?

//TheMunk
Reply
#2
Okay, just reporting my findings:

Apparently with multiple cursors their position can jump when adding particles. If you force the position of the cursor whenever you change the length of the rope, it will stay put (in my case one cursor at 0, and another at 1). This fixes the issue with one cursor adding its particle to the other side of a handle/tether.
Reply
#3
(31-10-2019, 10:44 AM)TheMunk Wrote: Okay, just reporting my findings:

Apparently with multiple cursors their position can jump when adding particles. If you force the position of the cursor whenever you change the length of the rope, it will stay put (in my case one cursor at 0, and another at 1). This fixes the issue with one cursor adding its particle to the other side of a handle/tether.

Hi there!

To be honest, never thought about the use case of having multiple cursors in a single rope. Taking note for future updates.

Since each cursor updates its own position (specified as normalized length) when adding/removing particles, what you found out makes perfect sense: each cursor is not aware of the others, so they do not automatically update their position when another cursor changes the amount of particles. Doing it manually for every cursor seems a viable workaround.
Reply
#4
(31-10-2019, 11:41 AM)josemendez Wrote: Hi there!

To be honest, never thought about the use case of having multiple cursors in a single rope. Taking note for future updates.

Since each cursor updates its own position (specified as normalized length) when adding/removing particles, what you found out makes perfect sense: each cursor is not aware of the others, so they do not automatically update their position when another cursor changes the amount of particles. Doing it manually for every cursor seems a viable workaround.

Adding another issue to this; 
When changing rope length with a cursor while baking particles, the playback will do some weird stuff. Is this a known bug?

EDIT:
Also, when trying to get the positions of all active particles in order to spawn and update a position for gameobjects, the indices jumps around when deleting from both ends. It's very obscure to get a list of all active particles.
Reply
#5
(01-11-2019, 11:31 AM)TheMunk Wrote: Adding another issue to this; 
When changing rope length with a cursor while baking particles, the playback will do some weird stuff. Is this a known bug?

EDIT:
Also, when trying to get the positions of all active particles in order to spawn and update a position for gameobjects, the indices jumps around when deleting from both ends. It's very obscure to get a list of all active particles.

Hi,

Adding new particles to a baked simulation won't behave nicely (since the new particles do not have any cached information, it's impossible to expect the playback to work). Anyway the baker is undocumented, unmaintained and pretty much unsupported as of now (in fact, it's entirely gone in 5.0). It was written way back in Obi 1.0 when there was no good way of getting baked simulations into Unity, but nowadays Alembic does a much better job of importing them so there's little motivation to maintain a system that does the same, but worse.  See this thread:
http://obi.virtualmethodstudio.com/forum...p?tid=1455

When adding particles from a rope, particles are appended/removed from the particle list, but aren't sorted in any particular way. If for some reason you need to get all particles in the rope in order (from first to last), you need to iterate over structural constraints (distance constraints for ropes, stretch/shear constraints for rods). Each structural constraint holds 2 particles together, and unlike particles, they are guaranteed to alway be correctly sorted:

Code:
int constraintCount = rope.GetStructuralConstraintCount();
for (int i = 0; i < constraintCount; ++i)
{
    int particle1 = -1, particle2 = -1;
    if (rope.GetStructuralConstraintParticles(i,ref particle1,ref particle2))
       {
        Vector3 pos1 = rope.GetParticlePosition(particle1)
               Vector3 pos2 = rope.GetParticlePosition(particle2));
    }
}

Or if you just want to iterate over all active particles in no particular order:
Code:
for (int i = 0; i < rope.particleIndices.Length; ++i)
{
    if (rope.active[i])
    {
    //do stuff
    }
}
Reply
#6
(02-11-2019, 08:35 AM)josemendez Wrote: Hi,

Adding new particles to a baked simulation won't behave nicely (since the new particles do not have any cached information, it's impossible to expect the playback to work). Anyway the baker is undocumented, unmaintained and pretty much unsupported as of now (in fact, it's entirely gone in 5.0). It was written way back in Obi 1.0 when there was no good way of getting baked simulations into Unity, but nowadays Alembic does a much better job of importing them so there's little motivation to maintain a system that does the same, but worse.  See this thread:
http://obi.virtualmethodstudio.com/forum...p?tid=1455

When adding particles from a rope, particles are appended/removed from the particle list, but aren't sorted in any particular way. If for some reason you need to get all particles in the rope in order (from first to last), you need to iterate over structural constraints (distance constraints for ropes, stretch/shear constraints for rods). Each structural constraint holds 2 particles together, and unlike particles, they are guaranteed to alway be correctly sorted:

Code:
int constraintCount = rope.GetStructuralConstraintCount();
for (int i = 0; i < constraintCount; ++i)
{
    int particle1 = -1, particle2 = -1;
    if (rope.GetStructuralConstraintParticles(i,ref particle1,ref particle2))
       {
        Vector3 pos1 = rope.GetParticlePosition(particle1)
               Vector3 pos2 = rope.GetParticlePosition(particle2));
    }
}

Or if you just want to iterate over all active particles in no particular order:
Code:
for (int i = 0; i < rope.particleIndices.Length; ++i)
{
    if (rope.active[i])
    {
    //do stuff
    }
}

I created this solution meanwhile. Seems to work so far with a single cursor. Will have to do some more tests, but it seems like this at least orders the particles correctly so that the prefab instantiated stays with he particle (and doesn't jump around as the rope is extended/shortened).

Code:
for (int i = 0; i < actor.active.Length; i++)
       {
           if (actor.active[i]) //if the particle is on the rope
           {
               Vector3 tempPos = actor.GetParticlePosition(i);
               if(i >= 0 && i < particleSystems.Count && particleSystems[i] != null) //if the reference is not null or out of bounds
                   particleSystems[i].transform.position = tempPos;
               else if ((i >= 0 && i < particleSystems.Count)) //if not out of bounds
               {
                   if(particleSystems[i] == null)
                   {
                       print("ReAdding");
                       GameObject particleSystem = Instantiate(WaterParticlePrefab, waterParticlesRoot);
                       particleSystem.transform.position = tempPos;
                       particleSystems[i] = particleSystem;
                   }
               }
               else if (!(i >= 0 && i < particleSystems.Count)) //if the index is out of bounds
               {
                   print("Adding new");
                   GameObject particleSystem = Instantiate(WaterParticlePrefab, waterParticlesRoot);
                   particleSystem.transform.position = tempPos;
                   particleSystems.Add(particleSystem);
               }        
           }
           else //if the particle is NOT on the rope (in the pool)
           {
               if(i >= 0 && i < particleSystems.Count && particleSystems[i] != null) //if the reference is not null or out of bounds
                   Destroy(particleSystems[i].gameObject);
           }
       }
Reply