Collision Query between Moving AABB and AABB

/// <summary>Determines the time when the box will hit another box</summary>
/// <param name="firstBox">First box that will be checked for impact</param>
/// <param name="secondBox">Second box that will be checked for impact</param>
/// <param name="firstVelocity">Velocity with which the first box is moving</param>
/// <returns>The point of first contact, if any</returns>
/// <remarks>
///   <para>
///     Conventional tests that resort to stepping often fail to detect collisions
///     between fast-moving objects. This impact determination test will always
///     detect a collision if it occurs, giving the exact time of the impact.
///   </para>
///   <para>
///     This is a simplified test that assumes a linear trajectory and does
///     not take object rotation into account. It is well suited to use on
///     two bounding boxes in order to determine if a collision between the
///     shapes contained is possible at all.
///   </para>
///   <para>
///     Idea taken from the "Simple Intersection Tests for Games" article
///     on gamasutra by Gomez.
///     (http://www.gamasutra.com/features/19991018/Gomez_1.htm)
///   </para>
/// </remarks>
internal static float? FindContact(
  AxisAlignedBox3 firstBox, Vector3 firstVelocity,
  AxisAlignedBox3 secondBox
) {
  Vector3 firstContact = new Vector3(0.0f, 0.0f, 0.0f);
  Vector3 lastContact = new Vector3(1.0f, 1.0f, 1.0f);

  // This could be done in a loop if the Vector3 class provided an indexing
  // operator for accessing the vector components. Sadly, as of XNA 1.1,
  // this is not the case, so that leaves us with this mess :)

  // X axis
  if(secondBox.Max.X < firstBox.Min.X && firstVelocity.X < 0.0f)
    firstContact.X = (secondBox.Max.X - firstBox.Min.X) / firstVelocity.X;
  else if(firstBox.Max.X < secondBox.Min.X && firstVelocity.X > 0.0f)
    firstContact.X = (secondBox.Min.X - firstBox.Max.X) / firstVelocity.X;

  if(firstBox.Max.X > secondBox.Min.X && firstVelocity.X < 0.0f)
    lastContact.X = (secondBox.Min.X - firstBox.Max.X) / firstVelocity.X;
  else if(secondBox.Max.X > firstBox.Min.X && firstVelocity.X > 0.0f)
    lastContact.X = (secondBox.Max.X - firstBox.Min.X) / firstVelocity.X;

  // Y axis
  if(secondBox.Max.Y < firstBox.Min.Y && firstVelocity.Y < 0.0f)
    firstContact.Y = (secondBox.Max.Y - firstBox.Min.Y) / firstVelocity.Y;
  else if(firstBox.Max.Y < secondBox.Min.Y && firstVelocity.Y > 0.0f)
    firstContact.Y = (secondBox.Min.Y - firstBox.Max.Y) / firstVelocity.Y;

  if(firstBox.Max.Y > secondBox.Min.Y && firstVelocity.Y < 0.0f)
    lastContact.Y = (secondBox.Min.Y - firstBox.Max.Y) / firstVelocity.Y;
  else if(secondBox.Max.Y > firstBox.Min.Y && firstVelocity.Y > 0.0f)
    lastContact.Y = (secondBox.Max.Y - firstBox.Min.Y) / firstVelocity.Y;

  // Z axis
  if(secondBox.Max.Z < firstBox.Min.Z && firstVelocity.Z < 0.0f)
    firstContact.Z = (secondBox.Max.Z - firstBox.Min.Z) / firstVelocity.Z;
  else if(firstBox.Max.Z < secondBox.Min.Z && firstVelocity.Z > 0.0f)
    firstContact.Z = (secondBox.Min.Z - firstBox.Max.Z) / firstVelocity.Z;

  if(firstBox.Max.Z > secondBox.Min.Z && firstVelocity.Z < 0.0f)
    lastContact.Z = (secondBox.Min.Z - firstBox.Max.Z) / firstVelocity.Z;
  else if(secondBox.Max.Z > firstBox.Min.Z && firstVelocity.Z > 0.0f)
    lastContact.Z = (secondBox.Max.Z - firstBox.Min.Z) / firstVelocity.Z;

  // We now extract the exact time of the box' entry into the other box
  // as well as the time of exit (if any)
  float entry = Math.Max(
    firstContact.X, Math.Max(firstContact.Y, firstContact.Z)
  );
  float exit = Math.Min(
    lastContact.X, Math.Min(lastContact.Y, lastContact.Z)
  );

  if(entry > exit)
    return null;

  return entry;
}