Determine Minimal AABB of OBB

in

Surprisingly, there seems to be no well-known clever algorithm for this. Some programmers did it by transforming all eight corners of the OBB into global coordinates and then finding the min and max coordinate on each axis by looping over the vertices.

My own approach tries to be a bit more intelligent and is at least twice as fast. How? Only calculate one half of the box corners and mirror the resulting AABB. The mirroring is very cheap since we know the OBB's center. Next we can, instead of taking the Min() and Max() of each axis, just do a Max() on the absolute value of each axis. The Abs() function just masks a single bit and actually executes in less than one clock cycle on modern CPUs.

Below code assumes your OBB has members named .Center (the center of the OBB), .Extents (how far away from the center the sides of the box are) and .Orientation, a 3x3 rotation matrix with an overloaded multiplication operator that transforms vectors by the matrix:

/// <summary>Calculates the smallest AABB that entirely encloses an OBB</summary>
/// <remarks>
///   This method was actually thought up by myself when all googling did not
///   reveal a clever way to avoid the expensive matrix-vector multiplications.
///   Feel free to use it in any way you see fit.
/// </remarks>
public static AABB GetBoundingBox(OBB box) {
  get {
    // We just calculate one half of the oriented box and obtain the other
    // by mirroring these points
    Vector3[] corners = new Vector3[] {
      new Vector3( box.Extents.X,  box.Extents.Y,  box.Extents.Z),
      new Vector3(-box.Extents.X,  box.Extents.Y,  box.Extents.Z),
      new Vector3( box.Extents.X, -box.Extents.Y,  box.Extents.Z),
      new Vector3( box.Extents.X,  box.Extents.Y, -box.Extents.Z)
    };

    // Transform all points and calculate the maximum distance on each
    // axis in positive direction by using its absolute value
    Vector3 aabbExtents = new Vector3();
    foreach(Vector3 corner in corners) {
      aabbExtents = Vector3.Max(
        aabbExtents, Vector3.Abs(Vector3.Transform(corner, box.Orientation))
      );
    }

    // Now we can just mirror the other direction
    return new AABB(box.Center - aabbExtents, box.Center + aabbExtents);
  }
}