Ejemplo n.º 1
0
        void ConstructOctree()
        {
            var aabb            = new AABB(transform.position, _radiusToSpawnIn * _octreeRadiusMultiplier);
            var octConstructJob = _octree.CreateConstructJob(_particlePositions, aabb);

            var job = octConstructJob.Schedule();

            job.Complete();
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
 /// <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;
 }