Dart Documentationbox2dContact

Contact abstract class

abstract class Contact {
 /** Used when crawling contact graph when forming islands. */
 static const int ISLAND_FLAG = 0x0001;
 static const int TOUCHING_FLAG = 0x0002;
 static const int ENABLED_FLAG = 0x0004;
 static const int FILTER_FLAG = 0x0008;
 static const int BULLET_HIT_FLAG = 0x0010;

 /** The flags for this Contact. */
 int flags;

 /** World pool and list pointers. */
 //TODO(gregbglw): Write benchmark comparing this linked list style with just
 // using a list.
 Contact prev;
 Contact next;

 /** Nodes for connecting bodies. */
 ContactEdge edge1;
 ContactEdge edge2;

 Fixture fixtureA;
 Fixture fixtureB;

 Manifold manifold;

 num toiCount;

 DefaultWorldPool pool;

 /** Pool manifold for internal use. */
 final Manifold _oldManifold;

 Contact(DefaultWorldPool pool) :
   manifold = new Manifold(),
   fixtureA = null,
   fixtureB = null,
   edge1 = new ContactEdge(),
   edge2 = new ContactEdge(),
   pool = pool,
   _oldManifold = new Manifold() { }

 /**
  * Initialization for pooling.
  */
 void init(Fixture fixA, Fixture fixB) {
   flags = 0;
   fixtureA = fixA;
   fixtureB = fixB;

   manifold.pointCount = 0;

   prev = null;
   next = null;

   edge1.contact = null;
   edge1.prev = null;
   edge1.next = null;
   edge1.other = null;

   edge2.contact = null;
   edge2.prev = null;
   edge2.next = null;
   edge2.other = null;

   toiCount = 0;
 }

 /**
  * Intializes the given world manifold.
  */
 void getWorldManifold(WorldManifold worldManifold) {
   final Body bodyA = fixtureA.body;
   final Body bodyB = fixtureB.body;
   final Shape shapeA = fixtureA.shape;
   final Shape shapeB = fixtureB.shape;

   worldManifold.initialize(manifold, bodyA.originTransform,
       shapeA.radius, bodyB.originTransform, shapeB.radius);
 }

 /**
  * Is this contact touching
  */
 bool get touching => (flags & TOUCHING_FLAG) == TOUCHING_FLAG;

 /**
  * Enable/disable this contact. This can be used inside the pre-solve
  * contact listener. The contact is only disabled for the current time step
  * (or sub-step in continuous collisions).
  */
 void set enabled(bool flag) {
   if (flag) {
     flags |= ENABLED_FLAG;
   } else {
     flags &= ~ENABLED_FLAG;
   }
 }

 bool get enabled => (flags & ENABLED_FLAG) == ENABLED_FLAG;

 /** Abstract method. */
 void evaluate(Manifold argManifold, Transform xfA, Transform xfB);

 /**
  * Flag this contact for filtering. Filtering will occur the next time step.
  */
 void flagForFiltering() {
   flags |= FILTER_FLAG;
 }

 void update(ContactListener listener) {
   _oldManifold.setFrom(manifold);

   // Re-enable this contact.
   flags |= ENABLED_FLAG;

   bool touching = false;
   bool wasTouching = (flags & TOUCHING_FLAG) == TOUCHING_FLAG;

   bool sensorA = fixtureA.isSensor;
   bool sensorB = fixtureB.isSensor;
   bool sensor = sensorA || sensorB;

   Body bodyA = fixtureA.body;
   Body bodyB = fixtureB.body;
   Transform xfA = bodyA.originTransform;
   Transform xfB = bodyB.originTransform;

   if (sensor) {
     Shape shapeA = fixtureA.shape;
     Shape shapeB = fixtureB.shape;
     touching = pool.collision.testOverlap(shapeA, shapeB, xfA, xfB);

     // Sensors don't generate manifolds.
     manifold.pointCount = 0;
   } else {
     evaluate(manifold, xfA, xfB);
     touching = manifold.pointCount > 0;

     // Match old contact ids to new contact ids and copy the
     // stored impulses to warm start the solver.
     for (int i = 0; i < manifold.pointCount; ++i) {
       ManifoldPoint mp2 = manifold.points[i];
       mp2.normalImpulse = 0.0;
       mp2.tangentImpulse = 0.0;
       ContactID id2 = mp2.id;

       for (int j = 0; j < _oldManifold.pointCount; ++j) {
         ManifoldPoint mp1 = _oldManifold.points[j];

         if (mp1.id.isEqual(id2)) {
           mp2.normalImpulse = mp1.normalImpulse;
           mp2.tangentImpulse = mp1.tangentImpulse;
           break;
         }
       }
     }

     if (touching != wasTouching) {
       bodyA.awake = true;
       bodyB.awake = true;
     }
   }

   if (touching) {
     flags |= TOUCHING_FLAG;
   } else {
     flags &= ~TOUCHING_FLAG;
   }

   if (listener == null) {
     return;
   }

   if (wasTouching == false && touching == true) {
     listener.beginContact(this);
   }

   if (wasTouching == true && touching == false) {
     listener.endContact(this);
   }

   if (sensor == false && touching) {
     listener.preSolve(this, _oldManifold);
   }
 }
}

Subclasses

CircleContact, PolygonAndCircleContact, PolygonContact

Static Properties

const int BULLET_HIT_FLAG #

BULLET_HIT_FLAG = 0x0010

const int ENABLED_FLAG #

ENABLED_FLAG = 0x0004

const int FILTER_FLAG #

FILTER_FLAG = 0x0008

const int ISLAND_FLAG #

ISLAND_FLAG = 0x0001

const int TOUCHING_FLAG #

TOUCHING_FLAG = 0x0002

Constructors

new Contact(DefaultWorldPool pool) #

Contact(DefaultWorldPool pool) :
 manifold = new Manifold(),
 fixtureA = null,
 fixtureB = null,
 edge1 = new ContactEdge(),
 edge2 = new ContactEdge(),
 pool = pool,
 _oldManifold = new Manifold() { }

Properties

ContactEdge edge1 #

edge1

ContactEdge edge2 #

edge2

bool enabled #

Enable/disable this contact. This can be used inside the pre-solve contact listener. The contact is only disabled for the current time step (or sub-step in continuous collisions).

bool get enabled => (flags & ENABLED_FLAG) == ENABLED_FLAG;
void set enabled(bool flag) {
 if (flag) {
   flags |= ENABLED_FLAG;
 } else {
   flags &= ~ENABLED_FLAG;
 }
}

Fixture fixtureA #

fixtureA

Fixture fixtureB #

fixtureB

int flags #

flags

Manifold manifold #

manifold

Contact next #

next

DefaultWorldPool pool #

pool

Contact prev #

prev

num toiCount #

toiCount

final bool touching #

Is this contact touching

bool get touching => (flags & TOUCHING_FLAG) == TOUCHING_FLAG;

Methods

abstract void evaluate(Manifold argManifold, Transform xfA, Transform xfB) #

Abstract method.

void flagForFiltering() #

Flag this contact for filtering. Filtering will occur the next time step.

void flagForFiltering() {
 flags |= FILTER_FLAG;
}

void getWorldManifold(WorldManifold worldManifold) #

Intializes the given world manifold.

void getWorldManifold(WorldManifold worldManifold) {
 final Body bodyA = fixtureA.body;
 final Body bodyB = fixtureB.body;
 final Shape shapeA = fixtureA.shape;
 final Shape shapeB = fixtureB.shape;

 worldManifold.initialize(manifold, bodyA.originTransform,
     shapeA.radius, bodyB.originTransform, shapeB.radius);
}

void init(Fixture fixA, Fixture fixB) #

Initialization for pooling.

void init(Fixture fixA, Fixture fixB) {
 flags = 0;
 fixtureA = fixA;
 fixtureB = fixB;

 manifold.pointCount = 0;

 prev = null;
 next = null;

 edge1.contact = null;
 edge1.prev = null;
 edge1.next = null;
 edge1.other = null;

 edge2.contact = null;
 edge2.prev = null;
 edge2.next = null;
 edge2.other = null;

 toiCount = 0;
}

void update(ContactListener listener) #

void update(ContactListener listener) {
 _oldManifold.setFrom(manifold);

 // Re-enable this contact.
 flags |= ENABLED_FLAG;

 bool touching = false;
 bool wasTouching = (flags & TOUCHING_FLAG) == TOUCHING_FLAG;

 bool sensorA = fixtureA.isSensor;
 bool sensorB = fixtureB.isSensor;
 bool sensor = sensorA || sensorB;

 Body bodyA = fixtureA.body;
 Body bodyB = fixtureB.body;
 Transform xfA = bodyA.originTransform;
 Transform xfB = bodyB.originTransform;

 if (sensor) {
   Shape shapeA = fixtureA.shape;
   Shape shapeB = fixtureB.shape;
   touching = pool.collision.testOverlap(shapeA, shapeB, xfA, xfB);

   // Sensors don't generate manifolds.
   manifold.pointCount = 0;
 } else {
   evaluate(manifold, xfA, xfB);
   touching = manifold.pointCount > 0;

   // Match old contact ids to new contact ids and copy the
   // stored impulses to warm start the solver.
   for (int i = 0; i < manifold.pointCount; ++i) {
     ManifoldPoint mp2 = manifold.points[i];
     mp2.normalImpulse = 0.0;
     mp2.tangentImpulse = 0.0;
     ContactID id2 = mp2.id;

     for (int j = 0; j < _oldManifold.pointCount; ++j) {
       ManifoldPoint mp1 = _oldManifold.points[j];

       if (mp1.id.isEqual(id2)) {
         mp2.normalImpulse = mp1.normalImpulse;
         mp2.tangentImpulse = mp1.tangentImpulse;
         break;
       }
     }
   }

   if (touching != wasTouching) {
     bodyA.awake = true;
     bodyB.awake = true;
   }
 }

 if (touching) {
   flags |= TOUCHING_FLAG;
 } else {
   flags &= ~TOUCHING_FLAG;
 }

 if (listener == null) {
   return;
 }

 if (wasTouching == false && touching == true) {
   listener.beginContact(this);
 }

 if (wasTouching == true && touching == false) {
   listener.endContact(this);
 }

 if (sensor == false && touching) {
   listener.preSolve(this, _oldManifold);
 }
}