Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  get position of particles
#1
Hello, 

I'm trying to retrieve the particle positions of 2 Obi Cloth Objectives.

In my scenario, i just created 2 flags with obi cloth blueprints. The two flags are on the same solver but in different world positions. 
Code:
ObiCloth cloth1 = Flag1.GetComponent<ObiCloth>();       
ObiCloth cloth2 = Flag2.GetComponent<ObiCloth>();

cloth1 is assigned to the 1st Flag and cloth2 to the 2nd. All good so far (or at least i think so.)

However, when i use, for example:
Code:
Debug.Log(cloth1.GetParticlePosition(0));

Debug.Log(cloth2.GetParticlePosition(0));

The result is exactly the same Vector3, despite the 2 flags being on different positions 
No matter where i put the flags, the result is always the same.

[Image: baCerXH.png]


Am i missing something? Any suggestions?
Reply
#2
Hi there!

From the API docs on GetParticlePosition:


Quote:Given a solver particle index, returns the position of that particle in world space.

Parameters:
solverIndex Index of the particle in the solver arrays.

Returns:
The position of a given particle in world space.

Since you're passing the same index to both calls (0), you get the same position, from the same particle.

You should use the following instead:

Code:
Debug.Log(cloth1.GetParticlePosition(cloth1.solverIndices[0]));
Debug.Log(cloth2.GetParticlePosition(cloth2.solverIndices[0]));

Note that particle indices come in two flavors: actor indices and solver indices. The first particle in the actor might be particle 237 (or any other) in the solver, depending on how many actors have been instantiated and in what order.

let me know how it goes!Sonrisa
Reply
#3
Hello again and thank you for the super fast reply.

It looks like your reccomendation solved my issue.

However i still have a problem.

My goal in this small task is to stitch the 2 flags togher using script. More specifficaly i want to stitch together only the parts  that overlap.

What i am doing so far is that i try to create 2 lists containing all the particle positions of the 2 flags. Then intersect these 2 lists and stitch the flags in the common particle positions.

At the moment this works only if i put one flag 100% on top of the other.  Indeed the interesction list has the same length (count) as the number of vertices (289) of both flags, which is expected i
[Image: aFXRcdu.png]
This results into all particles being 100% in same positions so the 2 flags are 100% stitched together.

If i try move one flag slightly, even though they have a lot of area overlapping, the list intersection is not detecting any common particle locations
[Image: DF0EGQQ.png]
In this case the common particles list returns 0 locations as common and a result they are not stitched.

I think again i am missing something related to the particle positions, (or maybe they are just no common particles at all?)

edit:
visualizing the particles of the 2 flags gives me this:
[Image: XHZ9GpF.png]
it looks like there should be common particles but there are none are detected.
Reply
#4
Hi there!

Could you share the script you're using to implement this?

Off the top of my head: in case you're comparing particle positions directly using the == operator, floating point precision issues can cause the comparison to always fail. Using Math.Approximately() would be a better approach.
Reply
#5
Hey again,

ok first of all i created 2 lists with the particle positions of each flag which is working.
Code:
  for (int i = 0; i <= 288; i++)
        {
            clothParticles1.Add(cloth1.GetParticlePosition(cloth1.solverIndices[i]));
            clothParticles2.Add(cloth2.GetParticlePosition(cloth2.solverIndices[i]));
        
        }
Then tried couple ways to compare. 
Code:
foreach (Vector3 i in clothParticles1)
        {
            if (clothParticles2.Contains(i))
            {
                stitchlist.Add(i);
            }

        }
and
Code:
List<Vector3> stitchlist = new List<Vector3>(clothParticles1.Intersect(clothParticles2));

Both the above returned the correct value of the list length (289 because the 2 flags have 17x17 vertices) only when the 2 flags were 100% on the same position.
Reply
#6
I don’t think you can reliably use list intersection() or contains() operations when the contents are floating point data. These use the type’s default comparer. This won’t work unless you provide a custom comparer that uses an epsilon to tell if two Vector3 are close enough to each other. Unless the particle positions are *exactly* the same, a direct comparison between floating point values is very likely to fail.

See: https://docs.unity3d.com/ScriptReference...ately.html
Reply
#7
(19-02-2021, 04:11 PM)josemendez Wrote: I don’t think you can reliably use list intersection() or contains() operations when the contents are floating point data. These use the type’s default comparer. This won’t work unless you provide a custom comparer that uses an epsilon to tell if two Vector3 are close enough to each other. Unless the particle positions are *exactly* the same, a direct comparison between floating point values is very likely to fail.

See: https://docs.unity3d.com/ScriptReference...ately.html
Hello and thanks for the reccomendation!

Using what you said and adding some checkings i managed to achieve what i wanted
Code:
for (int i = 0; i < 289; i++)
        {
            for (int j = 0; j < 289; j++)
            {
                if (Mathf.Approximately(clothParticles1[i].y, clothParticles2[j].y))
                {
                    if (Mathf.Approximately(clothParticles1[i].x,clothParticles2[j].x))
                    {
                        stitcher.AddStitch(i, j);
                    }
                }               
            }
        }
The above code succesfully stitches the 2 flags only on the overlaping positions.
Reply