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
1.5.6