Obi Official Forum
Obi Handle and fixing particles at runtime - Printable Version

+- Obi Official Forum (https://obi.virtualmethodstudio.com/forum)
+-- Forum: Obi Users Category (https://obi.virtualmethodstudio.com/forum/forum-1.html)
+--- Forum: Obi Softbody (https://obi.virtualmethodstudio.com/forum/forum-12.html)
+--- Thread: Obi Handle and fixing particles at runtime (/thread-1360.html)



Obi Handle and fixing particles at runtime - msw201089 - 10-09-2019

I am running into an interesting problem. I am trying to create a new gameobject, attach an Obi Particle Handle component to it, set a particles mass and velocity to 0, then add that particle to the handle. I have tried to do this in almost every order possible by creating the gameobject first, adding the particle first, zeroing out mass and velocity first, and no matter what order the operations are done in inevitably the model freaks out and disappears, or only the particle itself freaks out. I have also tried to setup the handle in the editor and then disable and enable it at runtime but this also causes weird behavior.

Code sample:
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;

public class ObiSoftBodyTester : MonoBehaviour
{
    ObiActor actor;

    public GameObject runtimeHandleGO;
    public ObiParticleHandle newHandle;
    public ObiSolver mySolver;

    // Start is called before the first frame update
    void Start()
    {
        actor = GetComponent<ObiActor>();
        Debug.Log(actor);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            RunInit();
        }
    }

    public void RunInit()
    {
        runtimeHandleGO = new GameObject();

        newHandle = runtimeHandleGO.AddComponent<ObiParticleHandle>();
        newHandle.Actor = actor;

        newHandle.transform.position = actor.GetParticlePosition(actor.particleIndices[0]);

        /*
        mySolver.velocities[0] = Vector3.zero;
        mySolver.invMasses[0] = 0;
        */

        /*
        actor.velocities[0] = Vector3.zero;
        actor.invMasses[0] = 0;
        actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);
        */

        newHandle.AddParticle(0, actor.GetParticlePosition(actor.particleIndices[0]), Quaternion.identity, actor.invMasses[0], 0.0f);

        /*
        mySolver.velocities[0] = Vector3.zero;
        mySolver.invMasses[0] = 0;
        */

        actor.velocities[0] = Vector3.zero;
        actor.invMasses[0] = 0;
        actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);

        Debug.Log(newHandle.ParticleCount);
    }
}

I have this script attached to the dragon in the sample scene from the Obi softbody asset.

Basically, I'm not sure if my code is causing the problems, I'm going about this the wrong way, or if I've found a bug.

Any help would be appreciated.

Unity version 2019.2.0f1


RE: Obi Handle and fixing particles at runtime - josemendez - 13-09-2019

(10-09-2019, 09:33 PM)msw201089 Wrote: I am running into an interesting problem. I am trying to create a new gameobject, attach an Obi Particle Handle component to it, set a particles mass and velocity to 0, then add that particle to the handle. I have tried to do this in almost every order possible by creating the gameobject first, adding the particle first, zeroing out mass and velocity first, and no matter what order the operations are done in inevitably the model freaks out and disappears, or only the particle itself freaks out. I have also tried to setup the handle in the editor and then disable and enable it at runtime but this also causes weird behavior.

Code sample:
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;

public class ObiSoftBodyTester : MonoBehaviour
{
    ObiActor actor;

    public GameObject runtimeHandleGO;
    public ObiParticleHandle newHandle;
    public ObiSolver mySolver;

    // Start is called before the first frame update
    void Start()
    {
        actor = GetComponent<ObiActor>();
        Debug.Log(actor);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            RunInit();
        }
    }

    public void RunInit()
    {
        runtimeHandleGO = new GameObject();

        newHandle = runtimeHandleGO.AddComponent<ObiParticleHandle>();
        newHandle.Actor = actor;

        newHandle.transform.position = actor.GetParticlePosition(actor.particleIndices[0]);

        /*
        mySolver.velocities[0] = Vector3.zero;
        mySolver.invMasses[0] = 0;
        */

        /*
        actor.velocities[0] = Vector3.zero;
        actor.invMasses[0] = 0;
        actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);
        */

        newHandle.AddParticle(0, actor.GetParticlePosition(actor.particleIndices[0]), Quaternion.identity, actor.invMasses[0], 0.0f);

        /*
        mySolver.velocities[0] = Vector3.zero;
        mySolver.invMasses[0] = 0;
        */

        actor.velocities[0] = Vector3.zero;
        actor.invMasses[0] = 0;
        actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);

        Debug.Log(newHandle.ParticleCount);
    }
}

I have this script attached to the dragon in the sample scene from the Obi softbody asset.

Basically, I'm not sure if my code is causing the problems, I'm going about this the wrong way, or if I've found a bug.

Any help would be appreciated.

Unity version 2019.2.0f1

Hi there,

After modifying particle masses in a softbody, a call to Oni.CalculateRestShapeMatching() is required, like so:

Code:
foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
               Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);

This is because shape matching relies on a rest configuration of the particles, basically their position and mass. If this rest configuration is altered you need to notify the engine.


RE: Obi Handle and fixing particles at runtime - msw201089 - 13-09-2019

So I tried to integrate the code that you gave and the behavior is still the same. I have attached a link to a youtube video that shows what happens when the key is pressed to execute the function in the code. I hope that you can derive a little more information about what\'s going on than I can because it just looks like the point is being updated by 2 separate things that are fighting for the position it is in.

I have also inserted the modification to the code I made. I tried the piece before and after pushing the actor data to the solver. As well as trying before and after the attaching of the handle and in all the situations the behavior was the same. I left the positions I tried the code in with what I sent to show where I tried it.

I will get in contact with support if it seems that this is something that shouldn't be happening but I wanted to confirm that it wasn't an error on my side before I did.

Thanks for the help so far though!

https://www.youtube.com/watch?v=MiISRnw3OWo&feature=youtu.be



Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;

public class ObiSoftBodyTester : MonoBehaviour
{
   ObiActor actor;

   public GameObject runtimeHandleGO;
   public ObiParticleHandle newHandle;
   public ObiSolver mySolver;

   // Start is called before the first frame update
   void Start()
   {
       actor = GetComponent<ObiActor>();
       Debug.Log(actor);
   }

   // Update is called once per frame
   void Update()
   {
       if (Input.GetKeyDown(KeyCode.A))
       {
           RunInit();
       }
   }

   public void RunInit()
   {
       runtimeHandleGO = new GameObject();

       newHandle = runtimeHandleGO.AddComponent<ObiParticleHandle>();
       newHandle.Actor = actor;

       newHandle.transform.position = actor.GetParticlePosition(actor.particleIndices[0]);

       /*
       mySolver.velocities[0] = Vector3.zero;
       mySolver.invMasses[0] = 0;
       */

       actor.velocities[0] = Vector3.zero;
       actor.invMasses[0] = 0;

       /*
       foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
       {
           Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);
       }
       */

       actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);

       /*
       foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
       {
           Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);
       }
       */

       newHandle.AddParticle(0, actor.GetParticlePosition(actor.particleIndices[0]), Quaternion.identity, actor.invMasses[0], 0.0f);

       foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
       {
           Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);
       }

       /*
       mySolver.velocities[0] = Vector3.zero;
       mySolver.invMasses[0] = 0;
       */

       /*
       actor.velocities[0] = Vector3.zero;
       actor.invMasses[0] = 0;
       actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);
       */

       Debug.Log(newHandle.ParticleCount);
   }
}


Quote:josemendez
Hi there,

After modifying particle masses in a softbody, a call to Oni.CalculateRestShapeMatching() is required, like so:

Code:
foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
               Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);

This is because shape matching relies on a rest configuration of the particles, basically their position and mass. If this rest configuration is altered you need to notify the engine.



RE: Obi Handle and fixing particles at runtime - josemendez - 14-09-2019

(13-09-2019, 05:58 PM)msw201089 Wrote: So I tried to integrate the code that you gave and the behavior is still the same. I have attached a link to a youtube video that shows what happens when the key is pressed to execute the function in the code. I hope that you can derive a little more information about what\'s going on than I can because it just looks like the point is being updated by 2 separate things that are fighting for the position it is in.

I have also inserted the modification to the code I made. I tried the piece before and after pushing the actor data to the solver. As well as trying before and after the attaching of the handle and in all the situations the behavior was the same. I left the positions I tried the code in with what I sent to show where I tried it.

I will get in contact with support if it seems that this is something that shouldn't be happening but I wanted to confirm that it wasn't an error on my side before I did.

Thanks for the help so far though!

https://www.youtube.com/watch?v=MiISRnw3OWo&feature=youtu.be



Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;

public class ObiSoftBodyTester : MonoBehaviour
{
   ObiActor actor;

   public GameObject runtimeHandleGO;
   public ObiParticleHandle newHandle;
   public ObiSolver mySolver;

   // Start is called before the first frame update
   void Start()
   {
       actor = GetComponent<ObiActor>();
       Debug.Log(actor);
   }

   // Update is called once per frame
   void Update()
   {
       if (Input.GetKeyDown(KeyCode.A))
       {
           RunInit();
       }
   }

   public void RunInit()
   {
       runtimeHandleGO = new GameObject();

       newHandle = runtimeHandleGO.AddComponent<ObiParticleHandle>();
       newHandle.Actor = actor;

       newHandle.transform.position = actor.GetParticlePosition(actor.particleIndices[0]);

       /*
       mySolver.velocities[0] = Vector3.zero;
       mySolver.invMasses[0] = 0;
       */

       actor.velocities[0] = Vector3.zero;
       actor.invMasses[0] = 0;

       /*
       foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
       {
           Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);
       }
       */

       actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);

       /*
       foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
       {
           Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);
       }
       */

       newHandle.AddParticle(0, actor.GetParticlePosition(actor.particleIndices[0]), Quaternion.identity, actor.invMasses[0], 0.0f);

       foreach (ObiShapeMatchingConstraintBatch batch in ((ObiSoftbody)actor).ShapeMatchingConstraints.GetBatches())
       {
           Oni.CalculateRestShapeMatching(actor.Solver.OniSolver, batch.OniBatch);
       }

       /*
       mySolver.velocities[0] = Vector3.zero;
       mySolver.invMasses[0] = 0;
       */

       /*
       actor.velocities[0] = Vector3.zero;
       actor.invMasses[0] = 0;
       actor.PushDataToSolver(ParticleData.INV_MASSES | ParticleData.VELOCITIES);
       */

       Debug.Log(newHandle.ParticleCount);
   }
}

Hi,

If adding a handle at runtime, particle masses are not modified until the actor gets added to the solver at the start of the scene. So you're actually calling the code I gave before the masses are modified, not after.

You could call this by subscribing to the solver add event, but for ease of use I modified ObiParticleHandle.cs for you to do it automatically. Find the code attached.


RE: Obi Handle and fixing particles at runtime - manurocker95 - 14-11-2019

(14-09-2019, 11:13 AM)josemendez Wrote: Hi,

If adding a handle at runtime, particle masses are not modified until the actor gets added to the solver at the start of the scene. So you're actually calling the code I gave before the masses are modified, not after.

You could call this by subscribing to the solver add event, but for ease of use I modified ObiParticleHandle.cs for you to do it automatically. Find the code attached.

trying both scripts gives me:

Invalid localAABB. Object transform is corrupt.


transform.position assign attempt for 'Dragon' is not valid. Input position is { NaN, NaN, NaN }.
UnityEngine.TransformConfundidoet_position(Vector3)
Obi.ObiSoftbody:OnSolverStepEnd(Single) (at Assets/Obi/Scripts/Actors/ObiSoftbody.cs:65)
Obi.ObiSolver:AllSolversStepEnd() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:877)
Obi.ObiArbiter:WaitForAllSolvers() (at Assets/Obi/Scripts/Solver/ObiArbiter.cs:45)
Obi.ObiSolver:WaitForAllSolvers() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:784)
Obi.ObiSolver:SimulateStep(Single) (at Assets/Obi/Scripts/Solver/ObiSolver.cs:672)
Obi.ObiSolver:FixedUpdate() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:866)

(14-11-2019, 12:26 PM)manurocker95 Wrote: trying both scripts gives me:

Invalid localAABB. Object transform is corrupt.


transform.position assign attempt for 'Dragon' is not valid. Input position is { NaN, NaN, NaN }.
UnityEngine.TransformConfundidoet_position(Vector3)
Obi.ObiSoftbody:OnSolverStepEnd(Single) (at Assets/Obi/Scripts/Actors/ObiSoftbody.cs:65)
Obi.ObiSolver:AllSolversStepEnd() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:877)
Obi.ObiArbiter:WaitForAllSolvers() (at Assets/Obi/Scripts/Solver/ObiArbiter.cs:45)
Obi.ObiSolver:WaitForAllSolvers() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:784)
Obi.ObiSolver:SimulateStep(Single) (at Assets/Obi/Scripts/Solver/ObiSolver.cs:672)
Obi.ObiSolver:FixedUpdate() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:866)

Closing Unity and opening it again made it working but I have the same issue. Can you provide an example scene where handles are created in runtime?




RE: Obi Handle and fixing particles at runtime - josemendez - 14-11-2019

(14-11-2019, 12:26 PM)manurocker95 Wrote: trying both scripts gives me:

Invalid localAABB. Object transform is corrupt.


transform.position assign attempt for 'Dragon' is not valid. Input position is { NaN, NaN, NaN }.
UnityEngine.TransformConfundidoet_position(Vector3)
Obi.ObiSoftbody:OnSolverStepEnd(Single) (at Assets/Obi/Scripts/Actors/ObiSoftbody.cs:65)
Obi.ObiSolver:AllSolversStepEnd() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:877)
Obi.ObiArbiter:WaitForAllSolvers() (at Assets/Obi/Scripts/Solver/ObiArbiter.cs:45)
Obi.ObiSolver:WaitForAllSolvers() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:784)
Obi.ObiSolver:SimulateStep(Single) (at Assets/Obi/Scripts/Solver/ObiSolver.cs:672)
Obi.ObiSolver:FixedUpdate() (at Assets/Obi/Scripts/Solver/ObiSolver.cs:866)


Closing Unity and opening it again made it working but I have the same issue. Can you provide an example scene where handles are created in runtime?


Hi there,

Here's a sample "Grabber" script (find it attached), that acts as a runtime handle able to grab and release any particles in contact with a collider.

A video of it: