Obi Official Forum
Manually Placing Rope Particles - Printable Version

+- Obi Official Forum (https://obi.virtualmethodstudio.com/forum)
+-- Forum: Obi Users Category (https://obi.virtualmethodstudio.com/forum/forum-1.html)
+--- Forum: Obi Rope (https://obi.virtualmethodstudio.com/forum/forum-4.html)
+--- Thread: Manually Placing Rope Particles (/thread-50.html)



Manually Placing Rope Particles - PhantomBadger - 17-07-2017

I'm looking to sync the position of the rope over a network, my initial test is getting the positions of the particles via the
Code:
ObiRope.GetParticles(index)

method, networking these values, then setting them on the other side, however I cannot seem to set them. My current attempt is as follows;

Code:
   private void SetPositions()
   {
       if (entity.isAttached)
       {
           for (int i = 0; i < ObiRope.UsedParticles && i < PositionArrayHardLimit; i++)
           {
               state.RopePositions[i] = ObiRope.GetParticlePosition(i);
           }
       }
   }

   private void GetPositions()
   {
       if (entity.isAttached)
       {
           for (int i = 0; i < ObiRope.UsedParticles && i < PositionArrayHardLimit; i++)
           {
               ObiRope.Solver.renderablePositions[ObiRope.particleIndices[i]] = state.RopePositions[i];
               ObiRope.Solver.UpdateActiveParticles();
           }
       }
   }
I can confirm that state.RopePositions contains the correct values when referenced by the client, but I'm unable to tell the solver to use these positions. Is this a thing that is even possible with ObiRope? Am I going about this all wrong? Any help would be appreciated!


RE: Manually Placing Rope Particles - josemendez - 17-07-2017

(17-07-2017, 02:02 PM)PhantomBadger Wrote: I'm looking to sync the position of the rope over a network, my initial test is getting the positions of the particles via the


Code:
ObiRope.GetParticles(index)

method, networking these values, then setting them on the other side, however I cannot seem to set them. My current attempt is as follows;



Code:
   private void SetPositions()
   {
       if (entity.isAttached)
       {
           for (int i = 0; i < ObiRope.UsedParticles && i < PositionArrayHardLimit; i++)
           {
               state.RopePositions[i] = ObiRope.GetParticlePosition(i);
           }
       }
   }

   private void GetPositions()
   {
       if (entity.isAttached)
       {
           for (int i = 0; i < ObiRope.UsedParticles && i < PositionArrayHardLimit; i++)
           {
               ObiRope.Solver.renderablePositions[ObiRope.particleIndices[i]] = state.RopePositions[i];
               ObiRope.Solver.UpdateActiveParticles();
           }
       }
   }
I can confirm that state.RopePositions contains the correct values when referenced by the client, but I'm unable to tell the solver to use these positions. Is this a thing that is even possible with ObiRope? Am I going about this all wrong? Any help would be appreciated!

GetParticlePosition() returns the final rendered position of a particle, so it's good when you want to post-process particle positions each frame. Not good at all if you want to transfer positions to another rope. The rendered position is usually not the same as the actual, physical position in the simulation due to several reasons:

- The rendered position might be the result of interpolating the previous frame's position and the current one (when the solver has interpolation enabled).
- Modifiers such as particle smoothing might offset the particle position only for rendering purposes. This modified position is not fed back into the simulation for the next frame.

The easiest (and fastest) way to do what you look for is to use the low-level getters/setters. These give you access to the solver particle positions/velocities/masses/etc directly. Take a look at the last part of this page:

http://obi.virtualmethodstudio.com/tutorials/scriptingparticles.html


RE: Manually Placing Rope Particles - PhantomBadger - 18-07-2017

(17-07-2017, 03:43 PM)josemendez Wrote: GetParticlePosition() returns the final rendered position of a particle, so it's good when you want to post-process particle positions each frame. Not good at all if you want to transfer positions to another rope. The rendered position is usually not the same as the actual, physical position in the simulation due to several reasons:

- The rendered position might be the result of interpolating the previous frame's position and the current one (when the solver has interpolation enabled).
- Modifiers such as particle smoothing might offset the particle position only for rendering purposes. This modified position is not fed back into the simulation for the next frame.

The easiest (and fastest) way to do what you look for is to use the low-level getters/setters. These give you access to the solver particle positions/velocities/masses/etc directly. Take a look at the last part of this page:

http://obi.virtualmethodstudio.com/tutorials/scriptingparticles.html

That's brilliant! Thank you Sonrisa
My final solution, should anyone else need it, is as follows;

Code:
   /// <summary>
   /// Sets the rope's current positions to the network using the Oni C++ Solver
   /// </summary>
   private void SetPositions()
   {
       if (entity.isAttached)
       {
           //Get the particle positions through the Oni .dll
           Vector4[] particlePositions = new Vector4[ObiRope.UsedParticles];
           Oni.GetParticlePositions(ObiRope.Solver.OniSolver, particlePositions, ObiRope.UsedParticles, ObiRope.particleIndices[0]);

           //Bind them to the network until we're done or hit the hard limit
           for (int i = 0; i < particlePositions.Length && i < PositionArrayHardLimit; i++)
           {
               state.RopePositions[i] = particlePositions[i];
           }
       }
   }

   /// <summary>
   /// Gets the rope's current positions from the network and sets our locals to that
   /// </summary>
   private void GetPositions()
   {
       if (entity.isAttached)
       {
           //Create a temporary array to hold all the particles we use
           Vector4[] newPositions = new Vector4[ObiRope.UsedParticles];

           //Retrieve the values from the network until we have them all or hit our hard limit
           for (int i = 0; i < newPositions.Length && i < PositionArrayHardLimit; i++)
           {
               newPositions[i] = state.RopePositions[i];
           }

           //Set the particle positions using the Oni .dll in order to apply to the rope
           Oni.SetParticlePositions(ObiRope.Solver.OniSolver, newPositions, newPositions.Length, ObiRope.particleIndices[0]);
           //Oni.ApplyPositionInterpolation(ObiRope.Solver.OniSolver, Time.fixedDeltaTime); Maybe ???
       }
   }