Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Get position of particle at end of rope
#1
Hello,

I would like to find the position of the particle at one end of a rope, no matter how much it has been resized at runtime. 

I have a rope with two control points and two particle attachments. The top attachment is static and the bottom is dynamic. I'm looking to reset an object to the end of the rope (on the dynamic attachment), and to do this I want to either move the rope to the object, or the object to the rope. They are both within close proximity of each other.

I tried to get the solver index of that particle using the rope's blueprint: 
Code:
int solverIndex = defaultRopeBlueprint.groups[1].particleIndices[0];
Vector3 worldPos = rope.GetParticlePosition(solverIndex);

This seemed to work, but if I change the length of the rope at runtime, I get a position that doesn't make sense. 

I also tried the solution from this thread, which needed a bit of updating. I'm not sure if I'm doing this correctly. I am getting a solver index of 0 for both the first and last particle. 

Code:
ObiConstraintsBatch batch = (ObiConstraintsBatch)rope.GetConstraintsByType(Oni.ConstraintType.Distance).GetBatch(0);
int lastParticle = batch.particleIndices[(batch.constraintCount - 1) * 2 + 1];
int firstParticle = batch.particleIndices[0];
Vector3 worldPos = rope.GetParticlePosition(firstParticle);
//or
Vector3 worldPos = rope.GetParticlePosition(lastParticle);

Thank you!
Reply
#2
More info: The problem is when the rope length has been changed to be shorter than it was originally. 

Then I try to set the particle position at the end of the rope to the objects position, but that particle is no longer being used, so it looks like the object is floating away from the end of the rope.
Reply
#3
Hi,

Particle order changes when you resize or tear the rope. On a 10-particles long rope, you can't assume #0 being the first and particle #9 being the last.

----------

However, elements are guaranteed to be sorted. These are the "edges" that link each particle in the rope to the next one.

You can use the rope's GetElementAt() method to get the element at a given normalized coordinate (0 being the start of the rope, 1 the end). Eg:

Code:
var element = GetElementAt(0,out float elementMu);
index1 = element.particle1; // first particle in the rope
index2 = element.particle2;

-----------

As you know, the ObiPathSmoother generates an intermediate representation of the rope that is used for rendering (see: http://obi.virtualmethodstudio.com/tutor...modes.html)

You can also get smoothed path positions along the rope, instead of working with raw particles/elements. For this you can use the path generator's GetSectionAt() method, that also takes a normalized coordinate as input. For instance, if you wanted to place an object at a position and orientation:

Code:
var generator = GetComponent<ObiPathSmoother>();
ObiPathFrame section = generator.GetSectionAt(m);
YourObject.transform.position = generator.transform.TransformPoint(section.position);
YourObject.transform.rotation = generator.transform.rotation * (Quaternion.LookRotation(section.tangent,section.binormal));

----------

Quote:I also tried the solution from this thread, which needed a bit of updating. I'm not sure if I'm doing this correctly. I am getting a solver index of 0 for both the first and last particle.

That thread is quite old, won't work in Obi 5.X and up. You're getting the first and last particles from the first batch in the blueprint. You should be getting the first particle from the first batch, and the last particle from the last batch in the solver. For details, see:
http://obi.virtualmethodstudio.com/tutor...aints.html

It's way easier to use either of the above methods.

let me know if I can be of further help. cheers!
Reply
#4
(07-04-2021, 10:21 AM)josemendez Wrote: As you know, the ObiPathSmoother generates an intermediate representation of the rope that is used for rendering (see: http://obi.virtualmethodstudio.com/tutor...modes.html)

You can also get smoothed path positions along the rope, instead of working with raw particles/elements. For this you can use the path generator's GetSectionAt() method, that also takes a normalized coordinate as input. For instance, if you wanted to place an object at a position and orientation:

Code:
var generator = GetComponent<ObiPathSmoother>();
ObiPathFrame section = generator.GetSectionAt(m);
YourObject.transform.position = generator.transform.TransformPoint(section.position);
YourObject.transform.rotation = generator.transform.rotation * (Quaternion.LookRotation(section.tangent,section.binormal));

Thank you, this is exactly what I was after- however I'm still having some issues when the rope is shorter than it's starting length. 

When I reduce the rope length and then run this code, for some reason the dynamic particle attachment doesn't hold the object. 

Here is a quick example video. The first time a car is picked up, the rope length isn't changed. The second time the rope is made shorter than it's initial length. 

When the magnet collides w the car, it changes the dynamic attachment target from the magnet to the car, and sets itself as a kinematic rigidbody, parented to the car

When releasing the car, the dynamic attachment target is set to null, the magnet is moved to match the end of the rope, set to a non-kinematic rigidbody, and the dynamic attachment target is set back to the magnet.
Reply