//Code from Simple Dynamics framework - Minsi Chen
        public void AddCollisionPair(CollisionPair pair)
        {
            Object A = pair.BodyA;
            Object B = pair.BodyB;


            //Check if the pair already exists
            foreach (var p in mCollisionPairs)
            {
                if (
                    (Object.ReferenceEquals(A, p.BodyA) && Object.ReferenceEquals(B, p.BodyB)) ||
                    (Object.ReferenceEquals(A, p.BodyB) && Object.ReferenceEquals(B, p.BodyA))
                    )
                {
                    return;
                }
            }

            mCollisionPairs.Add(pair);
        }
예제 #2
0
        //AABB Box to AABB box collision
        //Creates a collision pair with appropriate info
        public CollisionPair Collision(Box b)
        {
            Box     a = this;
            Vector2 collisionNormal = Vector2.Zero;
            float   collisionDepth  = 1000;

            Vector2[] normalsAABB = new Vector2[4]
            {
                new Vector2(1, 0),
                new Vector2(-1, 0),
                new Vector2(0, 1),
                new Vector2(0, -1)
            };

            float[] distances = new float[4]
            {
                b.Max().X - a.Min().X,
                    a.Max().X - b.Min().X,
                    b.Max().Y - a.Min().Y,
                    a.Max().Y - b.Min().Y
            };

            for (int i = 0; i < 4; i++)
            {
                if (i == 0 || (distances[i] < collisionDepth))
                {
                    collisionNormal = normalsAABB[i];
                    collisionDepth  = distances[i];
                }
            }
            CollisionPair p = new CollisionPair();

            p.BodyA          = a.parent;
            p.BodyB          = b.parent;
            p.CollisionDepth = collisionDepth;
            p.ContactNormal  = collisionNormal;
            p.ContactPoint   = (a.Center() + (collisionNormal * (1 / collisionDepth)));

            return(p);
        }
        public void Resolve(CollisionPair data)
        {
            Object a = data.BodyA;
            Object b = data.BodyB;

            if (a.Name == "Button" || b.Name == "Button")
            {
                return;
            }

            if (a == null || b == null)
            {
                return;
            }

            //perform the displacement using the collision depth and normal
            #region Displacement
            //data.ContactNormal.Normalize();

            Vector2 displacement = (data.ContactNormal * data.CollisionDepth);

            if (!a.IsStatic && b.IsStatic && !b.IsParticle)
            {
                a.Position += displacement * 1f;
            }
            else if (!a.IsStatic && !b.IsParticle)
            {
                a.Position += displacement / 1f;
            }

            if (!b.IsStatic && a.IsStatic && !a.IsParticle)
            {
                b.Position -= displacement * 1f;
            }
            else if (!b.IsStatic && !a.IsParticle)
            {
                b.Position -= displacement / 1f;
            }

            (a.HitBox).UpdatePos(a.Position);
            (b.HitBox).UpdatePos(b.Position);
            #endregion

            //perform the impulse response
            #region Impulse Collision
            Vector2 relativeVelocity = b.RigidBody.LinearVelocity - a.RigidBody.LinearVelocity;
            float   rVN = Vector2.Dot(relativeVelocity, data.ContactNormal);

            float elasticity = (a.Bounciness + b.Bounciness) / 2;

            float mass;

            if (a.IsStatic || b.IsParticle)
            {
                mass = b.RigidBody.InvMass;
            }
            else if (b.IsStatic || a.IsParticle)
            {
                mass = a.RigidBody.InvMass;
            }
            else
            {
                mass = (a.RigidBody.InvMass + b.RigidBody.InvMass);
            }

            float impulse = (-1 * (1 + elasticity) * rVN) / mass;

            if (!a.IsStatic && !b.IsParticle)
            {
                data.BodyA.RigidBody.LinearVelocity -= (data.ContactNormal * (impulse / a.RigidBody.Mass));
            }
            if (!b.IsStatic && !a.IsParticle)
            {
                data.BodyB.RigidBody.LinearVelocity += (data.ContactNormal * (impulse / b.RigidBody.Mass));
            }
            //Console.WriteLine("Friction impulse" + frictionImpulse + " Linear velocity" + a.RigidBody.LinearVelocity);
            #endregion

            relativeVelocity = b.RigidBody.LinearVelocity - a.RigidBody.LinearVelocity;
            rVN = Vector2.Dot(relativeVelocity, data.ContactNormal);

            //perform the friction response
            #region Friction Collision
            //Referenced - https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-friction-scene-and-jump-table--gamedev-7756
            float   frictionImpulse;
            float   dynamicFriction;
            Vector2 tangent = relativeVelocity - (rVN * data.ContactNormal);
            if (tangent != Vector2.Zero)
            {
                tangent.Normalize();
            }
            else
            {
                tangent = Vector2.Zero;
            }

            float magnitude = -Vector2.Dot(relativeVelocity, tangent);
            magnitude = magnitude / (a.RigidBody.InvMass + b.RigidBody.InvMass);

            float totalFriction = MathHelper.Clamp((float)Math.Sqrt(a.StaticFriction * a.StaticFriction + b.StaticFriction * b.StaticFriction), 0, 1f);

            float impulse2 = (-1 * (1 + elasticity) * Vector2.Dot(relativeVelocity, tangent));

            if (Math.Abs(magnitude) < impulse2 * totalFriction)
            {
                frictionImpulse = (magnitude);
            }
            else
            {
                dynamicFriction = MathHelper.Clamp((float)Math.Sqrt(a.DynamicFriction * a.DynamicFriction + b.DynamicFriction * b.DynamicFriction), 0f, 1f);
                frictionImpulse = (dynamicFriction);
            }

            if (!a.IsStatic && !b.IsParticle)
            {
                data.BodyA.RigidBody.LinearVelocity -= tangent / (1 - frictionImpulse) * impulse2 / a.RigidBody.Mass;
            }
            if (!b.IsStatic && !a.IsParticle)
            {
                data.BodyB.RigidBody.LinearVelocity += tangent / (1 - frictionImpulse) * impulse2 / b.RigidBody.Mass;
            }
            #endregion
        }