Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Buoyancy diffusion not working
#1
I'm trying to change buoyancy for each particle to make them move upward.

I used user data and map Buoyancy to one of the slots, but when I change the value nothing happens to particles.

Here is part of my code:

Code:
void Start()
{
    solver.OnCollision += Solver_OnCollision;
    emitter.OnEmitParticle += Emitter_OnEmitParticle;
}


void Emitter_OnEmitParticle(ObiEmitter em, int particleIndex)
{
    int k = emitter.solverIndices[particleIndex];
    Vector4 userData = emitter.solver.userData[k];
    userData[0] = solver.buoyancies[k];
    emitter.solver.userData[k] = userData;
}


private void Solver_OnCollision(ObiSolver s, ObiSolver.ObiCollisionEventArgs e)
{
    var world = ObiColliderWorld.GetInstance();
    foreach (Oni.Contact contact in e.contacts)
    {

        if (contact.distance < 0.01f)
        {
            var col = world.colliderHandles[contact.other].owner;
            var userData = solver.userData[contact.particle];
                 
            if (evaporators[0].collider == col)
            {
                userData[0] = 0;
            }

            solver.userData[contact.particle] = userData;
        }
    }
}

Could you please help me?
Reply
#2
(05-01-2021, 11:40 AM)Booyaka Wrote: I'm trying to change buoyancy for each particle to make them move upward.

I used user data and map Buoyancy to one of the slots, but when I change the value nothing happens to particles.

Here is part of my code:

Code:
void Start()
{
    solver.OnCollision += Solver_OnCollision;
    emitter.OnEmitParticle += Emitter_OnEmitParticle;
}


void Emitter_OnEmitParticle(ObiEmitter em, int particleIndex)
{
    int k = emitter.solverIndices[particleIndex];
    Vector4 userData = emitter.solver.userData[k];
    userData[0] = solver.buoyancies[k];
    emitter.solver.userData[k] = userData;
}


private void Solver_OnCollision(ObiSolver s, ObiSolver.ObiCollisionEventArgs e)
{
    var world = ObiColliderWorld.GetInstance();
    foreach (Oni.Contact contact in e.contacts)
    {

        if (contact.distance < 0.01f)
        {
            var col = world.colliderHandles[contact.other].owner;
            var userData = solver.userData[contact.particle];
                 
            if (evaporators[0].collider == col)
            {
                userData[0] = 0;
            }

            solver.userData[contact.particle] = userData;
        }
    }
}

Could you please help me?

You don’t seem to write back any data to the buoyancies array, you’re just writing values to the userData array.

Check the Raclette sample scene for reference. You need to write the userData values back to the array you wish to use, in this case, the buoyancies array.
Reply
#3
(05-01-2021, 07:47 PM)josemendez Wrote: You don’t seem to write back any data to the buoyancies array, you’re just writing values to the userData array.

Check the Raclette sample scene for reference. You need to write the userData values back to the array you wish to use, in this case, the buoyancies array.

I can't find the problem. Everything is just like "Melt" & "ViscositySurfTensionToUserData" scripts in Raclette sample.
Could you please mention it more precisely?

The weird thing is that the code will work for color but not any other parameters like viscosity, buoyancy, etc.
Reply
#4
This is what's happening in your script:

When you emit a new particle, you store its buoyancy value in userData.
When a particle hits a collider, you set its userData to 0.
(when particles are simulated by Obi, the contents of userData are diffused)
But you never do solver.buoyancies[k] = something. So ofc, buoyancy values are never actually set to the diffused values in userData.

In the Raclette sample scene, you'll see there's a "ColorFromViscosity" component added to the emitter. In its LateUpdate() method, color is driven by viscosity, then viscosity and surface tension are set to whatever values are in userData[k][0] and userData[k][1]. That's what maps the userData values to viscosity and surface tension and that's precisely what you're missing.

To make it clear, these are the steps required:

  1. buoyancy ---> userData (every time a particle is emitted)
  2. userData undergoes diffusion (during simulation, done automatically)
  3. userData ----> buoyancy (after simulation) // you're missing this one.

Anytime after the simulation has taken place (that is, after FixedUpdate()), you need to copy back from userData to buoyancies. LateUpdate() is a good place.
Reply
#5
(06-01-2021, 08:18 AM)josemendez Wrote: This is what's happening in your script:

When you emit a new particle, you store its buoyancy value in userData.
When a particle hits a collider, you set its userData to 0.
(when particles are simulated by Obi, the contents of userData are diffused)
But you never do solver.buoyancies[k] = something. So ofc, buoyancy values are never actually set to the diffused values in userData.

In the Raclette sample scene, you'll see there's a "ColorFromViscosity" component added to the emitter. In its LateUpdate() method, color is driven by viscosity, then viscosity and surface tension are set to whatever values are in userData[k][0] and userData[k][1]. That's what maps the userData values to viscosity and surface tension and that's precisely what you're missing.

To make it clear, these are the steps required:

  1. buoyancy ---> userData (every time a particle is emitted)
  2. userData undergoes diffusion (during simulation, done automatically)
  3. userData ----> buoyancy (after simulation) // you're missing this one.

Anytime after the simulation has taken place (that is, after FixedUpdate()), you need to copy back from userData to buoyancies. LateUpdate() is a good place.

I added this code to my script and it works correctly


Code:
void LateUpdate()
{
    for (int i = 0; i < emitter.solverIndices.Length; ++i)
    {
        int k = emitter.solverIndices[i];
        emitter.solver.buoyancies[k] = emitter.solver.userData[k][0];
    }
}

Thank you so much!
Reply