internalStep method

void internalStep(
  1. double dt
)

Implementation

void internalStep(double dt) {
  this.dt = dt;

  //final world = this;
  //final that = this;
  final contacts = this.contacts;
  final p1 = worldStepP1;
  final p2 = worldStepP2;
  int N = this.bodies.length;
  final bodies = this.bodies;
  final solver = this.solver;
  final gravity = this.gravity;
  final doProfiling = this.doProfiling;
  final profile = this.profile;
  int profilingStart = -1;
  final constraints = this.constraints;
  final frictionEquationPool = worldStepFrictionEquationPool;
  //final gnorm = gravity.length();
  final gx = gravity.x;
  final gy = gravity.y;
  final gz = gravity.z;
  int i = 0;

  if (doProfiling) {
    profilingStart = performance.now();
  }
  // Add gravity to all objects
  for (i = 0; i != N; i++) {
    final bi = bodies[i];
    if (bi.type == BodyTypes.dynamic) {
      // Only for dynamic bodies
      final f = bi.force;

      final m = bi.mass;
      f.x += m * gx;
      f.y += m * gy;
      f.z += m * gz;
    }
  }
  // Update subsystems
  for (int i = 0, nSubsystems = subsystems.length; i != nSubsystems; i++) {
    subsystems[i].update();
  }

  // Collision detection
  if (doProfiling) {
    profilingStart = performance.now();
  }
  p1.clear(); // Clean up pair arrays from last step
  p2.clear();
  broadphase.collisionPairs(this, p1, p2);
  if (doProfiling) {
    profile.broadphase = performance.now() - profilingStart;
  }
  // Remove constrained pairs with collideConnected == false
  int nConstraints = constraints.length;
  for (i = 0; i != nConstraints; i++) {
    final c = constraints[i];
    if (!c.collideConnected) {
      for (int j = p1.length - 1; j >= 0; j -= 1) {
        if ((c.bodyA == p1[j] && c.bodyB == p2[j]) || (c.bodyB == p1[j] && c.bodyA == p2[j])) {
          p1.removeAt(j);
          p2.removeAt(j);
        }
      }
    }
  }
  collisionMatrixTick();

  // Generate contacts
  if (doProfiling) {
    profilingStart = performance.now();
  }
  final oldcontacts = worldStepOldContacts;
  final nOldContacts = contacts.length;

  for (i = 0; i != nOldContacts; i++) {
    oldcontacts.add(contacts[i]);
  }
  contacts.clear();

  // Transfer FrictionEquation from current list to the pool for reuse
  final nOldFrictionEquations = frictionEquations.length;
  for (i = 0; i != nOldFrictionEquations; i++) {
    frictionEquationPool.add(frictionEquations[i]);
  }
  frictionEquations.clear();
  narrowphase.getContacts(
    p1,
    p2,
    this,
    contacts,
    oldcontacts, // To be reused
    frictionEquations,
    frictionEquationPool
  );

  if (doProfiling) {
    profile.narrowphase = performance.now() - profilingStart;
  }

  // Loop over all collisions
  if (doProfiling) {
    profilingStart = performance.now();
  }
  // Add all friction eqs
  for (i = 0; i < frictionEquations.length; i++) {
    solver.addEquation(frictionEquations[i]);
  }

  final ncontacts = contacts.length;
  for (int k = 0; k != ncontacts; k++) {
    // Current contact
    final c = contacts[k];

    // Get current collision indeces
    final bi = c.bi;

    final bj = c.bj;
    final si = c.si;
    final sj = c.sj;

    // If friction or restitution were specified in the material, use them
    if (bi.material != null && bj.material != null) {
      if (bi.material!.restitution >= 0 && bj.material!.restitution >= 0) {
        c.restitution = bi.material!.restitution * bj.material!.restitution;
      }
    }

    solver.addEquation(c);

    if (
      bi.allowSleep &&
      bi.type == BodyTypes.dynamic &&
      bi.sleepState == BodySleepStates.sleeping &&
      bj.sleepState == BodySleepStates.awake &&
      bj.type != BodyTypes.static
    ) {
      final speedSquaredB = bj.velocity.lengthSquared() + bj.angularVelocity.lengthSquared();
      final speedLimitSquaredB = math.pow(bj.sleepSpeedLimit,2);
      if (speedSquaredB >= speedLimitSquaredB * 2) {
        bi.wakeUpAfterNarrowphase = true;
      }
    }

    if (
      bj.allowSleep &&
      bj.type == BodyTypes.dynamic &&
      bj.sleepState == BodySleepStates.sleeping &&
      bi.sleepState == BodySleepStates.awake &&
      bi.type != BodyTypes.static
    ) {
      final speedSquaredA = bi.velocity.lengthSquared() + bi.angularVelocity.lengthSquared();
      final speedLimitSquaredA = math.pow(bi.sleepSpeedLimit,2);
      if (speedSquaredA >= speedLimitSquaredA * 2) {
        bj.wakeUpAfterNarrowphase = true;
      }
    }

    // Now we know that i and j are in contact. Set collision matrix state
    collisionMatrix.set(bi, bj, true);

    if (collisionMatrixPrevious.get(bi, bj) != 0) {
      // First contact!
      // We reuse the collideEvent object, otherwise we will end up creating objects for each contact, even if there's no event listener attached.
      _worldStepCollideEvent.body = bj;
      _worldStepCollideEvent.contact = c;
      bi.dispatchEvent(_worldStepCollideEvent);

      _worldStepCollideEvent.body = bi;
      bj.dispatchEvent(_worldStepCollideEvent);
    }

    bodyOverlapKeeper.set(bi.id, bj.id);
    shapeOverlapKeeper.set(si.id, sj.id);
  }

  emitContactEvents();

  if (doProfiling) {
    profile.makeContactConstraints = performance.now() - profilingStart;
    profilingStart = performance.now();
  }

  // Wake up bodies
  for (i = 0; i != N; i++) {
    final bi = bodies[i];
    if (bi.wakeUpAfterNarrowphase) {
      bi.wakeUp();
      bi.wakeUpAfterNarrowphase = false;
    }
  }

  // Add user-added constraints
  nConstraints = constraints.length;
  for (i = 0; i != nConstraints; i++) {
    final c = constraints[i];
    c.update();
    for (int j = 0, neq = c.equations.length; j != neq; j++) {
      final eq = c.equations[j];
      solver.addEquation(eq);
    }
  }

  // Solve the constrained system
  solver.solve(dt, this);

  if (doProfiling) {
    profile.solve = performance.now() - profilingStart;
  }

  // Remove all contacts from solver
  solver.removeAllEquations();

  // Apply damping, see http://code.google.com/p/bullet/issues/detail?id=74 for details
  for (i = 0; i != N; i++) {
    final bi = bodies[i];
    if (bi.type == BodyTypes.dynamic) {
      // Only for dynamic bodies
      final ld = math.pow(1.0 - bi.linearDamping, dt).toDouble();
      final v = bi.velocity;
      v.scale(ld, v);
      final av = bi.angularVelocity;
      final ad = math.pow(1.0 - bi.angularDamping, dt).toDouble();
      av.scale(ad, av);
    }
  }

 dispatchEvent(_worldStepPreStepEvent);

  // Leap frog
  if (doProfiling) {
    profilingStart = performance.now();
  }
  final stepnumber = this.stepnumber;
  final quatNormalize = stepnumber % (quatNormalizeSkip + 1) == 0;
  final quatNormalizeFast = this.quatNormalizeFast;

  for (i = 0; i != N; i++) {
    bodies[i].integrate(dt, quatNormalize, quatNormalizeFast);
  }
  clearForces();

  broadphase.dirty = true;

  if (doProfiling) {
    profile.integrate = performance.now() - profilingStart;
  }

  // Update step number
  this.stepnumber += 1;

  dispatchEvent(_worldStepPostStepEvent);

  // Sleeping update
  bool hasActiveBodies = true;
  if (allowSleep) {
    hasActiveBodies = false;
    for (i = 0; i != N; i++) {
      final bi = bodies[i];
      bi.sleepTick(time);

      if (bi.sleepState != BodySleepStates.sleeping) {
        hasActiveBodies = true;
      }
    }
  }
  this.hasActiveBodies = hasActiveBodies;
}