solve method

void solve(
  1. TimeStep step
)

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());
}