/* * "Transforming Axis-Aligned Bounding Boxes", * by Jim Arvo, in "Graphics Gems", Academic Press, 1990. * * This function transforms a 3D axis-aligned box using a 3x3 * matrix and a translation vector. It returns the tightest * axis-aligned box that encloses the result. * * The utility of this algorithm is that it performs the box * transformation with far fewer flops than the naive approach * of transforming the eight vertices of the original box, * then computing upper and lower bounds of the transformed * points. By using all of the inherent symmetry of the boxes, * this algorithms is about four times as fast as the naive * algorithm. * * Note that computing axis-aligned boxes in this way is fast, * but NOT recommended. Whenever possible, the bounding box * should be computed from the transformed object, NOT the * transformed bounding box of the object. The latter approach * can produce very loose bounding boxes, which can hurt the * performance of ray tracers and other algorithms that make * use of bounding boxes. * */ #include "GraphicsGems.h" void Transform_Box( M, T, A, B ) Matrix3 M; /* Transform matrix. */ Vector3 T; /* Translation vector. */ Box3 A; /* The original bounding box. */ Box3 *B; /* The transformed bounding box. */ { float a, b; float Amin[3], Amax[3]; float Bmin[3], Bmax[3]; int i, j; /* Copy box A into a min array and a max array for easy reference. */ Amin[0] = A.min.x; Amax[0] = A.max.x; Amin[1] = A.min.y; Amax[1] = A.max.y; Amin[2] = A.min.z; Amax[2] = A.max.z; /* Account for the translation by beginning at T. */ Bmin[0] = Bmax[0] = T.x; Bmin[1] = Bmax[1] = T.y; Bmin[2] = Bmax[2] = T.z; /* Now find the extreme points by considering the product */ /* of the min and max with each component of M. */ for( i = 0; i < 3; i++ ) for( j = 0; j < 3; j++ ) { a = M.element[i][j] * Amin[j]; b = M.element[i][j] * Amax[j]; if( a < b ) { Bmin[i] += a; Bmax[i] += b; } else { Bmin[i] += b; Bmax[i] += a; } } /* Copy the result into the new box. */ B->min.x = Bmin[0]; B->max.x = Bmax[0]; B->min.y = Bmin[1]; B->max.y = Bmax[1]; B->min.z = Bmin[2]; B->max.z = Bmax[2]; }