aabb.h

Go to the documentation of this file.
00001 
00006 /*
00007  Copyright (C) 2001-2006, William Joseph.
00008  All Rights Reserved.
00009 
00010  This file is part of GtkRadiant.
00011 
00012  GtkRadiant is free software; you can redistribute it and/or modify
00013  it under the terms of the GNU General Public License as published by
00014  the Free Software Foundation; either version 2 of the License, or
00015  (at your option) any later version.
00016 
00017  GtkRadiant is distributed in the hope that it will be useful,
00018  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  GNU General Public License for more details.
00021 
00022  You should have received a copy of the GNU General Public License
00023  along with GtkRadiant; if not, write to the Free Software
00024  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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(); // Pythagorean length of extents vector
00079         }
00080 
00087         void includePoint (const Vector3& point)
00088         {
00089             // Process each axis separately
00090             for (int i = 0; i < 3; ++i) {
00091                 float axisDisp = point[i] - origin[i]; // axis displacement from origin to point
00092                 float halfDif = 0.5 * (std::abs(axisDisp) - extents[i]); // half of extent increase needed (maybe negative if point inside)
00093                 if (halfDif > 0) {
00094                     origin[i] += (axisDisp > 0) ? halfDif : -halfDif;
00095                     extents[i] += halfDif;
00096                 }
00097             }
00098         }
00099 
00100         // Expand this AABB to include another AABB
00101         void includeAABB (const AABB& other)
00102         {
00103             // Validity check. If both this and other are valid, use the extension
00104             // algorithm. If only the other AABB is valid, set this AABB equal to it.
00105             // If neither are valid we do nothing.
00106 
00107             if (isValid() && other.isValid()) {
00108                 // Extend each axis separately
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         // Check whether the AABB is valid, or if the extents are still uninitialised
00130         bool isValid() const {
00131 
00132             bool valid = true;
00133 
00134             // Check each origin and extents value. The origins must be between
00135             // +/- FLT_MAX, and the extents between 0 and FLT_MAX.
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; // partially inside
00265     } else if (distance_origin < 0) {
00266         return 2; // totally inside
00267     }
00268     return 0; // totally outside
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; // partially inside
00279     } else if (distance_origin < 0) {
00280         return 2; // totally inside
00281     }
00282     return 0; // totally outside
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

Generated by  doxygen 1.6.2