Beispiel #1
0
        public Vertex3D SurfaceAcceleration(Vertex3D surfP)
        {
            // tangential acceleration = (0, 0, omega) x surfP
            var tangAcc = Vertex3D.CrossZ(_angularAcceleration, surfP);

            // centripetal acceleration = (0,0,omega) x ( (0,0,omega) x surfP )
            var av2      = AngleSpeed * AngleSpeed;
            var centrAcc = new Vertex3D(-av2 * surfP.X, -av2 * surfP.Y, 0);

            return(tangAcc.Add(centrAcc));
        }
Beispiel #2
0
        public override void Contact(CollisionEvent coll, float dTime, PlayerPhysics physics)
        {
            var ball   = coll.Ball;
            var normal = coll.HitNormal;

            //#ifdef PhysicsConstants.EMBEDDED
            if (coll.HitDistance < -PhysicsConstants.Embedded)
            {
                // magic to avoid balls being pushed by each other through resting flippers!
                ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(0.1f));
            }
            //#endif

            var vRel = new Vertex3D();
            var rB   = new Vertex3D();
            var rF   = new Vertex3D();

            GetRelativeVelocity(normal, ball, vRel, rB, rF);

            // this should be zero, but only up to +/- C_CONTACTVEL
            var normVel = vRel.Dot(normal);

            // If some collision has changed the ball's velocity, we may not have to do anything.
            if (normVel <= PhysicsConstants.ContactVel)
            {
                // compute accelerations of point on ball and flipper
                var aB   = ball.Hit.SurfaceAcceleration(rB, physics);
                var aF   = _mover.SurfaceAcceleration(rF);
                var aRel = aB.Clone().Sub(aF);

                // time derivative of the normal vector
                var normalDeriv = Vertex3D.CrossZ(_mover.AngleSpeed, normal);

                // relative acceleration in the normal direction
                var normAcc = aRel.Dot(normal) + 2.0f * normalDeriv.Dot(vRel);

                if (normAcc >= 0)
                {
                    return;                     // objects accelerating away from each other, nothing to do
                }

                // hypothetical accelerations arising from a unit contact force in normal direction
                var aBc             = normal.Clone().MultiplyScalar(ball.Hit.InvMass);
                var pv2             = normal.Clone().MultiplyScalar(-1);
                var cross           = Vertex3D.CrossProduct(rF, pv2);
                var pv1             = cross.Clone().DivideScalar(_mover.Inertia);
                var aFc             = Vertex3D.CrossProduct(pv1, rF);
                var contactForceAcc = normal.Dot(aBc.Clone().Sub(aFc));

                // find j >= 0 such that normAcc + j * contactForceAcc >= 0  (bodies should not accelerate towards each other)
                var j = -normAcc / contactForceAcc;

                // kill any existing normal velocity
                ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(j * dTime * ball.Hit.InvMass - coll.HitOrgNormalVelocity));
                _mover.ApplyImpulse(cross.Clone().MultiplyScalar(j * dTime));

                // apply friction

                // first check for slippage
                var      slip        = vRel.Clone().Sub(normal.Clone().MultiplyScalar(normVel));     // calc the tangential slip velocity
                var      maxFriction = j * Friction;
                var      slipSpeed   = slip.Length();
                Vertex3D slipDir;
                Vertex3D crossF;
                float    numer;
                float    denomF;
                Vertex3D pv13;

                if (slipSpeed < PhysicsConstants.Precision)
                {
                    // slip speed zero - static friction case
                    var slipAcc = aRel.Clone().Sub(normal.Clone().MultiplyScalar(aRel.Dot(normal)));                     // calc the tangential slip acceleration

                    // neither slip velocity nor slip acceleration? nothing to do here
                    if (slipAcc.LengthSq() < 1e-6)
                    {
                        return;
                    }

                    slipDir = slipAcc.Normalize();
                    numer   = -slipDir.Dot(aRel);
                    crossF  = Vertex3D.CrossProduct(rF, slipDir);
                    pv13    = crossF.Clone().DivideScalar(-_mover.Inertia);
                    denomF  = slipDir.Dot(Vertex3D.CrossProduct(pv13, rF));
                }
                else
                {
                    // nonzero slip speed - dynamic friction case
                    slipDir = slip.Clone().DivideScalar(slipSpeed);

                    numer  = -slipDir.Dot(vRel);
                    crossF = Vertex3D.CrossProduct(rF, slipDir);
                    pv13   = crossF.Clone().DivideScalar(_mover.Inertia);
                    denomF = slipDir.Dot(Vertex3D.CrossProduct(pv13, rF));
                }

                var crossB   = Vertex3D.CrossProduct(rB, slipDir);
                var pv12     = crossB.Clone().DivideScalar(ball.Hit.Inertia);
                var denomB   = ball.Hit.InvMass + slipDir.Dot(Vertex3D.CrossProduct(pv12, rB));
                var friction = Functions.Clamp(numer / (denomB + denomF), -maxFriction, maxFriction);

                ball.Hit.ApplySurfaceImpulse(
                    crossB.Clone().MultiplyScalar(dTime * friction),
                    slipDir.Clone().MultiplyScalar(dTime * friction)
                    );
                _mover.ApplyImpulse(crossF.Clone().MultiplyScalar(-dTime * friction));
            }
        }
Beispiel #3
0
 // rigid body functions
 public Vertex3D SurfaceVelocity(Vertex3D surfP)
 {
     return(Vertex3D.CrossZ(AngleSpeed, surfP));
 }