private void Solve(TimeStep step)
{
// Step all controlls
for (Controllers.Controller controller = _controllerList; controller != null; controller = controller._next)
{
controller.Step(step);
}
// Size the island for the worst case.
Island island = new Island(_bodyCount, _contactCount, _jointCount, _contactListener);
// Clear all the island flags.
for (Body b = _bodyList; b != null; b = b._next)
{
b._flags &= ~Body.BodyFlags.Island;
}
for (Contact c = _contactList; c != null; c = c._next)
{
c._flags &= ~Contact.CollisionFlags.Island;
}
for (Joint j = _jointList; j != null; j = j._next)
{
j._islandFlag = false;
}
// Build and simulate all awake islands.
int stackSize = _bodyCount;
{
Body[] stack = new Body[stackSize];
for (Body seed = _bodyList; seed != null; seed = seed._next)
{
if ((seed._flags & (Body.BodyFlags.Island | Body.BodyFlags.Sleep | Body.BodyFlags.Frozen)) != 0)
{
continue;
}
if (seed.IsStatic())
{
continue;
}
// Reset island and stack.
island.Clear();
int stackCount = 0;
stack[stackCount++] = seed;
seed._flags |= Body.BodyFlags.Island;
// Perform a depth first search (DFS) on the constraint graph.
while (stackCount > 0)
{
// Grab the next body off the stack and add it to the island.
Body b = stack[--stackCount];
island.Add(b);
// Make sure the body is awake.
b._flags &= ~Body.BodyFlags.Sleep;
// To keep islands as small as possible, we don't
// propagate islands across static bodies.
if (b.IsStatic())
{
continue;
}
// Search all contacts connected to this body.
for (ContactEdge cn = b._contactList; cn != null; cn = cn.Next)
{
// Has this contact already been added to an island?
if ((cn.Contact._flags & (Contact.CollisionFlags.Island | Contact.CollisionFlags.NonSolid)) != 0)
{
continue;
}
// Is this contact touching?
if (cn.Contact.GetManifoldCount() == 0)
{
continue;
}
island.Add(cn.Contact);
cn.Contact._flags |= Contact.CollisionFlags.Island;
Body other = cn.Other;
// Was the other body already added to this island?
if ((other._flags & Body.BodyFlags.Island) != 0)
{
continue;
}
Box2DXDebug.Assert(stackCount < stackSize);
stack[stackCount++] = other;
other._flags |= Body.BodyFlags.Island;
}
// Search all joints connect to this body.
for (JointEdge jn = b._jointList; jn != null; jn = jn.Next)
{
if (jn.Joint._islandFlag == true)
{
continue;
}
island.Add(jn.Joint);
jn.Joint._islandFlag = true;
Body other = jn.Other;
if ((other._flags & Body.BodyFlags.Island) != 0)
{
continue;
}
Box2DXDebug.Assert(stackCount < stackSize);
stack[stackCount++] = other;
other._flags |= Body.BodyFlags.Island;
}
}
island.Solve(step, _gravity, _allowSleep);
// Post solve cleanup.
for (int i = 0; i < island._bodyCount; ++i)
{
// Allow static bodies to participate in other islands.
Body b = island._bodies[i];
if (b.IsStatic())
{
b._flags &= ~Body.BodyFlags.Island;
}
}
}
stack = null;
}
// Synchronize shapes, check for out of range bodies.
for (Body b = _bodyList; b != null; b = b.GetNext())
{
if ((b._flags & (Body.BodyFlags.Sleep | Body.BodyFlags.Frozen)) != 0)
{
continue;
}
if (b.IsStatic())
{
continue;
}
// Update shapes (for broad-phase). If the shapes go out of
// the world AABB then shapes and contacts may be destroyed,
// including contacts that are
bool inRange = b.SynchronizeShapes();
// Did the body's shapes leave the world?
if (inRange == false && _boundaryListener != null)
{
_boundaryListener.Violation(b);
}
}
// Commit shape proxy movements to the broad-phase so that new contacts are created.
// Also, some contacts can be destroyed.
_broadPhase.Commit();
}