00001 /* 00002 * Convex polyhedron header 00003 * 00004 * This file is part of the "SoftPixel Engine" (Copyright (c) 2008 by Lukas Hermanns) 00005 * See "SoftPixelEngine.hpp" for license information. 00006 */ 00007 00008 #ifndef __SP_CONVEXPOLYHEDRON_H__ 00009 #define __SP_CONVEXPOLYHEDRON_H__ 00010 00011 00012 #include "Base/spStandard.hpp" 00013 #include "Base/spDimensionMatrix4.hpp" 00014 #include "Base/spDimensionVector3D.hpp" 00015 #include "Base/spDimensionPlane3D.hpp" 00016 #include "Base/spDimensionAABB.hpp" 00017 00018 00019 namespace sp 00020 { 00021 namespace scene 00022 { 00023 00024 00029 template <typename T, s32 PlaneCount> class ConvexPolyhedron 00030 { 00031 00032 public: 00033 00034 ConvexPolyhedron() 00035 { 00036 } 00037 ConvexPolyhedron(const ConvexPolyhedron<T, PlaneCount> &Other) 00038 { 00039 for (s32 i = 0; i < PlaneCount; ++i) 00040 Planes_[i] = Other.Planes_[i]; 00041 } 00042 virtual ~ConvexPolyhedron() 00043 { 00044 } 00045 00046 /* === Functions === */ 00047 00049 bool isPointInside(const dim::vector3d<T> &Point, const T Radius = T(0)) const 00050 { 00051 for (s32 i = 0; i < PlaneCount; ++i) 00052 { 00053 if (Planes_[i].getPointDistance(Point) > Radius) 00054 return false; 00055 } 00056 return true; 00057 } 00058 00063 bool isBoundBoxInsideInv(const dim::aabbox3d<T> &Box, const dim::matrix4<T> &InvMatrix) const 00064 { 00065 for (s32 i = 0; i < PlaneCount; ++i) 00066 { 00067 if ((InvMatrix * Planes_[i]).getAABBoxRelation(Box) == dim::PLANE_RELATION_FRONT) 00068 return false; 00069 } 00070 return true; 00071 } 00072 00077 bool isBoundBoxInside(const dim::aabbox3d<T> &Box, const dim::matrix4<T> &Matrix) const 00078 { 00079 return isBoundBoxInsideInv(Box, Matrix.getInverse()); 00080 } 00081 00088 bool checkLineIntersection(const dim::line3d<T> &Line, dim::line3d<T> &Intersection) const 00089 { 00090 const dim::vector3d<T> Direction(Line.getDirection()); 00091 00092 T IntervalFirst = T(0); 00093 T IntervalLast = T(1); 00094 00095 /* Test line against each plane */ 00096 for (s32 i = 0; i < PlaneCount; ++i) 00097 { 00098 T Denom = Planes_[i].Normal.dot(Direction); 00099 T Dist = Planes_[i].Distance - Planes_[i].Normal.dot(Line.Start); 00100 00101 /* Check if line runs parallel to the plane */ 00102 if (Denom == T(0)) 00103 { 00104 if (Dist > T(0)) 00105 return false; 00106 } 00107 else 00108 { 00109 T t = Dist / Denom; 00110 00111 if (Denom < T(0)) 00112 { 00113 if (t > IntervalFirst) 00114 IntervalFirst = t; 00115 } 00116 else 00117 { 00118 if (t < IntervalLast) 00119 IntervalLast = t; 00120 } 00121 00122 /* Exit with no intersection if intersection becomes empty */ 00123 if (IntervalFirst > IntervalLast) 00124 return false; 00125 } 00126 } 00127 00128 /* Return the intersection */ 00129 Intersection.Start = Line.Start + Direction * IntervalFirst; 00130 Intersection.End = Line.Start + Direction * IntervalLast; 00131 00132 return true; 00133 } 00134 00136 void normalize() 00137 { 00138 for (s32 i = 0; i < PlaneCount; ++i) 00139 Planes_[i].normalize(); 00140 } 00141 00142 /* === Inline functions === */ 00143 00145 inline const dim::plane3d<T>& getPlane(u32 Index) const 00146 { 00147 return Planes_[Index]; 00148 } 00149 inline dim::plane3d<T>& getPlane(u32 Index) 00150 { 00151 return Planes_[Index]; 00152 } 00153 00154 inline void setPlane(u32 Index, const dim::plane3d<T> &Plane) 00155 { 00156 if (Index < PlaneCount) 00157 Planes_[Index] = Plane; 00158 } 00159 00160 protected: 00161 00162 /* === Members === */ 00163 00164 dim::plane3d<T> Planes_[PlaneCount]; 00165 00166 }; 00167 00168 00169 } // /namespace scene 00170 00171 } // /namespace sp 00172 00173 00174 #endif 00175 00176 00177 00178 // ================================================================================