Axis aligned bounding boxes are quite often used in computer graphics, for example for fast collision detection. Often, you need to transform a given axis aligned bounding box by some matrix and then convert it into an axis aligned bounding box in the resulting coordinate space again. Here’s an efficient algorithm to do so:
public static BoundingBox transformBoundingBox(BoundingBox boundingBox, Matrix m) { var xa = m.Right * boundingBox.Min.X; var xb = m.Right * boundingBox.Max.X; var ya = m.Up * boundingBox.Min.Y; var yb = m.Up * boundingBox.Max.Y; var za = m.Backward * boundingBox.Min.Z; var zb = m.Backward * boundingBox.Max.Z; return new BoundingBox( Vector3.Min(xa, xb) + Vector3.Min(ya, yb) + Vector3.Min(za, zb) + m.Translation, Vector3.Max(xa, xb) + Vector3.Max(ya, yb) + Vector3.Max(za, zb) + m.Translation );
Note that Matrix.Right
returns the Matrix’s first column vector, i.e. and
Matrix.Up
and Matrix.Backward
return the second and third column vectors respectively. So looking at the source code above, all you have to do is multiply the bounding box min and max values in each coordinate direction by the corresponding Matrix column vector and then combine them to generate the result. Why does this work?
Let’s think about the definition of an axis aligned bounding box: It can be described by a center position and offsets for each coordinate axis
. We can then write the box’s delimiting positions as follows:
Note the and
operators are applied for each dimension independently. Since each dimension’s offset
is added and subtracted independently from the other dimensions as well the
,
operators go over
corner positions. So, lets transform the positions by some matrix
and then convert the resulting corners into an axis aligned bounding box
again by finding the minimum and maximum values in each coordinate direction:
In my previous post Rant: Matrix Layouts I pointed out that we can split up matrix vector products into a sum over the product of the vector’s components with individual matrix columns. Let’s try this here, just for the vector
of
first:
Note how something magic happened here: each component of and
appears only once in the resulting equation and we only have two possible values for each component! Now we just need to split up the
operator:
and we are done: We successfully decomposed the minimum over all eight bounding box coordinates into a component-wise minimum and a sum over all dimensions. Obviously, the same procedure holds for the maximum bounding box extent as well. Have another look at the code above again: It performs the very computation mentioned just before.
Nice, but if you say: min ( M ( c \in R^4 ) ) this means min considers the w component which is invalid. I was a little confused by this.
thx, really helped!
Thanks Buddy, that was helpful.