Beispiel #1
0
        public void ApplyImpulse_DynamicToFrozen(LsmBody applyBody, Particle applyParticle, LsmBody otherBody, double timeCoefficientPrediction, ref List<CollisionSubframeBuffer> collisionBuffer)
        {
            Debug.Assert(!applyBody.Equals(otherBody)); // don't allow self-collision here
            Debug.Assert(!applyBody.Frozen && otherBody.Frozen);

            foreach (Particle bodyt in otherBody.particles)
            {
                if (bodyt.xPos != null)
                {
                    CheckParticleEdge_D2F(
                        ref applyParticle.ccdDebugInfos, applyParticle, bodyt, bodyt.xPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(bodyt, bodyt.xPos), bodyt.v, bodyt.xPos.v, 0.0)
                    );
                }
                if (bodyt.yPos != null)
                {
                    CheckParticleEdge_D2F(
                        ref applyParticle.ccdDebugInfos, applyParticle, bodyt, bodyt.yPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(bodyt, bodyt.yPos), bodyt.v, bodyt.yPos.v, 0.0)
                    );
                }
            }
        }
        public void ApplyImpulse(
            LsmBody applyBody, Particle applyParticle,
            double timeCoefficientPrediction, ref List <CollisionSubframeBuffer> collisionBuffer // HACK // TODO: remove ref List<>
            )
        {
            float left = this.left + border, right = this.right - border, bottom = this.bottom + border, top = this.top - border;

            if (left < 0.0 || right < 0.0 || bottom < 0.0 || top < 0.0) // to prevent computation for incorrect case
            {
                return;
            }

            Vector2 pos      = applyParticle.x;
            Vector2 velocity = applyParticle.v;
            Vector2 posNext  = pos + velocity * timeCoefficientPrediction;

            if (posNext.X < left)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(-velocity.X * BodyRepulse.coefficientElasticity, velocity.Y), null, Vector2.ZERO, Vector2.ZERO, (left - pos.X) / velocity.X));
            }
            if (posNext.X > right)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(-velocity.X * BodyRepulse.coefficientElasticity, velocity.Y), null, Vector2.ZERO, Vector2.ZERO, (right - pos.X) / velocity.X));
            }
            if (posNext.Y < bottom)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(velocity.X, -velocity.Y * BodyRepulse.coefficientElasticity), null, Vector2.ZERO, Vector2.ZERO, (bottom - pos.Y) / velocity.Y));
            }
            if (posNext.Y > top)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(velocity.X, -velocity.Y * BodyRepulse.coefficientElasticity), null, Vector2.ZERO, Vector2.ZERO, (top - pos.Y) / velocity.Y));
            }
        }
Beispiel #3
0
        public void ApplyImpulse(
            LsmBody applyBody, Particle applyParticle, LsmBody otherBody, // HACK // TODO: try to don't use such information for collisions or formilize this ussage
            double timeCoefficientPrediction, ref List<CollisionSubframeBuffer> collisionBuffer // HACK // TODO: remove ref List<>
            )
        {
            Debug.Assert(!applyBody.Equals(otherBody)); // don't allow self-collision here
            Debug.Assert(!applyBody.Frozen && !otherBody.Frozen);

            // iterate all possible edges of body and test them with current subframed point
            foreach (Particle bodyt in otherBody.particles)
            {
                if (bodyt.xPos != null)
                {
                    CheckParticleEdge_D2D(
                        ref applyParticle.ccdDebugInfos, applyParticle, bodyt, bodyt.xPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(bodyt, bodyt.xPos), bodyt.v, bodyt.xPos.v, 0.0)
                    );
                }
                if (bodyt.yPos != null)
                {
                    CheckParticleEdge_D2D(
                        ref applyParticle.ccdDebugInfos, applyParticle, bodyt, bodyt.yPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(bodyt, bodyt.yPos), bodyt.v, bodyt.yPos.v, 0.0)
                    );
                }
            }
        }
Beispiel #4
0
        public void ApplyImpulse(
            LsmBody applyBody, Particle applyParticle, LsmBody otherBody,                        // HACK // TODO: try to don't use such information for collisions or formilize this ussage
            double timeCoefficientPrediction, ref List <CollisionSubframeBuffer> collisionBuffer // HACK // TODO: remove ref List<>
            )
        {
            Debug.Assert(!applyBody.Equals(otherBody)); // don't allow self-collision here
            Debug.Assert(!applyBody.Frozen && !otherBody.Frozen);

            // iterate all possible edges of body and test them with current subframed point
            foreach (Particle bodyt in otherBody.particles)
            {
                if (bodyt.xPos != null)
                {
                    CheckParticleEdge_D2D(
                        ref applyParticle.ccdDebugInfos, applyParticle, bodyt, bodyt.xPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(bodyt, bodyt.xPos), bodyt.v, bodyt.xPos.v, 0.0)
                        );
                }
                if (bodyt.yPos != null)
                {
                    CheckParticleEdge_D2D(
                        ref applyParticle.ccdDebugInfos, applyParticle, bodyt, bodyt.yPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(bodyt, bodyt.yPos), bodyt.v, bodyt.yPos.v, 0.0)
                        );
                }
            }
        }
Beispiel #5
0
        public void ApplyImpulse_FrozenToDynamic(LsmBody otherBody, Particle otherParticle, LsmBody applyBody, double timeCoefficientPrediction, ref List <CollisionSubframeBuffer> collisionBuffer)
        {
            Debug.Assert(!applyBody.Equals(otherBody)); // don't allow self-collision here
            Debug.Assert(applyBody.Frozen && !otherBody.Frozen);

            foreach (Particle applyParticle in applyBody.particles)
            {
                if (otherParticle.xPos != null)
                {
                    CheckParticleEdge_F2D(
                        ref applyParticle.ccdDebugInfos, applyParticle, otherParticle, otherParticle.xPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(otherParticle, otherParticle.xPos), otherParticle.v, otherParticle.xPos.v, 0.0)
                        );
                }
                if (otherParticle.yPos != null)
                {
                    CheckParticleEdge_F2D(
                        ref applyParticle.ccdDebugInfos, applyParticle, otherParticle, otherParticle.yPos,
                        ref collisionBuffer, timeCoefficientPrediction,
                        new CollisionSubframeBuffer(applyParticle, applyParticle.v, new Edge(otherParticle, otherParticle.yPos), otherParticle.v, otherParticle.yPos.v, 0.0)
                        );
                }
            }
        }
Beispiel #6
0
        public void ApplyImpulse(
            LsmBody applyBody, Particle applyParticle,
            double timeCoefficientPrediction, ref List<CollisionSubframeBuffer> collisionBuffer // HACK // TODO: remove ref List<>
            )
        {
            float left = this.left + border, right = this.right - border, bottom = this.bottom + border, top = this.top - border;
            if (left < 0.0 || right < 0.0 || bottom < 0.0 || top < 0.0) // to prevent computation for incorrect case
                return;

            Vector2 pos = applyParticle.x;
            Vector2 velocity = applyParticle.v;
            Vector2 posNext = pos + velocity * timeCoefficientPrediction;

            if (posNext.X < left)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(-velocity.X * BodyRepulse.coefficientElasticity, velocity.Y), null, Vector2.ZERO, Vector2.ZERO, (left - pos.X) / velocity.X));
            }
            if (posNext.X > right)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(-velocity.X * BodyRepulse.coefficientElasticity, velocity.Y), null, Vector2.ZERO, Vector2.ZERO, (right - pos.X) / velocity.X));
            }
            if (posNext.Y < bottom)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(velocity.X, -velocity.Y * BodyRepulse.coefficientElasticity), null, Vector2.ZERO, Vector2.ZERO, (bottom - pos.Y) / velocity.Y));
            }
            if (posNext.Y > top)
            {
                collisionBuffer.Add(new CollisionSubframeBuffer(applyParticle, new Vector2(velocity.X, -velocity.Y * BodyRepulse.coefficientElasticity), null, Vector2.ZERO, Vector2.ZERO, (top - pos.Y) / velocity.Y));
            }
        }
Beispiel #7
0
 public static void MakeDataBindingForBody(TestbedWindow window, LsmBody body, int bodyIndex)
 {
     // TODO: make this method suitable for N bodies - not only for 2 of them
     if (window != null && (bodyIndex == 0 || bodyIndex == 1))
     {
         MakeCheckBoxDataBinding(window, "model0" + (bodyIndex + 1) + "DisableCollisions", "Checked", body, "UseWallForce");
         MakeCheckBoxDataBinding(window, "model0" + (bodyIndex + 1) + "Freeze", "Checked", body, "Frozen");
     }
 }
Beispiel #8
0
        private static void RegenerateBody(int bodyIndex, bool[,] blueprint)
        {
            if (bodyIndex < 0 || bodyIndex >= world.bodies.Count)
            {
                PostMessage(Color.Red, "Invalud world.body index: " + bodyIndex + ". Failed to regenerate body.");
                return;
            }
            LsmBody body = GenerateBody(bodyIndex, blueprint);

            world.bodies[bodyIndex] = body;
        }
Beispiel #9
0
        public static void GenerateBodies(Array blueprints)
        {
            int verticalIndex = 0;

            foreach (bool[,] blueprint in blueprints)
            {
                LsmBody body = GenerateBody(verticalIndex, blueprint);
                world.bodies.Add(body);
                ++verticalIndex;
            }
        }
Beispiel #10
0
        private static LsmBody GenerateBody(int verticalIndex, bool[,] blueprint)
        {
            LsmBody body = new LsmBody(
                new Vector2(50, 50 + 150 * verticalIndex),
                new Point(LsmBody.blueprintSpacingX, LsmBody.blueprintSpacingY),
                new Color3(verticalIndex == 1 ? 1 : 0, verticalIndex == 0 ? 1 : 0, verticalIndex == 2 ? 1 : 0)
                );

            body.GenerateFromBlueprint(blueprint);
            if (verticalIndex < 2)
            {
                MakeDataBindingForBody(Program.testbedWindow, body, verticalIndex);
            }
            return(body);
        }
Beispiel #11
0
        public static void CollideBodies(LsmBody movingBody, LsmBody blockingBody, double timeCoefficientPrediction, ref List <CollisionSubframeBuffer> collisionBuffer)
        {
            foreach (Particle particleOfMovingBody in movingBody.particles)
            {
                // impulse & offset collision method
                particleOfMovingBody.ccdDebugInfos.Clear();
            }

            // Collide with other body
            if (!movingBody.Frozen && !blockingBody.Frozen)
            {
                foreach (Particle particleOfMovingBody in movingBody.particles)
                {
                    Testbed.world.bodyBodyRepulse.ApplyImpulse(
                        movingBody, particleOfMovingBody, blockingBody, timeCoefficientPrediction, ref collisionBuffer
                        );
                }
            }
            else if (!movingBody.Frozen && blockingBody.Frozen)
            {
                foreach (Particle particleOfMovingBody in movingBody.particles)
                {
                    Testbed.world.bodyBodyRepulse.ApplyImpulse_DynamicToFrozen(
                        movingBody, particleOfMovingBody, blockingBody, timeCoefficientPrediction, ref collisionBuffer
                        );
                }
            }
            else if (movingBody.Frozen && !blockingBody.Frozen)
            {
                foreach (Particle particleOfBlockingBody in blockingBody.particles)
                {
                    Testbed.world.bodyBodyRepulse.ApplyImpulse_FrozenToDynamic(
                        blockingBody, particleOfBlockingBody, movingBody, timeCoefficientPrediction, ref collisionBuffer
                        );
                }
            }
        }
Beispiel #12
0
        public static void CollideBodies(LsmBody movingBody, LsmBody blockingBody, double timeCoefficientPrediction, ref List<CollisionSubframeBuffer> collisionBuffer)
        {
            foreach (Particle particleOfMovingBody in movingBody.particles)
            {
                // impulse & offset collision method
                particleOfMovingBody.ccdDebugInfos.Clear();
            }

            // Collide with other body
            if (!movingBody.Frozen && !blockingBody.Frozen)
            {
                foreach (Particle particleOfMovingBody in movingBody.particles)
                    Testbed.world.bodyBodyRepulse.ApplyImpulse(
                        movingBody, particleOfMovingBody, blockingBody, timeCoefficientPrediction, ref collisionBuffer
                    );
            }
            else if (!movingBody.Frozen && blockingBody.Frozen)
            {
                foreach (Particle particleOfMovingBody in movingBody.particles)
                    Testbed.world.bodyBodyRepulse.ApplyImpulse_DynamicToFrozen(
                        movingBody, particleOfMovingBody, blockingBody, timeCoefficientPrediction, ref collisionBuffer
                    );
            }
            else if (movingBody.Frozen && !blockingBody.Frozen)
            {
                foreach (Particle particleOfBlockingBody in blockingBody.particles)
                    Testbed.world.bodyBodyRepulse.ApplyImpulse_FrozenToDynamic(
                        blockingBody, particleOfBlockingBody, movingBody, timeCoefficientPrediction, ref collisionBuffer
                    );
            }
        }
Beispiel #13
0
 static void MakeCheckBoxDataBinding(TestbedWindow window, string checkBoxName, string checkBoxPropertyName, LsmBody body, string bodyPropertyName)
 {
     System.Windows.Forms.Control[] controls = window.Controls.Find(checkBoxName, true);
     if (controls.Length > 0 && controls.GetValue(0) != null && controls.GetValue(0) is System.Windows.Forms.CheckBox)
     {
         System.Windows.Forms.CheckBox checkBox = controls.GetValue(0) as System.Windows.Forms.CheckBox;
         checkBox.DataBindings.Clear();
         checkBox.DataBindings.Add(checkBoxPropertyName, body, bodyPropertyName).DataSourceUpdateMode = System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged;
     }
 }
Beispiel #14
0
 private static LsmBody GenerateBody(int verticalIndex, bool[,] blueprint)
 {
     LsmBody body = new LsmBody(
         new Vector2(50, 50 + 150 * verticalIndex),
         new Point(LsmBody.blueprintSpacingX, LsmBody.blueprintSpacingY),
         new Color3(verticalIndex == 1 ? 1 : 0, verticalIndex == 0 ? 1 : 0, verticalIndex == 2 ? 1 : 0)
     );
     body.GenerateFromBlueprint(blueprint);
     if (verticalIndex < 2)
     {
         MakeDataBindingForBody(Program.testbedWindow, body, verticalIndex);
     }
     return body;
 }
Beispiel #15
0
 public static void MakeDataBindingForBody(TestbedWindow window, LsmBody body, int bodyIndex)
 {
     // TODO: make this method suitable for N bodies - not only for 2 of them
     if (window != null && (bodyIndex == 0 || bodyIndex == 1))
     {
         MakeCheckBoxDataBinding(window, "model0" + (bodyIndex + 1) + "DisableCollisions", "Checked", body, "UseWallForce");
         MakeCheckBoxDataBinding(window, "model0" + (bodyIndex + 1) + "Freeze", "Checked", body, "Frozen");
     }
 }
Beispiel #16
0
 static void MakeCheckBoxDataBinding(TestbedWindow window, string checkBoxName, string checkBoxPropertyName, LsmBody body, string bodyPropertyName)
 {
     System.Windows.Forms.Control[] controls = window.Controls.Find(checkBoxName, true);
     if (controls.Length > 0 && controls.GetValue(0) != null && controls.GetValue(0) is System.Windows.Forms.CheckBox)
     {
         System.Windows.Forms.CheckBox checkBox = controls.GetValue(0) as System.Windows.Forms.CheckBox;
         checkBox.DataBindings.Clear();
         checkBox.DataBindings.Add(checkBoxPropertyName, body, bodyPropertyName).DataSourceUpdateMode = System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged;
     }
 }
Beispiel #17
0
        public void Update()
        {
            // update internal processes in bodies, find velocities
            foreach (LsmBody b in bodies)
            {
                if (!b.Frozen)
                {
                    foreach (IEnvironmentForce force in environmentForces)
                    {
                        if (force is WallForce && !b.UseWallForce) // HACK to apply custom forces // TODO: make correct system
                        {
                            continue;
                        }
                        force.ApplyForce(b.particles);
                    }
                    b.Smooth();
                    b.DoFracture();
                    b.UpdateParticlesVelocity();
                }
                else
                {
                    b.UpdateFrozenParticlesVelocity();
                }
            }

            // iterate subframes for collision and integration system of bodies
            List <CollisionSubframeBuffer> collisionBuffer = new List <CollisionSubframeBuffer>();
            int       iterationsCounter         = 0;  // to prevent deadlocks
            const int maxIterations             = 64; // to prevent deadlocks
            double    timeCoefficientPrediction = 1.0;
            bool      collisionFound            = false;

            do
            {
                for (int i = 0; i < bodies.Count; ++i)
                {
                    LsmBody bLeft = bodies[i];
                    if (!bLeft.Frozen && !bLeft.UseWallForce)
                    {
                        bLeft.CollideWithWall(timeCoefficientPrediction, ref collisionBuffer); // TODO: refactor to remove 'ref collisionBuffer'
                    }
                    for (int j = i + 1; j < bodies.Count; ++j)                                 // TODO: implement self-collisions for j == i.
                    {
                        LsmBody bRight = bodies[j];
                        LsmBody.CollideBodies(bLeft, bRight, timeCoefficientPrediction, ref collisionBuffer); // TODO: refactor to remove 'ref collisionBuffer'
                        LsmBody.CollideBodies(bRight, bLeft, timeCoefficientPrediction, ref collisionBuffer); // TODO: refactor to remove 'ref collisionBuffer'
                    }
                }

                double timeCoefficientIntegrate = 0.0;
                if (collisionBuffer.Count > 0)
                {
                    CollisionSubframeBuffer subframe = LsmBody.GetEarliestSubframe(collisionBuffer);    // WARNING: now we assume that in 1 time moment we have maximum 1 collision in subframe.
                    // TODO: make system ready to handle multi-collision subframes. For example, we'll need to accumulate velocity deltas for every particle and then make summation - not just direct assign of values.
                    timeCoefficientIntegrate   = subframe.timeCoefficient;
                    timeCoefficientPrediction -= subframe.timeCoefficient;

                    subframe.particle.v = subframe.vParticle;
                    if (subframe.edge != null)
                    {
                        subframe.edge.start.v = subframe.vEdgeStart;
                        subframe.edge.end.v   = subframe.vEdgeEnd;
                    }

                    collisionBuffer.Clear();
                    collisionFound = true;
                }
                else
                {
                    timeCoefficientIntegrate = timeCoefficientPrediction;
                    collisionFound           = false;
                }

                if (timeCoefficientIntegrate > 0.0)
                {
                    foreach (LsmBody b in bodies)
                    {
                        if (!b.Frozen)
                        {
                            b.UpdateParticlesPosition(timeCoefficientIntegrate);
                        }
                        else
                        {
                            b.UpdateFrozenParticlesPosition();
                        }
                    }
                }
                else
                {
                    Testbed.PostMessage(System.Drawing.Color.Yellow, "Timestep <= 0.0 while subframes iterating!"); // DEBUG
                }

                if (++iterationsCounter >= maxIterations)                                                    // to prevent deadlocks
                {
                    Testbed.PostMessage(System.Drawing.Color.Red, "Deadlock detected in HandleCollisions!"); // DEBUG
                    if (LsmBody.pauseOnDeadlock)
                    {
                        Testbed.Paused = true;
                    }
                    break;
                }
            }while (collisionFound);
        }