Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __SP_DIMENSION_PLANE3D_H__
00009 #define __SP_DIMENSION_PLANE3D_H__
00010
00011
00012 #include "Base/spStandard.hpp"
00013 #include "Base/spDimensionVector3D.hpp"
00014 #include "Base/spDimensionTriangle3D.hpp"
00015 #include "Base/spDimensionQuadrangle3D.hpp"
00016 #include "Base/spDimensionAABB.hpp"
00017 #include "Base/spDimensionOBB.hpp"
00018 #include "Base/spMathCore.hpp"
00019
00020 #include <math.h>
00021
00022
00023 namespace sp
00024 {
00025 namespace dim
00026 {
00027
00028
00030 enum EPlaneAABBRelations
00031 {
00032 PLANE_RELATION_FRONT,
00033 PLANE_RELATION_BACK,
00034 PLANE_RELATION_CLIPPED,
00035 };
00036
00038 enum EPlanePointRelations
00039 {
00040 POINT_INFRONTOF_PLANE,
00041 POINT_BEHIND_PLANE,
00042 POINT_ON_PLANE,
00043 };
00044
00045
00046 template <typename T> class plane3d
00047 {
00048
00049 public:
00050
00051 plane3d() :
00052 Distance(0)
00053 {
00054 }
00055 plane3d(const vector3d<T> &PlaneNormal, const T Dist) :
00056 Normal (PlaneNormal),
00057 Distance(Dist )
00058 {
00059 }
00060 plane3d(const vector3d<T> &PointA, const vector3d<T> &PointB, const vector3d<T> &PointC) :
00061 Distance(0)
00062 {
00063 computePlane(PointA, PointB, PointC);
00064 }
00065 plane3d(const triangle3d<T> &Triangle) :
00066 Distance(0)
00067 {
00068 computePlane(Triangle.PointA, Triangle.PointB, Triangle.PointC);
00069 }
00070 plane3d(const quadrangle3d<T> &Quadrangle) :
00071 Distance(0)
00072 {
00073 computePlane(Quadrangle.PointA, Quadrangle.PointB, Quadrangle.PointC);
00074 }
00075 plane3d(const plane3d<T> &Other) :
00076 Normal (Other.Normal ),
00077 Distance(Other.Distance )
00078 {
00079 }
00080 ~plane3d()
00081 {
00082 }
00083
00084
00085
00086 inline void computePlane(
00087 const vector3d<T> &PointA, const vector3d<T> &PointB, const vector3d<T> &PointC)
00088 {
00089
00090 Normal = PointB;
00091 Normal -= PointA;
00092 Normal = Normal.cross(PointC - PointA);
00093 Normal.normalize();
00094
00095 Distance = Normal.dot(PointA);
00096 }
00097
00099 inline bool checkLineIntersection(
00100 const vector3d<T> &LineStart, const vector3d<T> &LineEnd, vector3d<T> &Intersection) const
00101 {
00102 vector3d<T> Direction(LineEnd);
00103 Direction -= LineStart;
00104
00105 const T t = (Distance - Normal.dot(LineStart)) / Normal.dot(Direction);
00106
00107 if (t >= T(0) && t <= T(1))
00108 {
00109
00110 Intersection = Direction;
00111 Intersection *= t;
00112 Intersection += LineStart;
00113 return true;
00114 }
00115
00116 return false;
00117 }
00118
00119 inline bool checkPlaneIntersection(
00120 const plane3d<T> &Other, vector3d<T> &Intersection, vector3d<T> &Direction) const
00121 {
00122
00123 Direction = Normal.cross(Other.Normal);
00124
00125
00126
00127
00128
00129 const T Denom = Direction.dot(Direction);
00130
00131 if (Denom < math::ROUNDING_ERROR)
00132 return false;
00133
00134
00135
00136 Intersection = Other.Normal;
00137 Intersection *= Distance;
00138 Intersection -= (Normal * Other.Distace);
00139 Intersection = Intersection.cross(Direction) / Denom;
00140
00141 return true;
00142 }
00143
00144 inline bool checkMultiplePlaneIntersection(
00145 const plane3d<T> &Plane1, const plane3d<T> &Plane2, vector3d<T> &Intersection) const
00146 {
00147 vector3d<T> u = Plane1.Normal.cross(Plane2.Normal);
00148 const T Denom = Normal.dot(u);
00149
00150
00151 if (math::Abs(Denom) < math::ROUNDING_ERROR)
00152 return false;
00153
00154
00155 Intersection = (u * Distance + Normal.cross(Plane1.Normal * Plane2.Distance - Plane2.Normal * Plane1.Distance)) / Denom;
00156
00157 return true;
00158 }
00159
00160 inline T getAABBoxDistance(const aabbox3d<T> &Box) const
00161 {
00162
00163 vector3d<T> c(Box.getCenter());
00164 vector3d<T> e(Box.Max - c);
00165
00166
00167 const T r = e.X * math::Abs(Normal.X) + e.Y * math::Abs(Normal.Y) + e.Z * math::Abs(Normal.Z);
00168
00169
00170 const T s = Normal.dot(c) - Distance;
00171
00172
00173 return math::Abs(s) - r;
00174 }
00175
00176 inline T getOBBoxDistance(const obbox3d<T> &Box) const
00177 {
00178
00179 const T r = (
00180 Box.HalfSize.X * math::Abs(Normal.dot(Box.Axis.X)) +
00181 Box.HalfSize.Y * math::Abs(Normal.dot(Box.Axis.Y)) +
00182 Box.HalfSize.Z * math::Abs(Normal.dot(Box.Axis.Z))
00183 );
00184
00185
00186 const T s = Normal.dot(Box.Center) - Distance;
00187
00188
00189 return math::Abs(s) - r;
00190 }
00191
00192 inline bool checkAABBoxIntersection(const aabbox3d<T> &Box) const
00193 {
00194 return getAABBoxDistance(Box) <= T(0);
00195 }
00196
00197 inline bool checkOBBoxIntersection(const obbox3d<T> &Box) const
00198 {
00199 return getOBBoxDistance(Box) <= T(0);
00200 }
00201
00202 inline EPlaneAABBRelations getAABBoxRelation(const aabbox3d<T> &Box) const
00203 {
00204 vector3d<T> NearPoint(Box.Max);
00205 vector3d<T> FarPoint(Box.Min);
00206
00207 if (Normal.X > T(0))
00208 {
00209 NearPoint.X = Box.Min.X;
00210 FarPoint.X = Box.Max.X;
00211 }
00212 if (Normal.Y > T(0))
00213 {
00214 NearPoint.Y = Box.Min.Y;
00215 FarPoint.Y = Box.Max.Y;
00216 }
00217 if (Normal.Z > T(0))
00218 {
00219 NearPoint.Z = Box.Min.Z;
00220 FarPoint.Z = Box.Max.Z;
00221 }
00222
00223 if (isPointFrontSide(NearPoint))
00224 return PLANE_RELATION_FRONT;
00225 if (isPointFrontSide(FarPoint))
00226 return PLANE_RELATION_CLIPPED;
00227
00228 return PLANE_RELATION_BACK;
00229 }
00230
00231 inline EPlanePointRelations getPointRelation(const vector3d<T> &Point) const
00232 {
00233 const T Dist = Normal.dot(Point) - Distance;
00234
00235 if (Dist > math::ROUNDING_ERROR)
00236 return POINT_INFRONTOF_PLANE;
00237 if (Dist < -math::ROUNDING_ERROR)
00238 return POINT_BEHIND_PLANE;
00239 return POINT_ON_PLANE;
00240 }
00241
00242 inline T getPointDistance(const vector3d<T> &Point) const
00243 {
00244 return (Normal.dot(Point) - Distance) / Normal.dot(Normal);
00245 }
00246
00248 inline vector3d<T> getClosestPoint(const vector3d<T> &Point) const
00249 {
00250 return Point - Normal * getPointDistance(Point);
00251 }
00252
00258 inline vector3d<T> getClosestPointNormalized(const vector3d<T> &Point) const
00259 {
00260 return Point - Normal * ( Normal.dot(Point) - Distance );
00261 }
00262
00264 inline vector3d<T> getMemberPoint() const
00265 {
00266 return Normal * Distance;
00267 }
00268
00270 inline bool isPointFrontSide(const vector3d<T> &Point) const
00271 {
00272 return getPointDistance(Point) >= 0;
00273 }
00274
00275 inline bool equal(const plane3d<T> &Other, f32 Precision = math::ROUNDING_ERROR) const
00276 {
00277 return
00278 Normal.equal(Other.Normal, Precision) &&
00279 (Distance + Precision > Other.Distance) &&
00280 (Distance - Precision < Other.Distance);
00281 }
00282
00283 inline plane3d<T>& swap()
00284 {
00285 Normal = -Normal;
00286 Distance = -Distance;
00287 return *this;
00288 }
00289
00290 inline plane3d<T>& normalize()
00291 {
00292 const T Len = 1.0f / Normal.getLength();
00293
00294 Normal *= Len;
00295 Distance *= Len;
00296
00297 return *this;
00298 }
00299
00300 template <typename B> inline vector3d<B> cast() const
00301 {
00302 return plane3d<B>(Normal.cast<B>(), static_cast<B>(Distance));
00303 }
00304
00305
00306
00307 vector3d<T> Normal;
00308 T Distance;
00309
00310 };
00311
00312 typedef plane3d<s32> plane3di;
00313 typedef plane3d<f32> plane3df;
00314
00315
00316 }
00317
00318 }
00319
00320
00321 #endif
00322
00323
00324
00325