void ConstructOctree() { var aabb = new AABB(transform.position, _radiusToSpawnIn * _octreeRadiusMultiplier); var octConstructJob = _octree.CreateConstructJob(_particlePositions, aabb); var job = octConstructJob.Schedule(); job.Complete(); }
public void Step(float dt) { Fluid.Gravity = _world.Gravity; Fluid.Update(dt); Collision.AABB fluidAABB = new Collision.AABB(); // Compute fluid AABB for (int i = 0; i < Fluid.Particles.Count; ++i) { FluidParticle p = Fluid.Particles[i]; if (p.IsActive) { fluidAABB.LowerBound = Vector2.Min(p.Position, fluidAABB.LowerBound); fluidAABB.UpperBound = Vector2.Max(p.Position, fluidAABB.UpperBound); } } fluidAABB.LowerBound -= new Vector2(Fluid.Definition.InfluenceRadius, Fluid.Definition.InfluenceRadius); fluidAABB.UpperBound += new Vector2(Fluid.Definition.InfluenceRadius, Fluid.Definition.InfluenceRadius); // Query the world for fixtures near fluid _fluidCollisions.Clear(); _world.QueryAABB(FluidQueryCallback, ref fluidAABB); // Save states for (int i = 0; i < _bodies.Count; ++i) { RigidBody rb = _bodies[i]; if (rb.Body.BodyType == BodyType.Dynamic) { rb.Reset(); rb.SaveState(); rb.Advance(dt, ref _world.Gravity); } } // Fluid > Bodies for (int ic = 0; ic < _fluidCollisions.Count; ++ic) { Fixture fixture = _fluidCollisions[ic]; if (fixture.RigidBody.Body.BodyType != BodyType.Dynamic) continue; if (fixture.IsSensor) continue; for (int ip = 0; ip < Fluid.Particles.Count; ++ip) { FluidParticle particle = Fluid.Particles[ip]; if (!particle.IsActive) continue; Feature result; if (!fixture.RigidBody.Intersect(fixture, ref particle.Position, out result)) continue; Vector2 impulse = new Vector2(); if (result.Distance < 0.0f) // Inside { Vector2 bodyVelocity = fixture.RigidBody.Body.GetLinearVelocityFromWorldPoint(ref particle.Position); Vector2 velocity = (particle.Position - particle.PreviousPosition) - bodyVelocity * dt; Vector2 velocityNormal = Vector2.Dot(velocity, result.Normal) * result.Normal; Vector2 velocityTangent = velocity - velocityNormal; impulse = velocityNormal + fixture.FluidProperties.Slip * velocityTangent; } else if (fixture.FluidProperties.IsSticky && result.Distance < fixture.FluidProperties.StickDistance) // Outside { impulse = -dt * fixture.FluidProperties.StickForce * result.Distance * (1.0f - result.Distance / fixture.FluidProperties.StickDistance) * result.Normal; } fixture.RigidBody.AddForce(ref impulse, ref particle.Position); } } // Apply buffers to bodies for (int i = 0; i < _bodies.Count; ++i) { RigidBody rb = _bodies[i]; if (rb.Body.BodyType == BodyType.Dynamic) { rb.RestoreState(); rb.bufferForce /= dt; rb.bufferTorque /= dt; if (Math.Abs(rb.bufferForce.X) > 0.0f && Math.Abs(rb.bufferForce.Y) > 0.0f) { rb.Body.ApplyLinearImpulse(ref rb.bufferForce); } if (Math.Abs(rb.bufferTorque) > 0.0f) { rb.Body.ApplyAngularImpulse(rb.bufferTorque); } } } // Physics step _world.Step(dt); // Bodies > Fluids for (int ip = 0; ip < Fluid.Particles.Count; ++ip) { FluidParticle particle = Fluid.Particles[ip]; if (!particle.IsActive) { continue; } for (int ic = 0; ic < _fluidCollisions.Count; ++ic) { Fixture fixture = _fluidCollisions[ic]; if (fixture.IsSensor) continue; Feature result; if (!fixture.RigidBody.Intersect(fixture, ref particle.Position, out result)) continue; Vector2 impulse = new Vector2(); if (result.Distance < 0.0f) // Inside { Vector2 bodyVelocity = fixture.RigidBody.Body.GetLinearVelocityFromWorldPoint(ref particle.Position); Vector2 velocity = (particle.Position - particle.PreviousPosition) - bodyVelocity * dt; Vector2 velocityNormal = Vector2.Dot(velocity, result.Normal) * result.Normal; Vector2 velocityTangent = velocity - velocityNormal; impulse = velocityNormal + fixture.FluidProperties.Slip * velocityTangent; } else if (fixture.FluidProperties.IsSticky && result.Distance < fixture.FluidProperties.StickDistance) // Outside { impulse = -dt * fixture.FluidProperties.StickForce * result.Distance * (1.0f - result.Distance / fixture.FluidProperties.StickDistance) * result.Normal; } particle.Position -= impulse; if (fixture.RigidBody.Intersect(fixture, ref particle.Position, out result)) { if (result.Distance < 0.0f) // Still inside { particle.ApplyImpulse((result.Position - particle.Position) / dt); particle.Position = result.Position; } } } } // Correct velocities Fluid.UpdateVelocities(dt); }
/// <summary> /// Get the fixture's AABB. This AABB may be enlarge and/or stale. /// If you need a more accurate AABB, compute it using the Shape and /// the body transform. /// </summary> /// <param name="aabb">The aabb.</param> /// <param name="childIndex">Index of the child.</param> public void GetAABB(out Collision.AABB aabb, int childIndex) { Debug.Assert(0 <= childIndex && childIndex < ProxyCount); aabb = Proxies[childIndex].AABB; }