00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if !defined(INCLUDED_MATH_AABB_H)
00028 #define INCLUDED_MATH_AABB_H
00029
00030 #include "math/matrix.h"
00031 #include "math/plane.h"
00032 #include <algorithm>
00033
00039 class AABB
00040 {
00041 public:
00043 Vector3 origin;
00044
00046 Vector3 extents;
00047
00050 AABB () :
00051 origin(0, 0, 0), extents(-1, -1, -1)
00052 {
00053 }
00054
00058 AABB (const Vector3& origin_, const Vector3& extents_) :
00059 origin(origin_), extents(extents_)
00060 {
00061 }
00062
00068 const Vector3& getOrigin () const
00069 {
00070 return origin;
00071 }
00072
00076 float getRadius () const
00077 {
00078 return extents.getLength();
00079 }
00080
00087 void includePoint (const Vector3& point)
00088 {
00089
00090 for (int i = 0; i < 3; ++i) {
00091 float axisDisp = point[i] - origin[i];
00092 float halfDif = 0.5 * (std::abs(axisDisp) - extents[i]);
00093 if (halfDif > 0) {
00094 origin[i] += (axisDisp > 0) ? halfDif : -halfDif;
00095 extents[i] += halfDif;
00096 }
00097 }
00098 }
00099
00100
00101 void includeAABB (const AABB& other)
00102 {
00103
00104
00105
00106
00107 if (isValid() && other.isValid()) {
00108
00109 for (int i = 0; i < 3; ++i) {
00110 float displacement = other.origin[i] - origin[i];
00111 float difference = other.extents[i] - extents[i];
00112 if (fabs(displacement) > fabs(difference)) {
00113 float half_difference = static_cast<float> (0.5 * (fabs(displacement) + difference));
00114 if (half_difference > 0.0f) {
00115 origin[i] += (displacement >= 0.0f) ? half_difference : -half_difference;
00116 extents[i] += half_difference;
00117 }
00118 } else if (difference > 0.0f) {
00119 origin[i] = other.origin[i];
00120 extents[i] = other.extents[i];
00121 }
00122 }
00123 } else if (other.isValid()) {
00124 origin = other.origin;
00125 extents = other.extents;
00126 }
00127 }
00128
00129
00130 bool isValid() const {
00131
00132 bool valid = true;
00133
00134
00135
00136 for (int i = 0; i < 3; ++i) {
00137 if (origin[i] < -FLT_MAX
00138 || origin[i] > FLT_MAX
00139 || extents[i] < 0
00140 || extents[i] > FLT_MAX)
00141 {
00142 valid = false;
00143 }
00144 }
00145
00146 return valid;
00147 }
00148 };
00149
00150 const float c_aabb_max = FLT_MAX;
00151
00152 inline bool extents_valid (float f)
00153 {
00154 return f >= 0.0f && f <= c_aabb_max;
00155 }
00156
00157 inline bool origin_valid (float f)
00158 {
00159 return f >= -c_aabb_max && f <= c_aabb_max;
00160 }
00161
00162 inline bool aabb_valid (const AABB& aabb)
00163 {
00164 return origin_valid(aabb.origin[0]) && origin_valid(aabb.origin[1]) && origin_valid(aabb.origin[2])
00165 && extents_valid(aabb.extents[0]) && extents_valid(aabb.extents[1]) && extents_valid(aabb.extents[2]);
00166 }
00167
00168 inline AABB aabb_for_minmax (const Vector3& min, const Vector3& max)
00169 {
00170 AABB aabb;
00171 aabb.origin = vector3_mid(min, max);
00172 aabb.extents = max - aabb.origin;
00173 return aabb;
00174 }
00175
00176 template<typename Index>
00177 class AABBExtend
00178 {
00179 public:
00180 static void apply (AABB& aabb, const AABB& other)
00181 {
00182 float displacement = other.origin[Index::VALUE] - aabb.origin[Index::VALUE];
00183 float difference = other.extents[Index::VALUE] - aabb.extents[Index::VALUE];
00184 if (fabs(displacement) > fabs(difference)) {
00185 float half_difference = static_cast<float> (0.5 * (fabs(displacement) + difference));
00186 if (half_difference > 0.0f) {
00187 aabb.origin[Index::VALUE] += (displacement >= 0.0f) ? half_difference : -half_difference;
00188 aabb.extents[Index::VALUE] += half_difference;
00189 }
00190 } else if (difference > 0.0f) {
00191 aabb.origin[Index::VALUE] = other.origin[Index::VALUE];
00192 aabb.extents[Index::VALUE] = other.extents[Index::VALUE];
00193 }
00194 }
00195 };
00196
00197 inline void aabb_extend_by_point_safe (AABB& aabb, const Vector3& point)
00198 {
00199 if (aabb_valid(aabb)) {
00200 aabb.includePoint(point);
00201 } else {
00202 aabb.origin = point;
00203 aabb.extents = Vector3(0, 0, 0);
00204 }
00205 }
00206
00207 class AABBExtendByPoint
00208 {
00209 AABB& m_aabb;
00210 public:
00211 AABBExtendByPoint (AABB& aabb) :
00212 m_aabb(aabb)
00213 {
00214 }
00215 void operator() (const Vector3& point) const
00216 {
00217 aabb_extend_by_point_safe(m_aabb, point);
00218 }
00219 };
00220
00221 inline void aabb_extend_by_aabb (AABB& aabb, const AABB& other)
00222 {
00223 AABBExtend<IntegralConstant<0> >::apply(aabb, other);
00224 AABBExtend<IntegralConstant<1> >::apply(aabb, other);
00225 AABBExtend<IntegralConstant<2> >::apply(aabb, other);
00226 }
00227
00228 inline void aabb_extend_by_vec3 (AABB& aabb, const Vector3& extension)
00229 {
00230 aabb.extents += extension;
00231 }
00232
00233 template<typename Index>
00234 inline bool aabb_intersects_point_dimension (const AABB& aabb, const Vector3& point)
00235 {
00236 return fabs(point[Index::VALUE] - aabb.origin[Index::VALUE]) < aabb.extents[Index::VALUE];
00237 }
00238
00239 inline bool aabb_intersects_point (const AABB& aabb, const Vector3& point)
00240 {
00241 return aabb_intersects_point_dimension<IntegralConstant<0> > (aabb, point) && aabb_intersects_point_dimension<
00242 IntegralConstant<1> > (aabb, point) && aabb_intersects_point_dimension<IntegralConstant<2> > (aabb, point);
00243 }
00244
00245 template<typename Index>
00246 inline bool aabb_intersects_aabb_dimension (const AABB& aabb, const AABB& other)
00247 {
00248 return fabs(other.origin[Index::VALUE] - aabb.origin[Index::VALUE]) < (aabb.extents[Index::VALUE]
00249 + other.extents[Index::VALUE]);
00250 }
00251
00252 inline bool aabb_intersects_aabb (const AABB& aabb, const AABB& other)
00253 {
00254 return aabb_intersects_aabb_dimension<IntegralConstant<0> > (aabb, other) && aabb_intersects_aabb_dimension<
00255 IntegralConstant<1> > (aabb, other) && aabb_intersects_aabb_dimension<IntegralConstant<2> > (aabb, other);
00256 }
00257
00258 inline unsigned int aabb_classify_plane (const AABB& aabb, const Plane3& plane)
00259 {
00260 double distance_origin = plane.normal().dot(aabb.origin) + plane.dist();
00261
00262 if (fabs(distance_origin) < (fabs(plane.a * aabb.extents[0]) + fabs(plane.b * aabb.extents[1]) + fabs(plane.c
00263 * aabb.extents[2]))) {
00264 return 1;
00265 } else if (distance_origin < 0) {
00266 return 2;
00267 }
00268 return 0;
00269 }
00270
00271 inline unsigned int aabb_oriented_classify_plane (const AABB& aabb, const Matrix4& transform, const Plane3& plane)
00272 {
00273 double distance_origin = plane.normal().dot(aabb.origin) + plane.dist();
00274
00275 if (fabs(distance_origin) < (fabs(aabb.extents[0] * plane.normal().dot(transform.x().getVector3())) + fabs(
00276 aabb.extents[1] * plane.normal().dot(transform.y().getVector3())) + fabs(aabb.extents[2]
00277 * plane.normal().dot(transform.z().getVector3())))) {
00278 return 1;
00279 } else if (distance_origin < 0) {
00280 return 2;
00281 }
00282 return 0;
00283 }
00284
00285 inline void aabb_corners (const AABB& aabb, Vector3 corners[8])
00286 {
00287 Vector3 min(aabb.origin - aabb.extents);
00288 Vector3 max(aabb.origin + aabb.extents);
00289 corners[0] = Vector3(min[0], max[1], max[2]);
00290 corners[1] = Vector3(max[0], max[1], max[2]);
00291 corners[2] = Vector3(max[0], min[1], max[2]);
00292 corners[3] = Vector3(min[0], min[1], max[2]);
00293 corners[4] = Vector3(min[0], max[1], min[2]);
00294 corners[5] = Vector3(max[0], max[1], min[2]);
00295 corners[6] = Vector3(max[0], min[1], min[2]);
00296 corners[7] = Vector3(min[0], min[1], min[2]);
00297 }
00298
00299 inline void aabb_corners_oriented (const AABB& aabb, const Matrix4& rotation, Vector3 corners[8])
00300 {
00301 Vector3 x = rotation.x().getVector3() * aabb.extents.x();
00302 Vector3 y = rotation.y().getVector3() * aabb.extents.y();
00303 Vector3 z = rotation.z().getVector3() * aabb.extents.z();
00304
00305 corners[0] = aabb.origin + -x + y + z;
00306 corners[1] = aabb.origin + x + y + z;
00307 corners[2] = aabb.origin + x + -y + z;
00308 corners[3] = aabb.origin + -x + -y + z;
00309 corners[4] = aabb.origin + -x + y + -z;
00310 corners[5] = aabb.origin + x + y + -z;
00311 corners[6] = aabb.origin + x + -y + -z;
00312 corners[7] = aabb.origin + -x + -y + -z;
00313 }
00314
00315 inline void aabb_planes (const AABB& aabb, Plane3 planes[6])
00316 {
00317 planes[0] = Plane3(g_vector3_axes[0], aabb.origin[0] + aabb.extents[0]);
00318 planes[1] = Plane3(-g_vector3_axes[0], -(aabb.origin[0] - aabb.extents[0]));
00319 planes[2] = Plane3(g_vector3_axes[1], aabb.origin[1] + aabb.extents[1]);
00320 planes[3] = Plane3(-g_vector3_axes[1], -(aabb.origin[1] - aabb.extents[1]));
00321 planes[4] = Plane3(g_vector3_axes[2], aabb.origin[2] + aabb.extents[2]);
00322 planes[5] = Plane3(-g_vector3_axes[2], -(aabb.origin[2] - aabb.extents[2]));
00323 }
00324
00325 inline void aabb_planes_oriented (const AABB& aabb, const Matrix4& rotation, Plane3 planes[6])
00326 {
00327 double x = rotation.x().getVector3().dot(aabb.origin);
00328 double y = rotation.y().getVector3().dot(aabb.origin);
00329 double z = rotation.z().getVector3().dot(aabb.origin);
00330
00331 planes[0] = Plane3(rotation.x().getVector3(), x + aabb.extents[0]);
00332 planes[1] = Plane3(-rotation.x().getVector3(), -(x - aabb.extents[0]));
00333 planes[2] = Plane3(rotation.y().getVector3(), y + aabb.extents[1]);
00334 planes[3] = Plane3(-rotation.y().getVector3(), -(y - aabb.extents[1]));
00335 planes[4] = Plane3(rotation.z().getVector3(), z + aabb.extents[2]);
00336 planes[5] = Plane3(-rotation.z().getVector3(), -(z - aabb.extents[2]));
00337 }
00338
00339 const Vector3 aabb_normals[6] = { Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1), Vector3(-1, 0, 0), Vector3(0,
00340 -1, 0), Vector3(0, 0, -1), };
00341
00342 const float aabb_texcoord_topleft[2] = { 0, 0 };
00343 const float aabb_texcoord_topright[2] = { 1, 0 };
00344 const float aabb_texcoord_botleft[2] = { 0, 1 };
00345 const float aabb_texcoord_botright[2] = { 1, 1 };
00346
00347 inline AABB aabb_for_oriented_aabb (const AABB& aabb, const Matrix4& transform)
00348 {
00349 return AABB(matrix4_transformed_point(transform, aabb.origin), Vector3(static_cast<float> (fabs(transform[0]
00350 * aabb.extents[0]) + fabs(transform[4] * aabb.extents[1]) + fabs(transform[8] * aabb.extents[2])),
00351 static_cast<float> (fabs(transform[1] * aabb.extents[0]) + fabs(transform[5] * aabb.extents[1]) + fabs(
00352 transform[9] * aabb.extents[2])), static_cast<float> (fabs(transform[2] * aabb.extents[0]) + fabs(
00353 transform[6] * aabb.extents[1]) + fabs(transform[10] * aabb.extents[2]))));
00354 }
00355
00356 inline AABB aabb_for_oriented_aabb_safe (const AABB& aabb, const Matrix4& transform)
00357 {
00358 if (aabb_valid(aabb)) {
00359 return aabb_for_oriented_aabb(aabb, transform);
00360 }
00361 return aabb;
00362 }
00363
00364 inline AABB aabb_infinite ()
00365 {
00366 return AABB(Vector3(0, 0, 0), Vector3(c_aabb_max, c_aabb_max, c_aabb_max));
00367 }
00368
00369 #endif