src/collisions/src/collision-handler.js
function _resolveCollision(collision, physicsParams) {
  const collidableA = collision.collidableA;
  const collidableB = collision.collidableB;
  const previousStateA = collidableA.physicsJob.previousState;
  const previousStateB = collidableB.physicsJob.previousState;
  const nextStateA = collidableA.physicsJob.currentState;
  const nextStateB = collidableB.physicsJob.currentState;
  const centerA = collidableA.centerOfMass;
  const centerB = collidableB.centerOfMass;
  const contactPoint = collision.contactPoint;

  const contactPointOffsetA = tmpVec3;
  vec3.subtract(contactPointOffsetA, contactPoint, centerA);
  const contactPointOffsetB = tmpVec4;
  vec3.subtract(contactPointOffsetB, contactPoint, centerB);

  //
  // Calculate the relative velocity of the bodies at the point of contact.
  //
  // We use the velocity from the previous state, since it is the velocity that led to the
  // collision.
  //

  const velocityA = tmpVec1;
  vec3.cross(tmpVec1, previousStateA.angularVelocity, contactPointOffsetA);
  vec3.add(velocityA, previousStateA.velocity, tmpVec1);

  const velocityB = tmpVec2;
  vec3.cross(tmpVec2, previousStateB.angularVelocity, contactPointOffsetB);
  vec3.add(velocityB, previousStateB.velocity, tmpVec2);

  const relativeVelocity = vec3.create();
  vec3.subtract(relativeVelocity, velocityB, velocityA);

  if (vec3.dot(relativeVelocity, collision.contactNormal) >= 0) {
    // If the relative velocity is not pointing against the normal, then the normal was calculated
    // incorrectly (this is likely due to the time step being too large and the fact that our
    // contact calculations don't consider velocity). So update the contact normal to be in the
    // direction of the relative velocity.

    // TODO: Check that this works as expected.

    // console.warn('Non-collision because objects are moving away from each other.');

    vec3.copy(collision.contactNormal, relativeVelocity);
    vec3.normalize(collision.contactNormal, collision.contactNormal);
    vec3.negate(collision.contactNormal, collision.contactNormal);
  }

  _applyImpulseFromCollision(collision, relativeVelocity, contactPointOffsetA,
      contactPointOffsetB, physicsParams);

  // NOTE: This state reversion is only applied to collidableA. This assumes that only A is moving
  // during this iteration of the collision pipeline.

  // Revert to the position and orientation from immediately before the collision.
  vec3.copy(nextStateA.position, previousStateA.position);
  quat.copy(nextStateA.orientation, previousStateA.orientation);

  // Also revert the collidables' position and orientation.
  collidableA.position = previousStateA.position;
  collidableA.orientation = previousStateA.orientation;

  nextStateA.updateDependentFields();
  nextStateB.updateDependentFields();
}
function _resolveCollision(collision, physicsParams) {
  const collidableA = collision.collidableA;
  const collidableB = collision.collidableB;
  const previousStateA = collidableA.physicsJob.previousState;
  const previousStateB = collidableB.physicsJob.previousState;
  const nextStateA = collidableA.physicsJob.currentState;
  const nextStateB = collidableB.physicsJob.currentState;
  const centerA = collidableA.centerOfMass;
  const centerB = collidableB.centerOfMass;
  const contactPoint = collision.contactPoint;

  const contactPointOffsetA = tmpVec3;
  vec3.subtract(contactPointOffsetA, contactPoint, centerA);
  const contactPointOffsetB = tmpVec4;
  vec3.subtract(contactPointOffsetB, contactPoint, centerB);

  //
  // Calculate the relative velocity of the bodies at the point of contact.
  //
  // We use the velocity from the previous state, since it is the velocity that led to the
  // collision.
  //

  const velocityA = tmpVec1;
  vec3.cross(tmpVec1, previousStateA.angularVelocity, contactPointOffsetA);
  vec3.add(velocityA, previousStateA.velocity, tmpVec1);

  const velocityB = tmpVec2;
  vec3.cross(tmpVec2, previousStateB.angularVelocity, contactPointOffsetB);
  vec3.add(velocityB, previousStateB.velocity, tmpVec2);

  const relativeVelocity = vec3.create();
  vec3.subtract(relativeVelocity, velocityB, velocityA);

  if (vec3.dot(relativeVelocity, collision.contactNormal) >= 0) {
    // If the relative velocity is not pointing against the normal, then the normal was calculated
    // incorrectly (this is likely due to the time step being too large and the fact that our
    // contact calculations don't consider velocity). So update the contact normal to be in the
    // direction of the relative velocity.

    // TODO: Check that this works as expected.

    // console.warn('Non-collision because objects are moving away from each other.');

    vec3.copy(collision.contactNormal, relativeVelocity);
    vec3.normalize(collision.contactNormal, collision.contactNormal);
    vec3.negate(collision.contactNormal, collision.contactNormal);
  }

  _applyImpulseFromCollision(collision, relativeVelocity, contactPointOffsetA,
      contactPointOffsetB, physicsParams);

  // NOTE: This state reversion is only applied to collidableA. This assumes that only A is moving
  // during this iteration of the collision pipeline.

  // Revert to the position and orientation from immediately before the collision.
  vec3.copy(nextStateA.position, previousStateA.position);
  quat.copy(nextStateA.orientation, previousStateA.orientation);

  // Also revert the collidables' position and orientation.
  collidableA.position = previousStateA.position;
  collidableA.orientation = previousStateA.orientation;

  nextStateA.updateDependentFields();
  nextStateB.updateDependentFields();
}
function _resolveCollision ( collision , physicsParams ) { const collidableA = collision . collidableA ; const collidableB = collision . collidableB ; const previousStateA = collidableA . physicsJob . previousState ; const previousStateB = collidableB . physicsJob . previousState ; const nextStateA = collidableA . physicsJob . currentState ; const nextStateB = collidableB . physicsJob . currentState ; const centerA = collidableA . centerOfMass ; const centerB = collidableB . centerOfMass ; const contactPoint = collision . contactPoint ; const contactPointOffsetA = tmpVec3 ; vec3 . subtract ( contactPointOffsetA , contactPoint , centerA ) ; const contactPointOffsetB = tmpVec4 ; vec3 . subtract ( contactPointOffsetB , contactPoint , centerB ) ; // // Calculate the relative velocity of the bodies at the point of contact. // // We use the velocity from the previous state, since it is the velocity that led to the // collision. // const velocityA = tmpVec1 ; vec3 . cross ( tmpVec1 , previousStateA . angularVelocity , contactPointOffsetA ) ; vec3 . add ( velocityA , previousStateA . velocity , tmpVec1 ) ; const velocityB = tmpVec2 ; vec3 . cross ( tmpVec2 , previousStateB . angularVelocity , contactPointOffsetB ) ; vec3 . add ( velocityB , previousStateB . velocity , tmpVec2 ) ; const relativeVelocity = vec3 . create ( ) ; vec3 . subtract ( relativeVelocity , velocityB , velocityA ) ; if ( vec3 . dot ( relativeVelocity , collision . contactNormal ) >= 0 ) { // If the relative velocity is not pointing against the normal, then the normal was calculated // incorrectly (this is likely due to the time step being too large and the fact that our // contact calculations don't consider velocity). So update the contact normal to be in the // direction of the relative velocity. // TODO: Check that this works as expected. // console.warn('Non-collision because objects are moving away from each other.'); vec3 . copy ( collision . contactNormal , relativeVelocity ) ; vec3 . normalize ( collision . contactNormal , collision . contactNormal ) ; vec3 . negate ( collision . contactNormal , collision . contactNormal ) ; } _applyImpulseFromCollision ( collision , relativeVelocity , contactPointOffsetA , contactPointOffsetB , physicsParams ) ; // NOTE: This state reversion is only applied to collidableA. This assumes that only A is moving // during this iteration of the collision pipeline. // Revert to the position and orientation from immediately before the collision. vec3 . copy ( nextStateA . position , previousStateA . position ) ; quat . copy ( nextStateA . orientation , previousStateA . orientation ) ; // Also revert the collidables' position and orientation. collidableA . position = previousStateA . position ; collidableA . orientation = previousStateA . orientation ; nextStateA . updateDependentFields ( ) ; nextStateB . updateDependentFields ( ) ; }
Resolve a collision between two moving, physics-based objects.

This is based on collision-response algorithms from Wikipedia
(https://en.wikipedia.org/wiki/Collision_response#Impulse-based_reaction_model).

@param {Collision} collision
@param {PhysicsConfig} physicsParams
@private
Resolve a collision between two moving physics - based objects .