00001
00002
00003
00004
00005 #ifndef __IRR_PLANE_3D_H_INCLUDED__
00006 #define __IRR_PLANE_3D_H_INCLUDED__
00007
00008 #include "irrMath.h"
00009 #include "vector3d.h"
00010
00011 namespace irr
00012 {
00013 namespace core
00014 {
00015
00017 enum EIntersectionRelation3D
00018 {
00019 ISREL3D_FRONT = 0,
00020 ISREL3D_BACK,
00021 ISREL3D_PLANAR,
00022 ISREL3D_SPANNING,
00023 ISREL3D_CLIPPED
00024 };
00025
00027
00032 template <class T>
00033 class plane3d
00034 {
00035 public:
00036
00037
00038
00039 plane3d(): Normal(0,1,0) { recalculateD(vector3d<T>(0,0,0)); }
00040
00041 plane3d(const vector3d<T>& MPoint, const vector3d<T>& Normal) : Normal(Normal) { recalculateD(MPoint); }
00042
00043 plane3d(T px, T py, T pz, T nx, T ny, T nz) : Normal(nx, ny, nz) { recalculateD(vector3d<T>(px, py, pz)); }
00044
00045 plane3d(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3)
00046 { setPlane(point1, point2, point3); }
00047
00048 plane3d(const vector3d<T> & normal, const T d) : Normal(normal), D(d) { }
00049
00050
00051
00052 inline bool operator==(const plane3d<T>& other) const { return (equals(D, other.D) && Normal==other.Normal);}
00053
00054 inline bool operator!=(const plane3d<T>& other) const { return !(*this == other);}
00055
00056
00057
00058 void setPlane(const vector3d<T>& point, const vector3d<T>& nvector)
00059 {
00060 Normal = nvector;
00061 recalculateD(point);
00062 }
00063
00064 void setPlane(const vector3d<T>& nvect, T d)
00065 {
00066 Normal = nvect;
00067 D = d;
00068 }
00069
00070 void setPlane(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3)
00071 {
00072
00073 Normal = (point2 - point1).crossProduct(point3 - point1);
00074 Normal.normalize();
00075
00076 recalculateD(point1);
00077 }
00078
00079
00081
00086 bool getIntersectionWithLine(const vector3d<T>& linePoint,
00087 const vector3d<T>& lineVect,
00088 vector3d<T>& outIntersection) const
00089 {
00090 T t2 = Normal.dotProduct(lineVect);
00091
00092 if (t2 == 0)
00093 return false;
00094
00095 T t =- (Normal.dotProduct(linePoint) + D) / t2;
00096 outIntersection = linePoint + (lineVect * t);
00097 return true;
00098 }
00099
00101
00107 f32 getKnownIntersectionWithLine(const vector3d<T>& linePoint1,
00108 const vector3d<T>& linePoint2) const
00109 {
00110 vector3d<T> vect = linePoint2 - linePoint1;
00111 T t2 = (f32)Normal.dotProduct(vect);
00112 return (f32)-((Normal.dotProduct(linePoint1) + D) / t2);
00113 }
00114
00116
00121 bool getIntersectionWithLimitedLine(
00122 const vector3d<T>& linePoint1,
00123 const vector3d<T>& linePoint2,
00124 vector3d<T>& outIntersection) const
00125 {
00126 return (getIntersectionWithLine(linePoint1, linePoint2 - linePoint1, outIntersection) &&
00127 outIntersection.isBetweenPoints(linePoint1, linePoint2));
00128 }
00129
00131
00135 EIntersectionRelation3D classifyPointRelation(const vector3d<T>& point) const
00136 {
00137 const T d = Normal.dotProduct(point) + D;
00138
00139 if (d < -ROUNDING_ERROR_f32)
00140 return ISREL3D_BACK;
00141
00142 if (d > ROUNDING_ERROR_f32)
00143 return ISREL3D_FRONT;
00144
00145 return ISREL3D_PLANAR;
00146 }
00147
00149 void recalculateD(const vector3d<T>& MPoint)
00150 {
00151 D = - MPoint.dotProduct(Normal);
00152 }
00153
00155 vector3d<T> getMemberPoint() const
00156 {
00157 return Normal * -D;
00158 }
00159
00161
00162 bool existsIntersection(const plane3d<T>& other) const
00163 {
00164 vector3d<T> cross = other.Normal.crossProduct(Normal);
00165 return cross.getLength() > core::ROUNDING_ERROR_f32;
00166 }
00167
00169
00173 bool getIntersectionWithPlane(const plane3d<T>& other,
00174 vector3d<T>& outLinePoint,
00175 vector3d<T>& outLineVect) const
00176 {
00177 const T fn00 = Normal.getLength();
00178 const T fn01 = Normal.dotProduct(other.Normal);
00179 const T fn11 = other.Normal.getLength();
00180 const f64 det = fn00*fn11 - fn01*fn01;
00181
00182 if (fabs(det) < ROUNDING_ERROR_f64 )
00183 return false;
00184
00185 const f64 invdet = 1.0 / det;
00186 const f64 fc0 = (fn11*-D + fn01*other.D) * invdet;
00187 const f64 fc1 = (fn00*-other.D + fn01*D) * invdet;
00188
00189 outLineVect = Normal.crossProduct(other.Normal);
00190 outLinePoint = Normal*(T)fc0 + other.Normal*(T)fc1;
00191 return true;
00192 }
00193
00195 bool getIntersectionWithPlanes(const plane3d<T>& o1,
00196 const plane3d<T>& o2, vector3d<T>& outPoint) const
00197 {
00198 vector3d<T> linePoint, lineVect;
00199 if (getIntersectionWithPlane(o1, linePoint, lineVect))
00200 return o2.getIntersectionWithLine(linePoint, lineVect, outPoint);
00201
00202 return false;
00203 }
00204
00206
00214 bool isFrontFacing(const vector3d<T>& lookDirection) const
00215 {
00216 const f32 d = Normal.dotProduct(lookDirection);
00217 return F32_LOWER_EQUAL_0 ( d );
00218 }
00219
00221
00222 T getDistanceTo(const vector3d<T>& point) const
00223 {
00224 return point.dotProduct(Normal) + D;
00225 }
00226
00228 vector3d<T> Normal;
00229
00231 T D;
00232 };
00233
00234
00236 typedef plane3d<f32> plane3df;
00237
00239 typedef plane3d<s32> plane3di;
00240
00241 }
00242 }
00243
00244 #endif
00245