예제 #1
0
        void solveColorMixing()
        {
            float strength = fluidSystemDef.colorMixingStrength;

            if (strength > 0)
            {
                for (int i = 0; i < contactBuffer.Count; i++)
                {
                    FluidParticleContact contact = contactBuffer [i];
                    if ((contact.a.flags & contact.b.flags & FluidParticleType.ColorMixingParticle) > 0)
                    {
                        Color a  = contact.a.color;
                        Color b  = contact.b.color;
                        float dr = (b.r - a.r) * strength;
                        float dg = (b.g - a.g) * strength;
                        float db = (b.b - a.b) * strength;
                        float da = (b.a - a.a) * strength;
                        a.r            += dr;
                        a.g            += dg;
                        a.b            += db;
                        a.a            += da;
                        b.r            -= dr;
                        b.g            -= dg;
                        b.b            -= db;
                        b.a            -= da;
                        contact.a.color = a;
                        contact.b.color = b;

                        float dm = (contact.b.mass - contact.a.mass) * strength;
                        contact.a.mass += dm;
                        contact.b.mass -= dm;
                    }
                }
            }
        }
예제 #2
0
        void solveViscous()
        {
            float viscousStrength = fluidSystemDef.viscousStrength;

            for (int i = 0; i < bodyContactBuffer.Count; i++)
            {
                FluidParticleBodyContact contact = bodyContactBuffer [i];
                if ((contact.fp.flags & FluidParticleType.ViscousParticle) > 0)
                {
//				b2Vec2 v = b->GetLinearVelocityFromWorldPoint(p) -
//					m_velocityBuffer.data[a];
                    Vector2 v = contact.body.velocity - contact.fp.velocity;
                    Vector2 f = viscousStrength * contact.mass * contact.weight * v;
                    contact.fp.velocity += getParticleInvMass() * f;
//				b->ApplyLinearImpulse(-f, p, true);
                }
            }
            for (int i = 0; i < contactBuffer.Count; i++)
            {
                FluidParticleContact contact = contactBuffer [i];
                if ((contact.flags & FluidParticleType.ViscousParticle) > 0)
                {
                    Vector2 v = contact.b.velocity - contact.a.velocity;
                    Vector2 f = viscousStrength * contact.weight * v;
                    contact.a.velocity += f;
                    contact.b.velocity -= f;
                }
            }
        }
예제 #3
0
        void solveDamping(float dt)
        {
            // reduces normal velocity of each contact
            float linearDamping    = fluidSystemDef.dampingStrength;
            float quadraticDamping = 1 / getCriticalVelocity(dt);

            for (int i = 0; i < bodyContactBuffer.Count; i++)
            {
                FluidParticleBodyContact contact = bodyContactBuffer [i];
                FluidParticle            a       = contact.fp;
                Vector2 p  = a.position;
                Vector2 v  = contact.body.velocity - a.velocity;
                float   vn = Vector2.Dot(v, contact.normal);
                if (vn < 0)
                {
                    float   damping = Mathf.Max(linearDamping * contact.weight, Mathf.Min(-quadraticDamping * vn, 0.5f));
                    Vector2 f       = damping * contact.mass * vn * contact.normal;
                    a.velocity += getParticleInvMass() * f;
                    contact.body.AddForceAtPosition(-f / dt, p);
                }
            }
            for (int i = 0; i < contactBuffer.Count; i++)
            {
                FluidParticleContact contact = contactBuffer [i];
                Vector2 v  = contact.b.velocity - contact.a.velocity;
                float   vn = Vector2.Dot(v, contact.normal);
                if (vn < 0)
                {
                    float   damping = Mathf.Max(linearDamping * contact.weight, Mathf.Min(-quadraticDamping * vn, 0.5f));
                    Vector2 f       = damping * vn * contact.normal;
                    contact.a.velocity += f;
                    contact.b.velocity -= f;
                }
            }
        }
예제 #4
0
        void addContact(FluidParticle a, FluidParticle b)
        {
            Vector2 d = b.position - a.position;
            float   distBtParticlesSq = d.sqrMagnitude;

            if (distBtParticlesSq < squaredDiameter)
            {
                float dist = Mathf.Sqrt(distBtParticlesSq);
                FluidParticleContact contact = new FluidParticleContact();
                contactBuffer.Add(contact);
                contact.a      = a;
                contact.b      = b;
                contact.flags  = a.flags | b.flags;
                contact.weight = 1 - dist * inverseDiameter;                // * (b.mass / a.mass);
                contact.normal = d / dist;
            }
        }
예제 #5
0
 void computeWeight()
 {
     for (int i = 0; i < count; i++)
     {
         particleBuffer [i].weight = 0;
     }
     for (int i = 0; i < bodyContactBuffer.Count; i++)
     {
         FluidParticleBodyContact contact = bodyContactBuffer [i];
         contact.fp.weight += contact.weight;
     }
     for (int i = 0; i < contactBuffer.Count; i++)
     {
         FluidParticleContact contact = contactBuffer [i];
         contact.a.weight += contact.weight;
         contact.b.weight += contact.weight;
     }
 }
예제 #6
0
        void solvePowder(float dt)
        {
            float powderStrength = fluidSystemDef.powderStrength * getCriticalVelocity(dt);
            float minWeight      = 1.0f - particleStride;

            for (int i = 0; i < contactBuffer.Count; i++)
            {
                FluidParticleContact contact = contactBuffer [i];
                if ((contact.flags & FluidParticleType.PowderParticle) > 0)
                {
                    if (contact.weight > minWeight)
                    {
                        Vector2 f = powderStrength * (contact.weight - minWeight) * contact.normal;
                        contact.a.velocity -= f;
                        contact.b.velocity += f;
                    }
                }
            }
        }
예제 #7
0
        void solveTensile(float dt)
        {
            for (int i = 0; i < count; i++)
            {
                particleBuffer [i].accumulation2 = Vector2.zero;
            }
            for (int i = 0; i < contactBuffer.Count; i++)
            {
                FluidParticleContact contact = contactBuffer [i];
                if ((contact.flags & FluidParticleType.TensileParticle) > 0)
                {
                    Vector2 weightedNormal = (1 - contact.weight) * contact.weight * contact.normal;
                    contact.a.accumulation2 -= weightedNormal;
                    contact.b.accumulation2 += weightedNormal;
                }
            }
            float criticalVelocity     = getCriticalVelocity(dt);
            float pressureStrength     = fluidSystemDef.surfaceTensionPressureStrength * criticalVelocity;
            float normalStrength       = fluidSystemDef.surfaceTensionNormalStrength * criticalVelocity;
            float maxVelocityVariation = maxParticleForce * criticalVelocity;

            for (int i = 0; i < contactBuffer.Count; i++)
            {
                FluidParticleContact contact = contactBuffer [i];
                if ((contact.flags & FluidParticleType.TensileParticle) > 0)
                {
                    float   h  = contact.a.weight + contact.b.weight;
                    Vector2 s  = contact.b.accumulation2 - contact.a.accumulation2;
                    float   fn = Mathf.Min(
                        pressureStrength * (h - 2) + normalStrength * Vector2.Dot(s, contact.normal),
                        maxVelocityVariation
                        ) * contact.weight;
                    Vector2 f = fn * contact.normal;
                    contact.a.velocity -= f;
                    contact.b.velocity += f;
                }
            }
        }
예제 #8
0
        void solveStaticPressure(float dt)
        {
            float criticalPressure  = getCriticalPressure(dt);
            float pressurePerWeight = fluidSystemDef.staticPressureStrength * criticalPressure;
            float maxPressure       = maxParticlePressure * criticalPressure;
            float relaxation        = fluidSystemDef.staticPressureRelaxation;

            for (int t = 0; t < fluidSystemDef.staticPressureIterations; t++)
            {
                for (int i = 0; i < count; i++)
                {
                    particleBuffer [i].accumulation = 0;
                }
                for (int i = 0; i < contactBuffer.Count; i++)
                {
                    FluidParticleContact contact = contactBuffer [i];
                    if ((contact.flags & FluidParticleType.StaticPressureParticle) > 0)
                    {
                        contact.a.accumulation += contact.weight * contact.b.staticPressure;
                        contact.b.accumulation += contact.weight * contact.a.staticPressure;
                    }
                }
                for (int i = 0; i < count; i++)
                {
                    FluidParticle fp = particleBuffer [i];
                    if ((fp.flags & FluidParticleType.StaticPressureParticle) > 0)
                    {
                        float h = (fp.accumulation + pressurePerWeight * (fp.weight - minParticleWeight)) / (fp.weight + relaxation);
                        fp.staticPressure = Mathf.Clamp(h, 0.0f, maxPressure);
                    }
                    else
                    {
                        fp.staticPressure = 0;
                    }
                }
            }
        }
예제 #9
0
        void solvePressure(float dt)
        {
            // calculates pressure as a linear function of density
            float criticalPressure  = getCriticalPressure(dt);
            float pressurePerWeight = fluidSystemDef.pressureStrength * criticalPressure;
            float maxPressure       = maxParticlePressure * criticalPressure;

            for (int i = 0; i < count; i++)
            {
                FluidParticle fp = particleBuffer [i];
                float         h  = pressurePerWeight * Mathf.Max(0f, fp.weight - minParticleWeight);
                fp.accumulation = Mathf.Min(h, maxPressure);
            }
            //		// ignores particles which have their own repulsive force
            //		if (m_allParticleFlags & k_noPressureFlags)
            //		{
            //			for (int32 i = 0; i < m_count; i++)
            //			{
            //				if (m_flagsBuffer.data[i] & k_noPressureFlags)
            //				{
            //					m_accumulationBuffer[i] = 0;
            //				}
            //			}
            //		}
            // static pressure
            if ((allParticleFlags & FluidParticleType.StaticPressureParticle) > 0)
            {
                for (int i = 0; i < count; i++)
                {
                    FluidParticle fp = particleBuffer [i];
                    if ((fp.flags & FluidParticleType.StaticPressureParticle) > 0)
                    {
                        fp.accumulation += fp.staticPressure;
                    }
                }
            }
            // applies pressure between each particles in contact
            float velocityPerPressure = dt / (fluidSystemDef.density * particleDiameter);

            for (int i = 0; i < bodyContactBuffer.Count; i++)
            {
                FluidParticleBodyContact contact = bodyContactBuffer [i];
                FluidParticle            a       = contact.fp;
                Rigidbody2D b = contact.body;
                Vector2     p = a.position;
                float       h = a.accumulation + pressurePerWeight * contact.weight;
                Vector2     f = velocityPerPressure * contact.weight * contact.mass * h * contact.normal;
                a.velocity -= getParticleInvMass() * f;
                b.AddForceAtPosition(f / dt, p);
            }

            float strength = fluidSystemDef.temperaturMixingStrength;

            for (int i = 0; i < contactBuffer.Count; i++)
            {
                FluidParticleContact contact = contactBuffer [i];
                FluidParticle        a       = contact.a;
                FluidParticle        b       = contact.b;

                float   h = a.accumulation + b.accumulation;
                Vector2 f = velocityPerPressure * contact.weight * h * contact.normal;
                a.velocity -= f;
                b.velocity += f;

                float t = (b.temperature - a.temperature) * strength;
                a.temperature += t;
                b.temperature -= t;

                if (Mathf.Abs(a.mass - b.mass) >= 0.01f)
                {
                    if (b.mass < a.mass)
                    {
                        a = contact.b;
                        b = contact.a;
                    }
                    a.velocity.y += fluidSystemDef.densityStrength;
                    b.velocity.y -= fluidSystemDef.densityStrength;
                }
                else if (Mathf.Abs(a.temperature - b.temperature) >= 0.1f)
                {
                    if (b.temperature > a.temperature)
                    {
                        a = contact.b;
                        b = contact.a;
                    }
                    a.velocity.y += fluidSystemDef.temperatureStrength;
                    b.velocity.y -= fluidSystemDef.temperatureStrength;
                }
            }
        }