Dart Documentationbox2dIsland

Island class

class Island {
 ContactListener listener;

 List<Body> bodies;
 List<Contact> contacts;
 List<Joint> joints;

 List<Position> positions;
 List<Velocity> velocities;

 int bodyCount;
 int jointCount;
 int contactCount;

 int bodyCapacity;
 int contactCapacity;
 int jointCapacity;

 int positionIterationCount;

 // Pool objects to cut down on object creation.
 ContactSolver _contactSolver;
 Vector _translation;
 ContactImpulse impulse;

 Island() :
   _contactSolver = new ContactSolver(),
   _translation = new Vector(),
   impulse = new ContactImpulse() { }

 //TODO(gregbglw): No need to keep capacity, count and array for these items as
 // in C. Simply measure the length of the array, for example, in order to
 // determine capacity.
 void init(int argBodyCapacity, int argContactCapacity, int argJointCapacity,
     ContactListener argListener) {
   bodyCapacity = argBodyCapacity;
   contactCapacity = argContactCapacity;
   jointCapacity = argJointCapacity;
   bodyCount = 0;
   contactCount = 0;

   listener = argListener;

   if (bodies == null || bodyCapacity > bodies.length) {
     bodies = new List<Body>(bodyCapacity);
   }
   if (contacts == null || contactCapacity > contacts.length) {
     contacts = new List<Contact>(contactCapacity);
   }
   if (joints == null || jointCapacity > joints.length) {
     joints = new List<Joint>(jointCapacity);
   }

   // dynamic array
   if (velocities == null || bodyCapacity > velocities.length) {
     final List<Velocity> old = velocities == null ?
         new List<Velocity>(0) : velocities;
     velocities = new List<Velocity>(bodyCapacity);
     velocities.setRange(0, old.length, old);
     for (int i=old.length; i<velocities.length; i++) {
       velocities[i] = new Velocity();
     }
   }

   // dynamic array
   if(positions == null || bodyCapacity > positions.length){
     List<Position> old = positions == null ?
         new List<Position>(0) : positions;
     positions = new List<Position>(bodyCapacity);
     positions.setRange(0, old.length, old);
     for (int i=old.length; i<positions.length; i++) {
       positions[i] = new Position();
     }
   }
 }

 void clear() {
   bodyCount = 0;
   contactCount = 0;
   jointCount = 0;
 }

 void solve(TimeStep step, Vector gravity, bool allowSleep){
   // Integrate velocities and apply damping.
   for (int i = 0; i < bodyCount; ++i){
     Body b = bodies[i];

     if (b.type != BodyType.DYNAMIC){
       continue;
     }

     final velocityDelta = new Vector(
         (b._force.x * b.invMass + gravity.x) * step.dt,
         (b._force.y * b.invMass + gravity.y) * step.dt);
     b.linearVelocity.addLocal(velocityDelta);
     num newAngularVelocity = b.angularVelocity +
         (step.dt * b.invInertia * b._torque);
     b.angularVelocity = newAngularVelocity;

     num a = (1.0 - step.dt * b.linearDamping);
     num a1 = (0.0 > (a < 1.0 ? a : 1.0) ? 0.0 : (a < 1.0 ? a : 1.0));
     b.linearVelocity.mulLocal(a1);

     num a2 = (1.0 - step.dt * b.angularDamping);
     num b1 = (a2 < 1.0 ? a2 : 1.0);
     b.angularVelocity *= 0.0 > b1 ? 0.0 : b1;
   }

   // Partition contacts so that contacts with static bodies are solved last.
   int i1 = -1;
   for (int i2 = 0; i2 < contactCount; ++i2) {
     Fixture fixtureA = contacts[i2].fixtureA;
     Fixture fixtureB = contacts[i2].fixtureB;
     Body bodyA = fixtureA.body;
     Body bodyB = fixtureB.body;
     bool nonStatic = bodyA.type != BodyType.STATIC && bodyB.type
         != BodyType.STATIC;
     if (nonStatic){
       ++i1;
       //Swap(contacts[i1], contacts[i2]);
       Contact temp = contacts[i1];
       contacts[i1] = contacts[i2];
       contacts[i2] = temp;
     }
   }

   // Initialize velocity constraints.
   _contactSolver.init(contacts, contactCount, step.dtRatio);
   _contactSolver.warmStart();

   for (int i = 0; i < jointCount; ++i){
     joints[i].initVelocityConstraints(step);
   }

   for (int i = 0; i < step.velocityIterations; ++i) {
     for (int j = 0; j < jointCount; ++j){
       joints[j].solveVelocityConstraints(step);
     }
     _contactSolver.solveVelocityConstraints();
   }

   // Post-solve (store impulses for warm starting).
   _contactSolver.storeImpulses();

   // Integrate positions.
   Vector temp = new Vector();
   for (int i = 0; i < bodyCount; ++i){
     Body b = bodies[i];

     if (b.type == BodyType.STATIC){
       continue;
     }

     // Check for large velocities.
     _translation.setFrom(b.linearVelocity);
     _translation.mulLocal(step.dt);
     if (Vector.dot(_translation, _translation) >
         Settings.MAX_TRANSLATION_SQUARED){
       num ratio = Settings.MAX_TRANSLATION / _translation.length;
       b.linearVelocity.mulLocal(ratio);
     }

     num rotation = step.dt * b.angularVelocity;
     if (rotation * rotation > Settings.MAX_ROTATION_SQUARED) {
       num ratio = Settings.MAX_ROTATION / rotation.abs();
       b.angularVelocity *= ratio;
     }

     // Store positions for continuous collision.
     b.sweep.centerZero.setFrom(b.sweep.center);
     b.sweep.angleZero = b.sweep.angle;

     // Integrate
     temp.setFrom(b.linearVelocity);
     temp.mulLocal(step.dt);
     b.sweep.center.addLocal(temp);
     b.sweep.angle += step.dt * b.angularVelocity;

     // Compute new transform
     b.synchronizeTransform();

     // Note: shapes are synchronized later.
   }

   // Iterate over constraints.
   for (int i = 0; i < step.positionIterations; ++i){
     bool contactsOkay =
         _contactSolver.solvePositionConstraints(Settings.CONTACT_BAUMGARTE);

     bool jointsOkay = true;
     for (int j = 0; j < jointCount; ++j){
       bool jointOkay =
           joints[j].solvePositionConstraints(Settings.CONTACT_BAUMGARTE);
       jointsOkay = jointsOkay && jointOkay;
     }

     if (contactsOkay && jointsOkay){
       // Exit early if the position errors are small.
       break;
     }
   }

   report(_contactSolver.constraints);


   if (allowSleep){
     num minSleepTime = Settings.BIG_NUMBER;

     num linTolSqr = Settings.LINEAR_SLEEP_TOLERANCE
         * Settings.LINEAR_SLEEP_TOLERANCE;
     num angTolSqr = Settings.ANGULAR_SLEEP_TOLERANCE
         * Settings.ANGULAR_SLEEP_TOLERANCE;

     for (int i = 0; i < bodyCount; ++i){
       Body b = bodies[i];
       if (b.type == BodyType.STATIC){
         continue;
       }

       if ((b.flags & Body.AUTO_SLEEP_FLAG) == 0){
         b.sleepTime = 0.0;
         minSleepTime = 0.0;
       }

       if ((b.flags & Body.AUTO_SLEEP_FLAG) == 0 ||
           b.angularVelocity * b.angularVelocity > angTolSqr ||
           Vector.dot(b.linearVelocity, b.linearVelocity) > linTolSqr){
         b.sleepTime = 0.0;
         minSleepTime = 0.0;
       }
       else{
         b.sleepTime += step.dt;
         minSleepTime = Math.min(minSleepTime, b.sleepTime);
       }
     }

     if (minSleepTime >= Settings.TIME_TO_SLEEP){
       for (int i = 0; i < bodyCount; ++i){
         Body b = bodies[i];
         b.awake = false;
       }
     }
   }

 }

 /** Adds a body to the Island. */
 void addBody(Body body){
   assert(bodyCount < bodyCapacity);
   body.islandIndex = bodyCount;
   bodies[bodyCount++] = body;
 }

 /** Add a contact to the Island. */
 void addContact(Contact contact) {
   assert(contactCount < contactCapacity);
   contacts[contactCount++] = contact;
 }

 /** Add a joint to the Island. */
 void addJoint(Joint joint) {
   assert(jointCount < jointCapacity);
   joints[jointCount++] = joint;
 }

 void report(List<ContactConstraint> constraints){
   if (listener == null){
     return;
   }

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

     ContactConstraint cc = constraints[i];

     for (int j = 0; j < cc.pointCount; ++j){
       impulse.normalImpulses[j] = cc.points[j].normalImpulse;
       impulse.tangentImpulses[j] = cc.points[j].tangentImpulse;
     }

     listener.postSolve(c, impulse);
   }
 }
}

Constructors

new Island() #

Island() :
 _contactSolver = new ContactSolver(),
 _translation = new Vector(),
 impulse = new ContactImpulse() { }

Properties

List<Body> bodies #

bodies

int bodyCapacity #

bodyCapacity

int bodyCount #

bodyCount

int contactCapacity #

contactCapacity

int contactCount #

contactCount

List<Contact> contacts #

contacts

ContactImpulse impulse #

impulse

int jointCapacity #

jointCapacity

int jointCount #

jointCount

List<Joint> joints #

joints

ContactListener listener #

listener

int positionIterationCount #

positionIterationCount

List<Position> positions #

positions

List<Velocity> velocities #

velocities

Methods

void addBody(Body body) #

Adds a body to the Island.

void addBody(Body body){
 assert(bodyCount < bodyCapacity);
 body.islandIndex = bodyCount;
 bodies[bodyCount++] = body;
}

void addContact(Contact contact) #

Add a contact to the Island.

void addContact(Contact contact) {
 assert(contactCount < contactCapacity);
 contacts[contactCount++] = contact;
}

void addJoint(Joint joint) #

Add a joint to the Island.

void addJoint(Joint joint) {
 assert(jointCount < jointCapacity);
 joints[jointCount++] = joint;
}

void clear() #

void clear() {
 bodyCount = 0;
 contactCount = 0;
 jointCount = 0;
}

void init(int argBodyCapacity, int argContactCapacity, int argJointCapacity, ContactListener argListener) #

void init(int argBodyCapacity, int argContactCapacity, int argJointCapacity,
   ContactListener argListener) {
 bodyCapacity = argBodyCapacity;
 contactCapacity = argContactCapacity;
 jointCapacity = argJointCapacity;
 bodyCount = 0;
 contactCount = 0;

 listener = argListener;

 if (bodies == null || bodyCapacity > bodies.length) {
   bodies = new List<Body>(bodyCapacity);
 }
 if (contacts == null || contactCapacity > contacts.length) {
   contacts = new List<Contact>(contactCapacity);
 }
 if (joints == null || jointCapacity > joints.length) {
   joints = new List<Joint>(jointCapacity);
 }

 // dynamic array
 if (velocities == null || bodyCapacity > velocities.length) {
   final List<Velocity> old = velocities == null ?
       new List<Velocity>(0) : velocities;
   velocities = new List<Velocity>(bodyCapacity);
   velocities.setRange(0, old.length, old);
   for (int i=old.length; i<velocities.length; i++) {
     velocities[i] = new Velocity();
   }
 }

 // dynamic array
 if(positions == null || bodyCapacity > positions.length){
   List<Position> old = positions == null ?
       new List<Position>(0) : positions;
   positions = new List<Position>(bodyCapacity);
   positions.setRange(0, old.length, old);
   for (int i=old.length; i<positions.length; i++) {
     positions[i] = new Position();
   }
 }
}

void report(List<ContactConstraint> constraints) #

void report(List<ContactConstraint> constraints){
 if (listener == null){
   return;
 }

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

   ContactConstraint cc = constraints[i];

   for (int j = 0; j < cc.pointCount; ++j){
     impulse.normalImpulses[j] = cc.points[j].normalImpulse;
     impulse.tangentImpulses[j] = cc.points[j].tangentImpulse;
   }

   listener.postSolve(c, impulse);
 }
}

void solve(TimeStep step, Vector gravity, bool allowSleep) #

void solve(TimeStep step, Vector gravity, bool allowSleep){
 // Integrate velocities and apply damping.
 for (int i = 0; i < bodyCount; ++i){
   Body b = bodies[i];

   if (b.type != BodyType.DYNAMIC){
     continue;
   }

   final velocityDelta = new Vector(
       (b._force.x * b.invMass + gravity.x) * step.dt,
       (b._force.y * b.invMass + gravity.y) * step.dt);
   b.linearVelocity.addLocal(velocityDelta);
   num newAngularVelocity = b.angularVelocity +
       (step.dt * b.invInertia * b._torque);
   b.angularVelocity = newAngularVelocity;

   num a = (1.0 - step.dt * b.linearDamping);
   num a1 = (0.0 > (a < 1.0 ? a : 1.0) ? 0.0 : (a < 1.0 ? a : 1.0));
   b.linearVelocity.mulLocal(a1);

   num a2 = (1.0 - step.dt * b.angularDamping);
   num b1 = (a2 < 1.0 ? a2 : 1.0);
   b.angularVelocity *= 0.0 > b1 ? 0.0 : b1;
 }

 // Partition contacts so that contacts with static bodies are solved last.
 int i1 = -1;
 for (int i2 = 0; i2 < contactCount; ++i2) {
   Fixture fixtureA = contacts[i2].fixtureA;
   Fixture fixtureB = contacts[i2].fixtureB;
   Body bodyA = fixtureA.body;
   Body bodyB = fixtureB.body;
   bool nonStatic = bodyA.type != BodyType.STATIC && bodyB.type
       != BodyType.STATIC;
   if (nonStatic){
     ++i1;
     //Swap(contacts[i1], contacts[i2]);
     Contact temp = contacts[i1];
     contacts[i1] = contacts[i2];
     contacts[i2] = temp;
   }
 }

 // Initialize velocity constraints.
 _contactSolver.init(contacts, contactCount, step.dtRatio);
 _contactSolver.warmStart();

 for (int i = 0; i < jointCount; ++i){
   joints[i].initVelocityConstraints(step);
 }

 for (int i = 0; i < step.velocityIterations; ++i) {
   for (int j = 0; j < jointCount; ++j){
     joints[j].solveVelocityConstraints(step);
   }
   _contactSolver.solveVelocityConstraints();
 }

 // Post-solve (store impulses for warm starting).
 _contactSolver.storeImpulses();

 // Integrate positions.
 Vector temp = new Vector();
 for (int i = 0; i < bodyCount; ++i){
   Body b = bodies[i];

   if (b.type == BodyType.STATIC){
     continue;
   }

   // Check for large velocities.
   _translation.setFrom(b.linearVelocity);
   _translation.mulLocal(step.dt);
   if (Vector.dot(_translation, _translation) >
       Settings.MAX_TRANSLATION_SQUARED){
     num ratio = Settings.MAX_TRANSLATION / _translation.length;
     b.linearVelocity.mulLocal(ratio);
   }

   num rotation = step.dt * b.angularVelocity;
   if (rotation * rotation > Settings.MAX_ROTATION_SQUARED) {
     num ratio = Settings.MAX_ROTATION / rotation.abs();
     b.angularVelocity *= ratio;
   }

   // Store positions for continuous collision.
   b.sweep.centerZero.setFrom(b.sweep.center);
   b.sweep.angleZero = b.sweep.angle;

   // Integrate
   temp.setFrom(b.linearVelocity);
   temp.mulLocal(step.dt);
   b.sweep.center.addLocal(temp);
   b.sweep.angle += step.dt * b.angularVelocity;

   // Compute new transform
   b.synchronizeTransform();

   // Note: shapes are synchronized later.
 }

 // Iterate over constraints.
 for (int i = 0; i < step.positionIterations; ++i){
   bool contactsOkay =
       _contactSolver.solvePositionConstraints(Settings.CONTACT_BAUMGARTE);

   bool jointsOkay = true;
   for (int j = 0; j < jointCount; ++j){
     bool jointOkay =
         joints[j].solvePositionConstraints(Settings.CONTACT_BAUMGARTE);
     jointsOkay = jointsOkay && jointOkay;
   }

   if (contactsOkay && jointsOkay){
     // Exit early if the position errors are small.
     break;
   }
 }

 report(_contactSolver.constraints);


 if (allowSleep){
   num minSleepTime = Settings.BIG_NUMBER;

   num linTolSqr = Settings.LINEAR_SLEEP_TOLERANCE
       * Settings.LINEAR_SLEEP_TOLERANCE;
   num angTolSqr = Settings.ANGULAR_SLEEP_TOLERANCE
       * Settings.ANGULAR_SLEEP_TOLERANCE;

   for (int i = 0; i < bodyCount; ++i){
     Body b = bodies[i];
     if (b.type == BodyType.STATIC){
       continue;
     }

     if ((b.flags & Body.AUTO_SLEEP_FLAG) == 0){
       b.sleepTime = 0.0;
       minSleepTime = 0.0;
     }

     if ((b.flags & Body.AUTO_SLEEP_FLAG) == 0 ||
         b.angularVelocity * b.angularVelocity > angTolSqr ||
         Vector.dot(b.linearVelocity, b.linearVelocity) > linTolSqr){
       b.sleepTime = 0.0;
       minSleepTime = 0.0;
     }
     else{
       b.sleepTime += step.dt;
       minSleepTime = Math.min(minSleepTime, b.sleepTime);
     }
   }

   if (minSleepTime >= Settings.TIME_TO_SLEEP){
     for (int i = 0; i < bodyCount; ++i){
       Body b = bodies[i];
       b.awake = false;
     }
   }
 }

}