public static void CalcCollisionOld(Contact c, out ObjCollisionData dataA, out ObjCollisionData dataB)
        {
            dataA.dVel = Vector2.Zero; //incase the method exits before ang velocities need to be calculated (ie, if the contact point is separating)
            dataB.dVel = Vector2.Zero;
            dataA.dAngVel = 0;
            dataB.dAngVel = 0;
            dataA.dPos = Vector2.Zero;
            dataB.dPos = Vector2.Zero;

            var a = c.A;
            var b = c.B;
            var disp = c.Disp;
            var axis = c.Axis; //axis from A to B
            var con = c.ConPoint;

            var Ia = a.GetInertiaMoment();
            var Ib = b.GetInertiaMoment();

            var totInvMass = a.InvMass + b.InvMass;
            dataA.dPos = +disp * axis * a.InvMass / totInvMass;
            dataB.dPos = -disp * axis * b.InvMass / totInvMass;

            //
            //impulse calculations to set momentum
            //

            var radA = (con - a.Position);
            var radB = (con - b.Position);

            Vector2 velA, velB, tvelA, tvelB;
            tvelA = Vector3.Cross(a.AngularVelocity * Vector3.UnitZ, radA.ToVector3()).ToVector2(); // tangentVel = (contactpt - centroid)x(angVel) // remember angVel is really on the Z axis.
            tvelB = Vector3.Cross(b.AngularVelocity * Vector3.UnitZ, radB.ToVector3()).ToVector2(); //also, remember position is the position of the axis of rotation (centroid, or fixed point). which works our well.

            velA = a.Velocity + tvelA; //velocity of contact point = (vel of object) + (tangential vel of pt due to ang_vel)
            velB = b.Velocity + tvelB;

            var sepVel = Vector2.Dot((velB - velA), axis); //find the separating velocity of the contact points
            if (sepVel > 0) return; //if the objects are already separatingm, then skip the impulse calcs below

            var res =  (a.Restitution + b.Restitution) / 2;
            var n = -axis; //-axis?

            var tmpA = Vector3.Dot(Vector3.Cross(n.ToVector3(), Vector3.Cross(radA.ToVector3(), n.ToVector3()) / Ia), radA.ToVector3());
            var tmpB = Vector3.Dot(Vector3.Cross(n.ToVector3(), Vector3.Cross(radB.ToVector3(), n.ToVector3()) / Ib), radB.ToVector3());
            var impulse = -sepVel * (res + 1) / (a.InvMass + b.InvMass + tmpA + tmpB); //angular

            var relVel = (velA - velB);
            var t = Vector3.Cross(Vector3.Cross(n.ToVector3(), relVel.ToVector3()), n.ToVector3()).ToVector2();
            t = relVel - n*Vector2.Dot(relVel, n);
            if (t != Vector2.Zero) t.Normalize();

            var u = (a.Friction + b.Friction) / 2;

            dataA.dVel = (impulse * n + impulse * u * t) * a.InvMass;
            dataB.dVel = (-impulse * n + impulse * u * t) * b.InvMass;

            dataA.dAngVel = (Vector3.Cross(radA.ToVector3(), (impulse * n.ToVector3() + impulse * u * t.ToVector3()))).Z * a.GetInverseInertiaMoment();
            dataB.dAngVel = (Vector3.Cross(radB.ToVector3(), (-impulse * n.ToVector3() + impulse * u * t.ToVector3()))).Z * b.GetInverseInertiaMoment();
        }
        public static void CalcCollisionNoFrict(Contact c, out ObjCollisionData dataA, out ObjCollisionData dataB)
        {
            dataA.dVel = Vector2.Zero;
            dataB.dVel = Vector2.Zero;
            dataA.dAngVel = 0;
            dataB.dAngVel = 0;
            dataA.dPos = Vector2.Zero;
            dataB.dPos = Vector2.Zero;

            var con = c.ConPoint;
            var a = c.A;
            var b = c.B;
            var disp = c.Disp;

            var Ia = a.GetInertiaMoment();
            var Ib = b.GetInertiaMoment();

            var Ia_inv = a.GetInverseInertiaMoment();
            var Ib_inv = b.GetInverseInertiaMoment();

            var axis = c.Axis; //from A->B
            var n = -axis; //points from B->A
            var n3 = n.ToVector3();

            var u = (a.Friction + b.Friction) / 2;
            var res = (a.Restitution + b.Restitution) / 2;
            //ADD: limit the rest. if sep vel is slow

            var totInvMass = a.InvMass + b.InvMass;
            dataA.dPos = +disp * axis * a.InvMass / totInvMass;
            dataB.dPos = -disp * axis * b.InvMass / totInvMass;

            var relPosA = (con - a.Position).ToVector3();
            var relPosB = (con - b.Position).ToVector3();

            Vector3 velA, velB, tvelA, tvelB;
            tvelA = Vector3.Cross(a.AngularVelocity * Vector3.UnitZ, relPosA); // tangentVel = (contactpt - centroid)x(angVel) // remember angVel is really on the Z axis.
            tvelB = Vector3.Cross(b.AngularVelocity * Vector3.UnitZ, relPosB); //also, remember position is the position of the axis of rotation (centroid, or fixed point). which works our well.

            velA = a.Velocity.ToVector3() + tvelA; //velocity of contact point = (vel of object) + (tangential vel of pt due to ang_vel)
            velB = b.Velocity.ToVector3() + tvelB;

            var torquePerImpulseA = Vector3.Cross(relPosA, n3);
            var torquePerImpulseB = Vector3.Cross(relPosB, n3);

            var rotPerImpA = torquePerImpulseA * Ia_inv;
            var rotPerImpB = torquePerImpulseB * Ib_inv;

            var velPerImpA = Vector3.Cross(rotPerImpA, relPosA); //"deltaVelWorld"
            var velPerImpB = Vector3.Cross(rotPerImpB, relPosB);

            Matrix localToWorld = CreateOrthonormalBasis(n, n.Perpen());
            Matrix worldToLocal = Matrix.Transpose(localToWorld);

            var velPerImpA_Contact = velPerImpA.TransformToLocal(worldToLocal); //"deltaVelocity"
            var velPerImpB_Contact = velPerImpB.TransformToLocal(worldToLocal);

            var angCompA = velPerImpA_Contact.X;
            var angCompB = velPerImpB_Contact.X;

            var deltaVelocity = angCompA + angCompB + a.InvMass + b.InvMass;

            var sepVel = velA - velB;
            var conVel = sepVel.TransformToLocal(worldToLocal);

            var desiredVel = -conVel.X * (1 + res);

            Vector3 impulseContact;
            impulseContact.X = desiredVel / deltaVelocity;
            impulseContact.Y = 0;
            impulseContact.Z = 0;

            var impulse = impulseContact.TransformToWorld(localToWorld);
            var impulse2 = impulse.ToVector2();

            dataA.dVel = impulse2 * a.InvMass;
            dataB.dVel = -impulse2 * b.InvMass;

            var impulsiveTorqueA = Vector3.Cross(relPosA, impulse);
            var impulsiveTorqueB = Vector3.Cross(relPosB, -impulse);

            dataA.dAngVel = impulsiveTorqueA.Z * a.GetInverseInertiaMoment();
            dataB.dAngVel = impulsiveTorqueB.Z * b.GetInverseInertiaMoment();
        }
 public static void ApplyColData(RigidBody body, ObjCollisionData colD)
 {
     body.SetMasterPosition(body.Position + colD.dPos);
     body.Velocity += colD.dVel;
     body.AngularVelocity += colD.dAngVel;
 }
        public static void CalcCollision(Contact c, out ObjCollisionData dataA, out ObjCollisionData dataB)
        {
            dataA.dVel = Vector2.Zero;
            dataB.dVel = Vector2.Zero;
            dataA.dAngVel = 0;
            dataB.dAngVel = 0;
            dataA.dPos = Vector2.Zero;
            dataB.dPos = Vector2.Zero;

            var con = c.ConPoint;
            var a = c.A;
            var b = c.B;
            var disp = c.Disp;

            var Ia = a.GetInertiaMoment();
            var Ib = b.GetInertiaMoment();

            var Ia_inv = a.GetInverseInertiaMoment();
            var Ib_inv = b.GetInverseInertiaMoment();

            var axis = c.Axis; //from A->B
            var n = -axis; //points from B->A
            var n3 = n.ToVector3();

            var u = (a.Friction + b.Friction) / 2;
            var res = (a.Restitution + b.Restitution) / 2;
            //TODO: limit the rest. if sep vel is slow

            //var totInvMass = a.InvMass + b.InvMass;
            //dataA.dPos = +disp * axis * a.InvMass / totInvMass;
            //dataB.dPos = -disp * axis * b.InvMass / totInvMass;

            var relPosA = (con - a.Position).ToVector3();
            var relPosB = (con - b.Position).ToVector3();

            Vector3 velA, velB, tvelA, tvelB;
            tvelA = Vector3.Cross(a.AngularVelocity * Vector3.UnitZ, relPosA); // tangentVel = (contactpt - centroid)x(angVel) // remember angVel is really on the Z axis.
            tvelB = Vector3.Cross(b.AngularVelocity * Vector3.UnitZ, relPosB); //also, remember position is the position of the axis of rotation (centroid, or fixed point). which works our well.

            velA = a.Velocity.ToVector3() + tvelA; //velocity of contact point = (vel of object) + (tangential vel of pt due to ang_vel)
            velB = b.Velocity.ToVector3() + tvelB;

            var relVel = velB - velA;
            var t = relVel - n3 * Vector3.Dot(relVel, n3);
            if (t != Vector3.Zero)
                t.Normalize();
            else
                t = n.Perpen().ToVector3();

            Matrix localToWorld = CreateOrthonormalBasis(n, n.Perpen());
            Matrix worldToLocal = Matrix.Transpose(localToWorld);

            var sepVel = velA - velB;
            var conVel = sepVel.TransformToLocal(worldToLocal);
            var desiredVel = -conVel.X * (1 + res);

            //
            //Friction-collision calcs
            //

            var impulseToTorqueA = CreateSkewSymmetric(relPosA);
            /*var torquePerUnitImpulseA = impulseToTorqueA * localToWorld;
            var angVelPerUnitImpulseA = torquePerUnitImpulseA * a.GetInverseInertiaMoment();
            var velPerUnitImpulseA = -angVelPerUnitImpulseA * impulseToTorqueA;
            var velPerUnitImpulseContactA = worldToLocal * velPerUnitImpulseA; //used to transform an impulse in contact coordinates -> velocity in contact coordinates
            */

            var impulseToTorqueB = CreateSkewSymmetric(relPosB);
            /*var torquePerUnitImpulseB = impulseToTorqueB * localToWorld;
            var angVelPerUnitImpulseB = torquePerUnitImpulseB * b.GetInverseInertiaMoment();
            var velPerUnitImpulseB = -angVelPerUnitImpulseB * impulseToTorqueB;
            var velPerUnitImpulseContactB = worldToLocal * velPerUnitImpulseB;
            */

            var delVelWorldA = -1*(impulseToTorqueA * a.GetInverseInertiaMoment() * impulseToTorqueA); //matrix which transforms impluse -> velocity in world coordinates ie: Velocity Per Unit Impulse
            var delVelWorldB = -1*(impulseToTorqueB * b.GetInverseInertiaMoment() * impulseToTorqueB);

            var delVelWorld = delVelWorldA + delVelWorldB;
            var delVelContact = worldToLocal * delVelWorld * localToWorld;

            var invM = a.InvMass + b.InvMass;
            delVelContact.M11 += invM;
            delVelContact.M22 += invM;
            delVelContact.M33 += invM;

            MathNet.Numerics.LinearAlgebra.Matrix m = delVelContact.ToMathNet();
            var mi = m.Inverse(); //from vel per impulse -> impulse per vel
            Matrix impulsePerVel = mi.ToXNA();

            //var velKill = (desiredVel * Vector3.UnitX); //NO FRICTION
            var velKill = (desiredVel * Vector3.UnitX) - conVel.Y*Vector3.UnitY - conVel.Z*Vector3.UnitZ; //default = super mega-friction (ie: kill all talgential velocities
            var impulseContact = Vector3.TransformNormal(velKill, impulsePerVel);

            var planarImp = (float)Math.Sqrt(impulseContact.Y * impulseContact.Y + impulseContact.Z * impulseContact.Z);

            if (planarImp != 0 && planarImp > impulseContact.X * u)
            {
                //handle dynamic friction
                impulseContact.Y /= planarImp; //basically normalize (preserve direction, set len (y,x)=0
                impulseContact.Z /= planarImp;

                impulseContact.X = desiredVel / (delVelContact.M11 + delVelContact.M12 * u * impulseContact.Y + delVelContact.M13 * u * impulseContact.Z); //shorhand for the matrix transform
                impulseContact.Y *= u * impulseContact.X; //scale up the impluses as friction*normal (since impCon.X = normal)
                impulseContact.Z *= u * impulseContact.X;
            }

            //
            //impulse from ImpulseContact + apply
            //

            var impulse = impulseContact.TransformToWorld(localToWorld);
            var impulse2 = impulse.ToVector2();

            dataA.dVel = impulse2 * a.InvMass;
            dataB.dVel = -impulse2 * b.InvMass;

            var impulsiveTorqueA = Vector3.Cross(relPosA, impulse);
            var impulsiveTorqueB = Vector3.Cross(relPosB, -impulse);

            dataA.dAngVel = impulsiveTorqueA.Z * a.GetInverseInertiaMoment();
            dataB.dAngVel = impulsiveTorqueB.Z * b.GetInverseInertiaMoment();
        }
        public static float SOFTNESS = .8f; // from (0, 1] = represents how much interpenetration is tolerated

        #endregion Fields

        #region Methods

        public static ObjCollisionData AggrColData(List<ObjCollisionData> cols)
        {
            ObjCollisionData dat = new ObjCollisionData();
            float totWeight = 0f;
            foreach (var c in cols)
            {
                var weight = 1; // c.dPos.Length();

                dat.dPos += weight * c.dPos;
                dat.dVel += weight * c.dVel;
                dat.dAngVel += weight * c.dAngVel;
                totWeight += weight;
            }
            if (totWeight == 0f) totWeight = 1;
            dat.dPos /= totWeight;
            dat.dVel /= totWeight;
            dat.dAngVel /= totWeight;

            return dat;
        }