internalStep method
void
internalStep(
- 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;
}