Obi Official Forum
Help Flickering - solvers effect each other - Printable Version

+- Obi Official Forum (https://obi.virtualmethodstudio.com/forum)
+-- Forum: Obi Users Category (https://obi.virtualmethodstudio.com/forum/forum-1.html)
+--- Forum: Obi Fluid (https://obi.virtualmethodstudio.com/forum/forum-3.html)
+--- Thread: Help Flickering - solvers effect each other (/thread-966.html)



Flickering - solvers effect each other - shayk - 09-03-2019

Hi All,
First of all - I have to say that i really like this product, simulations are very realistic, fast, configurable - well done! (documentation could be improvedSonrisa

using unity 2018.2.1f1 
using Obi 4.0.2

My real scene is a little complex with many moving solvers/emitters, so I built a simple demo scene to demonstrate the problem.
In general: fluid stream collide with a sphere, collided particles are being killed, and for every killed particle a new particle is emitted from a local emitter on the sphere

The demo scene includes the following GameObjects/Components:
1)MainSolver - Empty with a solver (global space) and a script MainCollisionDetection(described bellow)
(solver constraints copied from Obi sample scene "FluidViscosity")
2)MainEmitter - Empty with an ObiEmitter (that uses MainSolver as its solver) and particle renderer
  emitter properties: speed: 5, emitter material: Honey, collision material :very sticky
3)Sphere - unity sphere with ObiCollider ,RB, and ObiRB
  a)SphereSolver - child of Sphere - Empty with a solver (local space)
    (solver constraints copied from Obi sample scene "FluidViscosity")
    1. SphereEmitter - child of SphereSolver - empty with an ObiEmitter (that uses SphereSolver as its solver) and particle renderer
       emitter properties: speed: controlled by script SphereEmitionControl (described bellow), emitter material: Honey, collision material :very sticky 

4)MainCollisionDetection script detects collisions (on MainSolver), kills the hitting particle, and adds the particle collision data to a queue in the SphereEmitionControl script
Code:
using System.Collections.Generic;
using UnityEngine;
using Obi;

public class MainCollisionDetection : MonoBehaviour {

   public ObiEmitter mainEmitter;
   ObiSolver solver;

   Obi.ObiSolver.ObiCollisionEventArgs frame;
   List<int> allreadyEmittedParticles;

   void Awake()
   {
       solver = GetComponent<Obi.ObiSolver>();
   }

   void OnEnable()
   {
       solver.OnCollision += Solver_OnCollision;
   }

   void OnDisable()
   {
       solver.OnCollision -= Solver_OnCollision;
   }
   
   void Solver_OnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
   {
       frame = e;
       if (solver == null || frame == null || frame.contacts == null) return;

       allreadyEmittedParticles = new List<int>();
       int closeContacts = 0;

       for (int i = 0; i < frame.contacts.Count; ++i)
       {
           
           if (frame.contacts[i].distance < 0.001f)
           {
               Component contactColl;
               ObiCollider.idToCollider.TryGetValue(frame.contacts[i].other, out contactColl);

               if (contactColl != null)
               {
                   ObiSolver.ParticleInActor pa = solver.particleToActor[frame.contacts[i].particle];
                   ObiEmitter emtr = pa.actor as ObiEmitter;
                   int particleIndexInEmitter = pa.indexInActor;

                   if (!allreadyEmittedParticles.Contains(particleIndexInEmitter))
                   {
                       allreadyEmittedParticles.Add(particleIndexInEmitter);
                       closeContacts++;

                       Vector3 point = frame.contacts[i].point;
                       Vector3 normal = frame.contacts[i].normal;

                       //kill hit particle in the main emitter
                       emtr.life[particleIndexInEmitter] = 0;

                       //look for the hitted collider emitter
                       ObiEmitter colliderEmitter = contactColl.GetComponentInChildren<ObiEmitter>();
                       
                       if (colliderEmitter != null)
                       {
                           SphereEmitionControl sphereEmitionControl = colliderEmitter.GetComponent<SphereEmitionControl>();

                           //add particle to collider emitter queue
                           sphereEmitionControl.AddParticleToEmit(point, Quaternion.Euler(normal));
                       }
                   }
               }  
           }
       }
   }
}

5)SphereEmitionControl script has a queue of particles positions/normals, it is filled only by data from MainCollisionDetection script.  The script repeatedly checks if the queue is not empty, it dequeues the data, move its transform to the stored position/normal and emit for a short while (i didn't know how to emit one particle so i timed the emittion with a coroutine)
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;


public class ParticleToEmit
{
   public Vector3 pos;
   public Quaternion localRot;
}

public class SphereEmitionControl : MonoBehaviour {

   ObiEmitter m_emitter;
   bool emitting;
   Queue<ParticleToEmit> particlesToEmit;

   void Start()
   {
       m_emitter = GetComponent<ObiEmitter>();
       m_emitter.speed = 0f;
       particlesToEmit = new Queue<ParticleToEmit>();
   }

   void LateUpdate()
   {
       if (particlesToEmit.Count > 0 && !emitting)
       {
           ParticleToEmit par = particlesToEmit.Dequeue();
           transform.position = par.pos;
           transform.localRotation = par.localRot;
           StartCoroutine(ColliderEmitterEmit());
       }
   }

   //add a particle data to queue
   public void AddParticleToEmit(Vector3 pos, Quaternion localRot)
   {
       ParticleToEmit newParticle = new ParticleToEmit();
       newParticle.pos = pos;
       newParticle.localRot = localRot;
       particlesToEmit.Enqueue(newParticle);
   }

   //emit particle
   public IEnumerator ColliderEmitterEmit()
   {
       emitting = true;
       
       m_emitter.speed = 1f;
       m_emitter.EmitParticle(0);

       yield return null;
       
       m_emitter.speed = 0f;

       emitting = false;
   }
}


Regarding the collisions the scripts run OK , the problem is : the particles (emitted from SphereEmitter) are flickering.
I did some testing and found that:
case a: while running - if i disable the MainSolver (in the editor) the flickering stops (strange, it should not effect the scene because the particles belong to the SphereSolver)
case b: while running - if the MainSolver is enabled, and i disable and than enable the SphereSolver - flickering stops, and everything works well as expected, but now if i disable and than enable the MainSolver, flickering starts again

why does the flickering happen?
how to prevent it?

thanks,
shayk


RE: Flickering - solvers effect each other - shayk - 14-03-2019

Hi,

I could really use some help with this...
thank you


RE: Flickering - solvers effect each other - josemendez - 19-03-2019

(14-03-2019, 09:36 AM)shayk Wrote: Hi,

I could really use some help with this...
thank you

Hi Shayk,

We have tried a similar set up to the one you described, but particles do not flicker for us. Maybe there's some difference in the way we set up the scene. We'd be more than glad to take a look at yours and diagnose it, feel free to send a minimal repro project to support(at)virtualmethodstudio.com

thanks!