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; } } }
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; } } }
public override void reportFixtureAndParticle(FluidFixtureShape fixture, FluidParticle fp) { float d; Vector2 n; fixture.computeDistance(fp, out d, out n); if ((d < fluidSystem.particleDiameter) && ((fp.flags & FluidParticleType.WallParticle) == 0)) { Rigidbody2D b = fixture.GetComponent <Rigidbody2D> (); //Vector2 bp = b.transform.position; float bm = b.mass; // b2Vec2 bp = b->GetWorldCenter(); // float32 bI = // b->GetInertia() - bm * b->GetLocalCenter().LengthSquared(); float invBm = bm > 0 ? 1 / bm : 0; // float32 invBI = bI > 0 ? 1 / bI : 0; float invAm = (fp.flags & FluidParticleType.WallParticle) > 0 ? 0 : fluidSystem.getParticleInvMass(); //Vector2 rp = fp.position - bp; // float rpn = rp * n; // float32 rpn = b2Cross(rp, n); // float32 invM = invAm + invBm + invBI * rpn * rpn; float invM = invAm + invBm; FluidParticleBodyContact contact = new FluidParticleBodyContact { fp = fp, body = b, fixture = fixture, weight = 1 - d * fluidSystem.inverseDiameter, normal = -n, mass = invM > 0 ? 1 / invM : 0 }; if (fixture.isTrigger()) { fluidSystem.triggerContactBuffer.Add(contact); fixture.notifyOnTrigger(contact); } else { fluidSystem.bodyContactBuffer.Add(contact); } // m_system->DetectStuckParticle(a); } }
public void notifyOnTrigger(FluidParticleBodyContact bodyContact) { foreach (GameObject receiver in listeners.ToArray()) { MonoBehaviour[] components = receiver.GetComponents <MonoBehaviour> (); foreach (MonoBehaviour component in components) { if (component is IFluidFixtureTriggerListener) { if (component.enabled) { IFluidFixtureTriggerListener l = component as IFluidFixtureTriggerListener; l.fluidOnTrigger(bodyContact); } } } } }
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; } }
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; } } }