Пример #1
0
 public World(AABB worldAABB, Vec2 gravity, bool doSleep)
 {
     this._destructionListener = null;
     this._boundaryListener = null;
     this._contactFilter = WorldCallback.DefaultFilter;
     this._contactListener = null;
     this._debugDraw = null;
     this._bodyList = null;
     this._contactList = null;
     this._jointList = null;
     this._bodyCount = 0;
     this._contactCount = 0;
     this._jointCount = 0;
     this._warmStarting = true;
     this._continuousPhysics = true;
     this._allowSleep = doSleep;
     this._gravity = gravity;
     this._lock = false;
     this._inv_dt0 = 0f;
     this._contactManager = new ContactManager();
     this._contactManager._world = this;
     this._broadPhase = new BroadPhase(worldAABB, this._contactManager);
     BodyDef def = new BodyDef();
     this._groundBody = this.CreateBody(def);
 }
Пример #2
0
        public void BeginContact(Contact contact)
        {
            if (contact.FixtureA.UserData is IEntity && contact.FixtureB.UserData is IEntity) {
                IEntity A = (IEntity)contact.FixtureA.UserData;
                IEntity B = (IEntity)contact.FixtureB.UserData;

                A.OnCollides(B);
                B.OnCollides(A);
            }
        }
Пример #3
0
        public ContactManager()
        {
            _broadPhase = new BroadPhase();
            _defaultFilter = new ContactFilter();
            _defaultListener = new ContactListener();

            _contactList = null;
            _contactCount = 0;
            _contactFilter = _defaultFilter;
            _contactListener = _defaultListener;
        }
Пример #4
0
 void OnEndContact(Box2DX.Dynamics.Contact contact)
 {
     if ((contact.GetShape1().UserData is Actor) && (contact.GetShape2().UserData is Actor))
     {
         (contact.GetShape1().UserData as Actor).OnEndContact((contact.GetShape2().UserData as Actor), contact.GetShape1(), contact.GetShape2());
         (contact.GetShape2().UserData as Actor).OnEndContact((contact.GetShape1().UserData as Actor), contact.GetShape2(), contact.GetShape1());
     }
     else
     {
         throw new Exceptions.PhysicsBodyDataIsBroken("This contact listener requires for user data to be owner of the component to properly operate");
     }
 }
		public ContactSolver(TimeStep step, Contact[] contacts, int contactCount)
		{
			_step = step;
			_constraintCount = contactCount;

			_constraints = new ContactConstraint[_constraintCount];
			for (int i = 0; i < _constraintCount; i++)
			{
				_constraints[i] = new ContactConstraint();
			}

			for (int i = 0; i < _constraintCount; ++i)
			{
				Contact contact = contacts[i];

				Fixture fixtureA = contact._fixtureA;
				Fixture fixtureB = contact._fixtureB;
				Shape shapeA = fixtureA.Shape;
				Shape shapeB = fixtureB.Shape;
				float radiusA = shapeA._radius;
				float radiusB = shapeB._radius;
				Body bodyA = fixtureA.Body;
				Body bodyB = fixtureB.Body;
				Manifold manifold = contact.Manifold;

				float friction = Settings.MixFriction(fixtureA.Friction, fixtureB.Friction);
				float restitution = Settings.MixRestitution(fixtureA.Restitution, fixtureB.Restitution);

				Box2DXDebug.Assert(manifold.PointCount > 0);

				WorldManifold worldManifold = new WorldManifold();
				worldManifold.Initialize(manifold, bodyA._xf, radiusA, bodyB._xf, radiusB);

				ContactConstraint cc = _constraints[i];
				cc.BodyA = bodyA;
				cc.BodyB = bodyB;
				cc.Manifold = manifold;
				cc.Normal = worldManifold.Normal;
				cc.PointCount = manifold.PointCount;
				cc.Friction = friction;
				cc.Restitution = restitution;

				cc.LocalPlaneNormal = manifold.LocalPlaneNormal;
				cc.LocalPoint = manifold.LocalPoint;
				cc.Radius = radiusA + radiusB;
				cc.Type = manifold.Type;

				ContactSolverSetup(manifold, worldManifold, cc);
			}
		}
Пример #6
0
        public override void PostSolve(Contact contact, ContactImpulse impulse)
        {
            if (_broke)
            {
                // The body already broke.
                return;
            }

            // Should the body break?
            int count = contact.GetManifold().PointCount;

            float maxImpulse = 0.0f;
            for (int i = 0; i < count; ++i)
            {
                maxImpulse = Math.Max(maxImpulse, impulse.normalImpulses[i]);
            }

            if (maxImpulse > 50.0f)
            {
                // Flag the body for breaking.
                _break = true;
            }
        }
Пример #7
0
 public Contact(Shape s1, Shape s2)
 {
     this._flags = (Contact.CollisionFlags)0;
     if (s1.IsSensor || s2.IsSensor)
     {
         this._flags |= Contact.CollisionFlags.NonSolid;
     }
     this._shape1 = s1;
     this._shape2 = s2;
     this._manifoldCount = 0;
     this._prev = null;
     this._next = null;
     this._node1 = new ContactEdge();
     this._node1.Contact = null;
     this._node1.Prev = null;
     this._node1.Next = null;
     this._node1.Other = null;
     this._node2 = new ContactEdge();
     this._node2.Contact = null;
     this._node2.Prev = null;
     this._node2.Next = null;
     this._node2.Other = null;
 }
        public void Destroy(Contact c)
        {
            Shape shape1 = c.GetShape1();
            Shape shape2 = c.GetShape2();
            Body body1 = shape1.GetBody();
            Body body2 = shape2.GetBody();

            ContactPoint cp = new ContactPoint();
            cp.Shape1 = shape1;
            cp.Shape2 = shape2;
            cp.Friction = Settings.MixFriction(shape1.Friction, shape2.Friction);
            cp.Restitution = Settings.MixRestitution(shape1.Restitution, shape2.Restitution);

            // Inform the user that this contact is ending.
            int manifoldCount = c.GetManifoldCount();
            if (manifoldCount > 0 && _world._contactListener!=null)
            {
                Manifold[] manifolds = c.GetManifolds();

                for (int i = 0; i < manifoldCount; ++i)
                {
                    Manifold manifold = manifolds[i];
                    cp.Normal = manifold.Normal;

                    for (int j = 0; j < manifold.PointCount; ++j)
                    {
                        ManifoldPoint mp = manifold.Points[j];
                        cp.Position = body1.GetWorldPoint(mp.LocalPoint1);
                        Vec2 v1 = body1.GetLinearVelocityFromLocalPoint(mp.LocalPoint1);
                        Vec2 v2 = body2.GetLinearVelocityFromLocalPoint(mp.LocalPoint2);
                        cp.Velocity = v2 - v1;
                        cp.Separation = mp.Separation;
                        cp.ID = mp.ID;
                        _world._contactListener.Remove(cp);
                    }
                }
            }

            // Remove from the world.
            if (c._prev != null)
            {
                c._prev._next = c._next;
            }

            if (c._next != null)
            {
                c._next._prev = c._prev;
            }

            if (c == _world._contactList)
            {
                _world._contactList = c._next;
            }

            // Remove from body 1
            if (c._node1.Prev != null)
            {
                c._node1.Prev.Next = c._node1.Next;
            }

            if (c._node1.Next != null)
            {
                c._node1.Next.Prev = c._node1.Prev;
            }

            if (c._node1 == body1._contactList)
            {
                body1._contactList = c._node1.Next;
            }

            // Remove from body 2
            if (c._node2.Prev != null)
            {
                c._node2.Prev.Next = c._node2.Next;
            }

            if (c._node2.Next != null)
            {
                c._node2.Next.Prev = c._node2.Prev;
            }

            if (c._node2 == body2._contactList)
            {
                body2._contactList = c._node2.Next;
            }

            // Call the factory.
            Contact.Destroy(c);
            --_world._contactCount;
        }
Пример #9
0
        public void AddPair(object proxyUserDataA, object proxyUserDataB)
        {
            Fixture fixtureA = (Fixture)proxyUserDataA;
            Fixture fixtureB = (Fixture)proxyUserDataB;

            Body bodyA = fixtureA.GetBody();
            Body bodyB = fixtureB.GetBody();

            // Are the fixtures on the same body?
            if (bodyA == bodyB)
            {
                return;
            }

            // Are both bodies static?
            if (bodyA.IsStatic() && bodyB.IsStatic())
            {
                return;
            }

            // Does a contact already exist?
            ContactEdge edge = bodyB.GetContactList();
            while (edge != null)
            {
                if (edge.Other == bodyA)
                {
                    Fixture fA = edge.Contact.GetFixtureA();
                    Fixture fB = edge.Contact.GetFixtureB();
                    if (fA == fixtureA && fB == fixtureB)
                    {
                        // A contact already exists.
                        return;
                    }

                    if (fA == fixtureB && fB == fixtureA)
                    {
                        // A contact already exists.
                        return;
                    }
                }

                edge = edge.Next;
            }

            // Does a joint override collision?
            if (bodyB.IsConnected(bodyA))
            {
                return;
            }

            // Check user filtering.
            if (_contactFilter.ShouldCollide(fixtureA, fixtureB) == false)
            {
                return;
            }

            // Call the factory.
            Contact c = Contact.Create(fixtureA, fixtureB);

            // Contact creation may swap fixtures.
            fixtureA = c.GetFixtureA();
            fixtureB = c.GetFixtureB();
            bodyA = fixtureA.GetBody();
            bodyB = fixtureB.GetBody();

            // Insert into the world.
            c.Prev = null;
            c.Next = _contactList;
            if (_contactList != null)
            {
                _contactList.Prev = c;
            }
            _contactList = c;

            // Connect to island graph.

            // Connect to body A
            c.NodeA.Contact = c;
            c.NodeA.Other = bodyB;

            c.NodeA.Prev = null;
            c.NodeA.Next = bodyA._contactList;
            if (bodyA._contactList != null)
            {
                bodyA._contactList.Prev = c.NodeA;
            }
            bodyA._contactList = c.NodeA;

            // Connect to body B
            c.NodeB.Contact = c;
            c.NodeB.Other = bodyA;

            c.NodeB.Prev = null;
            c.NodeB.Next = bodyB._contactList;
            if (bodyB._contactList != null)
            {
                bodyB._contactList.Prev = c.NodeB;
            }
            bodyB._contactList = c.NodeB;

            ++_contactCount;
        }
Пример #10
0
 public static new void Destroy(Contact contact)
 {
 }
Пример #11
0
        public static void Destroy(Contact contact, ShapeType typeA, ShapeType typeB)
        {
            Box2DXDebug.Assert(Initialized == true);

            if (contact.Manifold.PointCount > 0)
            {
                contact.GetFixtureA().GetBody().WakeUp();
                contact.GetFixtureB().GetBody().WakeUp();
            }

            Box2DXDebug.Assert(ShapeType.UnknownShape < typeA && typeB < ShapeType.ShapeTypeCount);
            Box2DXDebug.Assert(ShapeType.UnknownShape < typeA && typeB < ShapeType.ShapeTypeCount);

            ContactDestroyFcn destroyFcn = Registers[(int)typeA][(int)typeB].DestroyFcn;
            destroyFcn(contact);
        }
Пример #12
0
		public Contact(Shape s1, Shape s2)
		{
			_flags = 0;

			if (s1.IsSensor || s2.IsSensor)
			{
				_flags |= CollisionFlags.NonSolid;
			}

			_shape1 = s1;
			_shape2 = s2;

			_manifoldCount = 0;

			_prev = null;
			_next = null;

			_node1 = new ContactEdge();
			_node1.Contact = null;
			_node1.Prev = null;
			_node1.Next = null;
			_node1.Other = null;

			_node2 = new ContactEdge();
			_node2.Contact = null;
			_node2.Prev = null;
			_node2.Next = null;
			_node2.Other = null;
		}
Пример #13
0
 public void PostSolve(Contact contact, ContactImpulse impulse)
 {
     //eh
 }
Пример #14
0
        public Contact(Fixture fA, Fixture fB)
        {
            _flags = 0;

            if (fA.IsSensor || fB.IsSensor)
            {
                _flags |= CollisionFlags.NonSolid;
            }

            _fixtureA = fA;
            _fixtureB = fB;

            _manifold.PointCount = 0;

            _prev = null;
            _next = null;

            _nodeA = new ContactEdge();
            _nodeB = new ContactEdge();
        }
Пример #15
0
		new public static void Destroy(ref Contact contact)
		{
			contact = null;
		}
		public ContactSolver(TimeStep step, Contact[] contacts, int contactCount)
		{
			_step = step;

			_constraintCount = 0;
			for (int i = 0; i < contactCount; ++i)
			{
				Box2DXDebug.Assert(contacts[i].IsSolid());
				_constraintCount += contacts[i].GetManifoldCount();
			}

			_constraints = new ContactConstraint[_constraintCount];
			for (int i = 0; i < _constraintCount; i++)
				_constraints[i] = new ContactConstraint();

			int count = 0;
			for (int i = 0; i < contactCount; ++i)
			{
				Contact contact = contacts[i];

				Shape shape1 = contact._shape1;
				Shape shape2 = contact._shape2;
				Body b1 = shape1.GetBody();
				Body b2 = shape2.GetBody();
				int manifoldCount = contact.GetManifoldCount();
				Manifold[] manifolds = contact.GetManifolds();

				float friction = Settings.MixFriction(shape1.Friction, shape2.Friction);
				float restitution = Settings.MixRestitution(shape1.Restitution, shape2.Restitution);

				Vec2 v1 = b1._linearVelocity;
				Vec2 v2 = b2._linearVelocity;
				float w1 = b1._angularVelocity;
				float w2 = b2._angularVelocity;

				for (int j = 0; j < manifoldCount; ++j)
				{
					Manifold manifold = manifolds[j];

					Box2DXDebug.Assert(manifold.PointCount > 0);

					Vec2 normal = manifold.Normal;

					Box2DXDebug.Assert(count < _constraintCount);
					ContactConstraint cc = _constraints[count];
					cc.Body1 = b1;
					cc.Body2 = b2;
					cc.Manifold = manifold;
					cc.Normal = normal;
					cc.PointCount = manifold.PointCount;
					cc.Friction = friction;
					cc.Restitution = restitution;

					for (int k = 0; k < cc.PointCount; ++k)
					{
						ManifoldPoint cp = manifold.Points[k];
						ContactConstraintPoint ccp = cc.Points[k];

						ccp.NormalImpulse = cp.NormalImpulse;
						ccp.TangentImpulse = cp.TangentImpulse;
						ccp.Separation = cp.Separation;

						ccp.LocalAnchor1 = cp.LocalPoint1;
						ccp.LocalAnchor2 = cp.LocalPoint2;
						ccp.R1 = Common.Math.Mul(b1.GetXForm().R, cp.LocalPoint1 - b1.GetLocalCenter());
						ccp.R2 = Common.Math.Mul(b2.GetXForm().R, cp.LocalPoint2 - b2.GetLocalCenter());

						float rn1 = Vec2.Cross(ccp.R1, normal);
						float rn2 = Vec2.Cross(ccp.R2, normal);
						rn1 *= rn1;
						rn2 *= rn2;

						float kNormal = b1._invMass + b2._invMass + b1._invI * rn1 + b2._invI * rn2;

						Box2DXDebug.Assert(kNormal > Common.Settings.FLT_EPSILON);
						ccp.NormalMass = 1.0f / kNormal;

						float kEqualized = b1._mass * b1._invMass + b2._mass * b2._invMass;
						kEqualized += b1._mass * b1._invI * rn1 + b2._mass * b2._invI * rn2;

						Box2DXDebug.Assert(kEqualized > Common.Settings.FLT_EPSILON);
						ccp.EqualizedMass = 1.0f / kEqualized;

						Vec2 tangent = Vec2.Cross(normal, 1.0f);

						float rt1 = Vec2.Cross(ccp.R1, tangent);
						float rt2 = Vec2.Cross(ccp.R2, tangent);
						rt1 *= rt1;
						rt2 *= rt2;

						float kTangent = b1._invMass + b2._invMass + b1._invI * rt1 + b2._invI * rt2;

						Box2DXDebug.Assert(kTangent > Common.Settings.FLT_EPSILON);
						ccp.TangentMass = 1.0f / kTangent;

						// Setup a velocity bias for restitution.
						ccp.VelocityBias = 0.0f;
						if (ccp.Separation > 0.0f)
						{
							ccp.VelocityBias = -step.Inv_Dt * ccp.Separation; // TODO_ERIN b2TimeStep
						}
						else
						{
							float vRel = Vec2.Dot(cc.Normal, v2 + Vec2.Cross(w2, ccp.R2) - v1 - Vec2.Cross(w1, ccp.R1));
							if (vRel < -Settings.VelocityThreshold)
							{
								ccp.VelocityBias = -cc.Restitution * vRel;
							}
						}
					}

					// If we have two points, then prepare the block solver.
					if (cc.PointCount == 2)
					{
						ContactConstraintPoint ccp1 = cc.Points[0];
						ContactConstraintPoint ccp2 = cc.Points[1];

						float invMass1 = b1._invMass;
						float invI1 = b1._invI;
						float invMass2 = b2._invMass;
						float invI2 = b2._invI;

						float rn11 = Vec2.Cross(ccp1.R1, normal);
						float rn12 = Vec2.Cross(ccp1.R2, normal);
						float rn21 = Vec2.Cross(ccp2.R1, normal);
						float rn22 = Vec2.Cross(ccp2.R2, normal);

						float k11 = invMass1 + invMass2 + invI1 * rn11 * rn11 + invI2 * rn12 * rn12;
						float k22 = invMass1 + invMass2 + invI1 * rn21 * rn21 + invI2 * rn22 * rn22;
						float k12 = invMass1 + invMass2 + invI1 * rn11 * rn21 + invI2 * rn12 * rn22;

						// Ensure a reasonable condition number.
						const float k_maxConditionNumber = 100.0f;
						if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12))
						{
							// K is safe to invert.
							cc.K.Col1.Set(k11, k12);
							cc.K.Col2.Set(k12, k22);
							cc.NormalMass = cc.K.Invert();
						}
						else
						{
							// The constraints are redundant, just use one.
							// TODO_ERIN use deepest?
							cc.PointCount = 1;
						}
					}

					++count;
				}
			}

			Box2DXDebug.Assert(count == _constraintCount);
		}
Пример #17
0
 /// This lets you inspect a contact after the solver is finished. This is useful
 /// for inspecting impulses.
 /// Note: the contact manifold does not include time of impact impulses, which can be
 /// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly
 /// in a separate data structure.
 /// Note: this is only called for contacts that are touching, solid, and awake.
 public virtual void PostSolve(Contact contact, ContactImpulse impulse)
 {
     //B2_NOT_USED(contact);
     //B2_NOT_USED(impulse);
 }
Пример #18
0
 /// This is called after a contact is updated. This allows you to inspect a
 /// contact before it goes to the solver. If you are careful, you can modify the
 /// contact manifold (e.g. disable contact).
 /// A copy of the old manifold is provided so that you can detect changes.
 /// Note: this is called only for awake bodies.
 /// Note: this is called even when the number of contact points is zero.
 /// Note: this is not called for sensors.
 /// Note: if you set the number of contact points to zero, you will not
 /// get an EndContact callback. However, you may get a BeginContact callback
 /// the next step.
 public virtual void PreSolve(Contact contact, Manifold oldManifold)
 {
     //B2_NOT_USED(contact);
     //B2_NOT_USED(oldManifold);
 }
Пример #19
0
 /// Called when two fixtures cease to touch.
 public virtual void EndContact(Contact contact)
 {
     //B2_NOT_USED(contact);
 }
Пример #20
0
 /// Called when two fixtures begin to touch.
 public virtual void BeginContact(Contact contact)
 {
     //B2_NOT_USED(contact);
 }
Пример #21
0
        public Contact(Fixture fixtureA, Fixture fixtureB)
        {
            Flags = 0;

            if (fixtureA.IsSensor || fixtureB.IsSensor)
            {
                Flags |= ContactFlag.SensorFlag;
            }

            Body bodyA = fixtureA.GetBody();
            Body bodyB = fixtureB.GetBody();

            if (bodyA.IsStatic() || bodyA.IsBullet() || bodyB.IsStatic() || bodyB.IsBullet())
            {
                Flags |= ContactFlag.ContinuousFlag;
            }
            else
            {
                Flags &= ~ContactFlag.ContinuousFlag;
            }

            _fixtureA = fixtureA;
            _fixtureB = fixtureB;

            Manifold = new Manifold();
            Manifold.PointCount = 0;

            Prev = null;
            Next = null;

            NodeA = new ContactEdge();
            NodeA.Contact = null;
            NodeA.Prev = null;
            NodeA.Next = null;
            NodeA.Other = null;

            NodeB = new ContactEdge();
            NodeB.Contact = null;
            NodeB.Prev = null;
            NodeB.Next = null;
            NodeB.Other = null;
        }
Пример #22
0
        public ContactSolver(TimeStep step, Contact[] contacts, int contactCount)
        {
            Step = step;

            ConstraintCount = contactCount;
            Constraints = new ContactConstraint[ConstraintCount];

            for (int i = 0; i < ConstraintCount; ++i)
            {
                Contact contact = contacts[i];

                Fixture fixtureA = contact.GetFixtureA();
                Fixture fixtureB = contact.GetFixtureB();
                Shape shapeA = fixtureA.GetShape();
                Shape shapeB = fixtureB.GetShape();
                float radiusA = shapeA._radius;
                float radiusB = shapeB._radius;
                Body bodyA = fixtureA.GetBody();
                Body bodyB = fixtureB.GetBody();
                Manifold manifold = contact.GetManifold();

                float friction = Settings.MixFriction(fixtureA.GetFriction(), fixtureB.GetFriction());
                float restitution = Settings.MixRestitution(fixtureA.GetRestitution(), fixtureB.GetRestitution());

                Vec2 vA = bodyA._linearVelocity;
                Vec2 vB = bodyB._linearVelocity;
                float wA = bodyA._angularVelocity;
                float wB = bodyB._angularVelocity;

                Box2DXDebug.Assert(manifold.PointCount > 0);

                WorldManifold worldManifold = new WorldManifold();
                worldManifold.Initialize(manifold, bodyA.GetTransform(), radiusA, bodyB.GetTransform(), radiusB);

                ContactConstraint cc = new ContactConstraint();
                Constraints[i] = cc;
                cc.BodyA = bodyA;
                cc.BodyB = bodyB;
                cc.Manifold = manifold;
                cc.Normal = worldManifold.Normal;
                cc.PointCount = manifold.PointCount;
                cc.Friction = friction;
                cc.Restitution = restitution;

                cc.LocalPlaneNormal = manifold.LocalPlaneNormal;
                cc.LocalPoint = manifold.LocalPoint;
                cc.Radius = radiusA + radiusB;
                cc.Type = manifold.Type;

                for (int j = 0; j < cc.PointCount; ++j)
                {
                    ManifoldPoint cp = manifold.Points[j];
                    ContactConstraintPoint ccp = cc.Points[j];

                    ccp.NormalImpulse = cp.NormalImpulse;
                    ccp.TangentImpulse = cp.TangentImpulse;

                    ccp.LocalPoint = cp.LocalPoint;

                    ccp.RA = worldManifold.Points[j] - bodyA._sweep.C;
                    ccp.RB = worldManifold.Points[j] - bodyB._sweep.C;

                    float rnA = Vec2.Cross(ccp.RA, cc.Normal);
                    float rnB = Vec2.Cross(ccp.RB, cc.Normal);
                    rnA *= rnA;
                    rnB *= rnB;

                    float kNormal = bodyA._invMass + bodyB._invMass + bodyA._invI * rnA + bodyB._invI * rnB;

                    Box2DXDebug.Assert(kNormal > Settings.FLT_EPSILON);
                    ccp.NormalMass = 1.0f / kNormal;

                    float kEqualized = bodyA._mass * bodyA._invMass + bodyB._mass * bodyB._invMass;
                    kEqualized += bodyA._mass * bodyA._invI * rnA + bodyB._mass * bodyB._invI * rnB;

                    Box2DXDebug.Assert(kEqualized > Settings.FLT_EPSILON);
                    ccp.EqualizedMass = 1.0f / kEqualized;

                    Vec2 tangent = Vec2.Cross(cc.Normal, 1.0f);

                    float rtA = Vec2.Cross(ccp.RA, tangent);
                    float rtB = Vec2.Cross(ccp.RB, tangent);
                    rtA *= rtA;
                    rtB *= rtB;

                    float kTangent = bodyA._invMass + bodyB._invMass + bodyA._invI * rtA + bodyB._invI * rtB;

                    Box2DXDebug.Assert(kTangent > Settings.FLT_EPSILON);
                    ccp.TangentMass = 1.0f / kTangent;

                    // Setup a velocity bias for restitution.
                    ccp.VelocityBias = 0.0f;
                    float vRel = Vec2.Dot(cc.Normal, vB + Vec2.Cross(wB, ccp.RB) - vA - Vec2.Cross(wA, ccp.RA));
                    if (vRel < -Settings.VelocityThreshold)
                    {
                        ccp.VelocityBias = -cc.Restitution * vRel;
                    }
                }

                // If we have two points, then prepare the block solver.
                if (cc.PointCount == 2)
                {
                    ContactConstraintPoint ccp1 = cc.Points[0];
                    ContactConstraintPoint ccp2 = cc.Points[1];

                    float invMassA = bodyA._invMass;
                    float invIA = bodyA._invI;
                    float invMassB = bodyB._invMass;
                    float invIB = bodyB._invI;

                    float rn1A = Vec2.Cross(ccp1.RA, cc.Normal);
                    float rn1B = Vec2.Cross(ccp1.RB, cc.Normal);
                    float rn2A = Vec2.Cross(ccp2.RA, cc.Normal);
                    float rn2B = Vec2.Cross(ccp2.RB, cc.Normal);

                    float k11 = invMassA + invMassB + invIA * rn1A * rn1A + invIB * rn1B * rn1B;
                    float k22 = invMassA + invMassB + invIA * rn2A * rn2A + invIB * rn2B * rn2B;
                    float k12 = invMassA + invMassB + invIA * rn1A * rn2A + invIB * rn1B * rn2B;

                    // Ensure a reasonable condition number.
                    const float k_maxConditionNumber = 100.0f;
                    if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12))
                    {
                        // K is safe to invert.
                        cc.K.Col1.Set(k11, k12);
                        cc.K.Col2.Set(k12, k22);
                        cc.NormalMass = cc.K.Invert();
                    }
                    else
                    {
                        // The constraints are redundant, just use one.
                        // TODO_ERIN use deepest?
                        cc.PointCount = 1;
                    }
                }
            }
        }
Пример #23
0
		public static void Destroy(Contact contact)
		{

            //Box2DXDebug.Assert(s_initialized == true); // COMMENT IS HACK HACK HACK

			if (contact.GetManifoldCount() > 0)
			{
				contact.GetShape1().GetBody().WakeUp();
				contact.GetShape2().GetBody().WakeUp();
			}

			ShapeType type1 = contact.GetShape1().GetType();
			ShapeType type2 = contact.GetShape2().GetType();

			Box2DXDebug.Assert(ShapeType.UnknownShape < type1 && type1 < ShapeType.ShapeTypeCount);
			Box2DXDebug.Assert(ShapeType.UnknownShape < type2 && type2 < ShapeType.ShapeTypeCount);

            try
            {
                ContactDestroyFcn destroyFcn = s_registers[(int)type1][(int)type2].DestroyFcn;
                destroyFcn(contact);
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine("NullReferenceException caught in Box2DX.Dynamics.Contact#Destroy");
            }
		}
Пример #24
0
        public void EndContact(Contact contact)
        {
            if (contact.FixtureA.UserData is IEntity && contact.FixtureB.UserData is IEntity) {
                IEntity A = (IEntity)contact.FixtureA.UserData;
                IEntity B = (IEntity)contact.FixtureB.UserData;

                A.OnSeperate(B);
                B.OnSeperate(A);
            }
        }
Пример #25
0
 public void Add(Contact contact)
 {
     Box2DXDebug.Assert(_contactCount < _contactCapacity);
     _contacts[_contactCount++] = contact;
 }
Пример #26
0
 public void PreSolve(Contact contact, Manifold oldManifold)
 {
     //eh
 }
Пример #27
0
        public void Destroy(Contact c)
        {
            Fixture fixtureA = c.GetFixtureA();
            Fixture fixtureB = c.GetFixtureB();
            Body body1 = fixtureA.GetBody();
            Body body2 = fixtureB.GetBody();

            if (c.Manifold.PointCount > 0)
            {
                _contactListener.EndContact(c);
            }

            // Remove from the world.
            if (c.Prev != null)
            {
                c.Prev.Next = c.Next;
            }

            if (c.Next != null)
            {
                c.Next.Prev = c.Prev;
            }

            if (c == _contactList)
            {
                _contactList = c.Next;
            }

            // Remove from body 1
            if (c.NodeA.Prev != null)
            {
                c.NodeA.Prev.Next = c.NodeA.Next;
            }

            if (c.NodeA.Next != null)
            {
                c.NodeA.Next.Prev = c.NodeA.Prev;
            }

            if (c.NodeA == body1._contactList)
            {
                body1._contactList = c.NodeA.Next;
            }

            // Remove from body 2
            if (c.NodeB.Prev != null)
            {
                c.NodeB.Prev.Next = c.NodeB.Next;
            }

            if (c.NodeB.Next != null)
            {
                c.NodeB.Next.Prev = c.NodeB.Prev;
            }

            if (c.NodeB == body2._contactList)
            {
                body2._contactList = c.NodeB.Next;
            }

            // Call the factory.
            Contact.Destroy(c);
            --_contactCount;
        }
Пример #28
0
 public void Add(ref Contact contact)
 {
     Box2DXDebug.Assert(ContactCount < ContactCapacity);
     Contacts[ContactCount++] = contact;
 }
Пример #29
0
 public static void Destroy(Contact contact)
 {
     Destroy(contact, contact.GetFixtureA().GetType(), contact.GetFixtureB().GetType());
 }
 public static new void Destroy(Contact contact)
 {
     contact = null;
 }
Пример #31
0
		/// <summary>
		/// Construct a world object.
		/// </summary>
		/// <param name="worldAABB">A bounding box that completely encompasses all your shapes.</param>
		/// <param name="gravity">The world gravity vector.</param>
		/// <param name="doSleep">Improve performance by not simulating inactive bodies.</param>
		public World(AABB worldAABB, Vec2 gravity, bool doSleep)
		{
			_destructionListener = null;
			_boundaryListener = null;
			_contactFilter = WorldCallback.DefaultFilter;
			_contactListener = null;
			_debugDraw = null;

			_bodyList = null;
			_contactList = null;
			_jointList = null;

			_bodyCount = 0;
			_contactCount = 0;
			_jointCount = 0;

			_warmStarting = true;
			_continuousPhysics = true;

			_allowSleep = doSleep;
			_gravity = gravity;

			_lock = false;

			_inv_dt0 = 0.0f;

			_contactManager = new ContactManager();
			_contactManager._world = this;
			_broadPhase = new BroadPhase(worldAABB, _contactManager);

			BodyDef bd = new BodyDef();
			_groundBody = CreateBody(bd);
		}