solve method
Implementation
void solve(TimeStep step) {
_profile.solveInit.startAccum();
_profile.solveVelocity.startAccum();
_profile.solvePosition.startAccum();
// update previous transforms
for (final b in bodies) {
b.previousTransform.setFrom(b.transform);
}
// Size the island for the worst case.
island.listener = contactManager.contactListener;
// Clear all the island flags.
for (final b in bodies) {
b.flags &= ~Body.islandFlag;
}
for (final c in contactManager.contacts) {
c.flags &= ~Contact.islandFlag;
}
for (final j in joints) {
j.islandFlag = false;
}
for (final seed in bodies) {
if ((seed.flags & Body.islandFlag) == Body.islandFlag) {
continue;
}
if (seed.isAwake == false || seed.isActive == false) {
continue;
}
// The seed can be dynamic or kinematic.
if (seed.bodyType == BodyType.static) {
continue;
}
// Reset island and stack.
island.clear();
stack.clear();
stack.add(seed);
seed.flags |= Body.islandFlag;
// Perform a depth first search (DFS) on the constraint graph.
while (stack.isNotEmpty) {
// Grab the next body off the stack and add it to the island.
final body = stack.removeLast();
assert(body.isActive);
island.addBody(body);
// Make sure the body is awake.
body.setAwake(true);
// To keep islands as small as possible, we don't
// propagate islands across static bodies.
if (body.bodyType == BodyType.static) {
continue;
}
// Search all contacts connected to this body.
for (final contact in body.contacts) {
// Has this contact already been added to an island?
if ((contact.flags & Contact.islandFlag) == Contact.islandFlag) {
continue;
}
// Is this contact solid and touching?
if (contact.isEnabled == false || contact.isTouching() == false) {
continue;
}
// Skip sensors.
final sensorA = contact.fixtureA.isSensor;
final sensorB = contact.fixtureB.isSensor;
if (sensorA || sensorB) {
continue;
}
island.addContact(contact);
contact.flags |= Contact.islandFlag;
final other = contact.getOtherBody(body);
// Was the other body already added to this island?
if ((other.flags & Body.islandFlag) == Body.islandFlag) {
continue;
}
stack.add(other);
other.flags |= Body.islandFlag;
}
// Search all joints connect to this body.
for (final joint in body.joints) {
if (joint.islandFlag) {
continue;
}
final other = joint.otherBody(body);
// Don't simulate joints connected to inactive bodies.
if (!other.isActive) {
continue;
}
island.addJoint(joint);
joint.islandFlag = true;
if ((other.flags & Body.islandFlag) == Body.islandFlag) {
continue;
}
stack.add(other);
other.flags |= Body.islandFlag;
}
}
island.solve(_profile, step, _gravity, allowSleep: _allowSleep);
// Post solve cleanup.
for (final bodyMeta in island.bodies) {
// Allow static bodies to participate in other islands.
final b = bodyMeta.body;
if (b.bodyType == BodyType.static) {
b.flags &= ~Body.islandFlag;
}
}
}
_profile.solveInit.endAccum();
_profile.solveVelocity.endAccum();
_profile.solvePosition.endAccum();
broadphaseTimer.reset();
// Synchronize fixtures, check for out of range bodies.
for (final b in bodies) {
// If a body was not in an island then it did not move.
if ((b.flags & Body.islandFlag) == 0) {
continue;
}
if (b.bodyType == BodyType.static) {
continue;
}
// Update fixtures (for broad-phase).
b.synchronizeFixtures();
}
// Look for new contacts.
contactManager.findNewContacts();
_profile.broadphase.record(broadphaseTimer.getMilliseconds());
}