AABB.inl

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file:   AABB.inl
00003    @author: Travis Clayton Fischer
00004    @acct:   tfischer
00005    @date:   Tue Sep 30 20:35:43 2008
00006 <!-------------------------------------------------------------------->**/
00007 
00008 #ifndef AABB_INL_
00009 #define AABB_INL_
00010 
00011 #include <core/Ray.h>
00012 
00013 /**
00014  * Ray-box intersection using IEEE numerical properties to ensure that the
00015  * test is both robust and efficient, as described in:
00016  *
00017  *      Amy Williams, Steve Barrus, R. Keith Morley, and Peter Shirley
00018  *      "An Efficient and Robust Ray-Box Intersection Algorithm"
00019  *      Journal of graphics tools, 10(1):49-54, 2005
00020  * 
00021  * Modified slightly by for the purposes of this program
00022  */
00023 inline bool AABB::intersects(const Ray &ray, real_t &tMin, real_t &tMax) const {
00024    const Vector3 bounds[2] = { min, max };
00025    const bool xSign = (ray.invDir[0] < 0);
00026    const bool ySign = (ray.invDir[1] < 0);
00027    
00028    tMin  = (bounds[xSign ][0] - ray.origin[0]) * ray.invDir[0];
00029    tMax  = (bounds[!xSign][0] - ray.origin[0]) * ray.invDir[0];
00030    const real_t tyMin = (bounds[ySign ][1] - ray.origin[1]) * ray.invDir[1];
00031    const real_t tyMax = (bounds[!ySign][1] - ray.origin[1]) * ray.invDir[1];
00032    
00033    if ((tMin > tyMax) || (tyMin > tMax))
00034       return false;
00035    
00036    if (tyMin > tMin)
00037       tMin = tyMin;
00038    if (tyMax < tMax)
00039       tMax = tyMax;
00040    
00041    const bool zSign   = (ray.invDir[2] < 0);
00042    const real_t tzMin = (bounds[zSign ][2] - ray.origin[2]) * ray.invDir[2];
00043    const real_t tzMax = (bounds[!zSign][2] - ray.origin[2]) * ray.invDir[2];
00044    
00045    if ((tMin > tzMax) || (tzMin > tMax))
00046       return false;
00047    
00048    if (tzMin > tMin)
00049       tMin = tzMin;
00050    if (tzMax < tMax)
00051       tMax = tzMax;
00052    
00053    return (tMin <= tMax);
00054 }
00055 
00056 inline void AABB::add(const Vector3 &v) {
00057    min = Vector3::min(min, v);
00058    max = Vector3::max(max, v);
00059 }
00060 
00061 inline void AABB::add(const Point3 &p) {
00062    add(Vector3(p.data));
00063 }
00064 
00065 inline void AABB::add(const AABB &aabb) {
00066    if (aabb.min != aabb.max) {
00067       min = Vector3::min(min, aabb.min);
00068       max = Vector3::max(max, aabb.max);
00069    }
00070 }
00071 
00072 inline bool AABB::intersects(const AABB &aabb) const {
00073    const Vector3 &min2 = aabb.min, &max2 = aabb.max;
00074    
00075    return (max[0] >= min2[0] && min[0] <= max2[0] && 
00076            max[1] >= min2[1] && min[1] <= max2[1] &&
00077            max[2] >= min2[2] && min[2] <= max2[2]);
00078 }
00079 
00080 inline bool AABB::contains(const Point3 &p) const {
00081    return (max[0] >= p[0] && min[0] <= p[0] && 
00082            max[1] >= p[1] && min[1] <= p[1] &&
00083            max[2] >= p[2] && min[2] <= p[2]);
00084 }
00085 
00086 inline Vector3 AABB::getDiagonal() const {
00087    return (max - min);
00088 }
00089 
00090 inline Point3 AABB::getCenter() const {
00091    return Point3() + (min + max) / 2.0;
00092 }
00093 
00094 inline unsigned AABB::getMaxExtent() const {
00095    const Vector3 &diag = max - min;
00096    
00097    return (diag[0] > diag[1]) ? 
00098       2 * (diag[2] > diag[0]) : 
00099       1 + (diag[2] > diag[1]);
00100 }
00101 
00102 inline unsigned AABB::getMinExtent() const {
00103    const Vector3 &diag = max - min;
00104    
00105    return (diag[0] < diag[1]) ? 
00106       2 * (diag[2] < diag[0]) : 
00107       1 + (diag[2] < diag[1]);
00108 }
00109 
00110 inline real_t AABB::getSurfaceArea() const {
00111    const Vector3 &diag = max - min;
00112    
00113    return 2 * (diag[0] * diag[1] + 
00114                diag[1] * diag[2] + 
00115                diag[2] * diag[0]);
00116 }
00117 
00118 inline void AABB::getMinMaxSurfaceArea(const unsigned axis, 
00119                                        const real_t pos, 
00120                                        real_t &leftArea, 
00121                                        real_t &rightArea) const
00122 {
00123    Vector3 diag = max - min;
00124    
00125    diag[axis]   = pos - min[axis];
00126    leftArea     = 2 * (diag[0] * diag[1] + 
00127                        diag[1] * diag[2] + 
00128                        diag[2] * diag[0]);
00129    
00130    diag[axis]   = max[axis] - pos;
00131    rightArea    = 2 * (diag[0] * diag[1] + 
00132                        diag[1] * diag[2] + 
00133                        diag[2] * diag[0]);
00134 }
00135 
00136 inline AABB AABB::getTransformed(const Matrix4x4 &trans) const {
00137    const Vector3 &p0 = 
00138       Vector3((trans * Point3(min[0], min[1], min[2])).data);
00139    const Vector3 &p1 = 
00140       Vector3((trans * Point3(max[0], min[1], min[2])).data);
00141    const Vector3 &p2 = 
00142       Vector3((trans * Point3(min[0], max[1], min[2])).data);
00143    const Vector3 &p3 = 
00144       Vector3((trans * Point3(max[0], max[1], min[2])).data);
00145    const Vector3 &p4 = 
00146       Vector3((trans * Point3(min[0], min[1], max[2])).data);
00147    const Vector3 &p5 = 
00148       Vector3((trans * Point3(max[0], min[1], max[2])).data);
00149    const Vector3 &p6 = 
00150       Vector3((trans * Point3(min[0], max[1], max[2])).data);
00151    const Vector3 &p7 = 
00152       Vector3((trans * Point3(max[0], max[1], max[2])).data);
00153    
00154    AABB transformed;
00155    
00156    transformed.add(p0);
00157    transformed.add(p1);
00158    transformed.add(p2);
00159    transformed.add(p3);
00160    transformed.add(p4);
00161    transformed.add(p5);
00162    transformed.add(p6);
00163    transformed.add(p7);
00164    
00165    return transformed;
00166 }
00167 
00168 inline bool AABB::isValid() const {
00169    return (min[0] <= max[0] && min[1] <= max[1] && min[2] <= max[2]);
00170 }
00171 
00172 inline bool AABB::isPoint() const {
00173    return (min[0] == max[0] && min[1] == max[1] && min[2] == max[2]);
00174 }
00175 
00176 inline std::ostream &operator<<(std::ostream &os, const AABB &aabb) {
00177    os << "{ min = " << aabb.min 
00178       << ", max = " << aabb.max 
00179       << ", mid = " << aabb.getCenter() 
00180       << " }";
00181    
00182    return os;
00183 }
00184 
00185 #endif // AABB_INL_
00186 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6