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 template <class T>
00028 class plane3d
00029 {
00030 public:
00031
00032
00033
00034 plane3d(): Normal(0,1,0) { recalculateD(vector3d<T>(0,0,0)); }
00035
00036 plane3d(const vector3d<T>& MPoint, const vector3d<T>& Normal) : Normal(Normal) { recalculateD(MPoint); }
00037
00038 plane3d(T px, T py, T pz, T nx, T ny, T nz) : Normal(nx, ny, nz) { recalculateD(vector3d<T>(px, py, pz)); }
00039
00040 plane3d(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3)
00041 { setPlane(point1, point2, point3); }
00042
00043 plane3d(const vector3d<T> & normal, const T d) : Normal(normal), D(d) { }
00044
00045
00046
00047 inline bool operator==(const plane3d<T>& other) const { return (equals(D, other.D) && Normal==other.Normal);}
00048
00049 inline bool operator!=(const plane3d<T>& other) const { return !(*this == other);}
00050
00051
00052
00053 void setPlane(const vector3d<T>& point, const vector3d<T>& nvector)
00054 {
00055 Normal = nvector;
00056 recalculateD(point);
00057 }
00058
00059 void setPlane(const vector3d<T>& nvect, T d)
00060 {
00061 Normal = nvect;
00062 D = d;
00063 }
00064
00065 void setPlane(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3)
00066 {
00067
00068 Normal = (point2 - point1).crossProduct(point3 - point1);
00069 Normal.normalize();
00070
00071 recalculateD(point1);
00072 }
00073
00074
00076
00081 bool getIntersectionWithLine(const vector3d<T>& linePoint,
00082 const vector3d<T>& lineVect,
00083 vector3d<T>& outIntersection) const
00084 {
00085 T t2 = Normal.dotProduct(lineVect);
00086
00087 if (t2 == 0)
00088 return false;
00089
00090 T t =- (Normal.dotProduct(linePoint) + D) / t2;
00091 outIntersection = linePoint + (lineVect * t);
00092 return true;
00093 }
00094
00096
00102 f32 getKnownIntersectionWithLine(const vector3d<T>& linePoint1,
00103 const vector3d<T>& linePoint2) const
00104 {
00105 vector3d<T> vect = linePoint2 - linePoint1;
00106 T t2 = (f32)Normal.dotProduct(vect);
00107 return (f32)-((Normal.dotProduct(linePoint1) + D) / t2);
00108 }
00109
00111
00116 bool getIntersectionWithLimitedLine(
00117 const vector3d<T>& linePoint1,
00118 const vector3d<T>& linePoint2,
00119 vector3d<T>& outIntersection) const
00120 {
00121 return (getIntersectionWithLine(linePoint1, linePoint2 - linePoint1, outIntersection) &&
00122 outIntersection.isBetweenPoints(linePoint1, linePoint2));
00123 }
00124
00126
00130 EIntersectionRelation3D classifyPointRelation(const vector3d<T>& point) const
00131 {
00132 const T d = Normal.dotProduct(point) + D;
00133
00134 if (d < -ROUNDING_ERROR_f32)
00135 return ISREL3D_BACK;
00136
00137 if (d > ROUNDING_ERROR_f32)
00138 return ISREL3D_FRONT;
00139
00140 return ISREL3D_PLANAR;
00141 }
00142
00144 void recalculateD(const vector3d<T>& MPoint)
00145 {
00146 D = - MPoint.dotProduct(Normal);
00147 }
00148
00150 vector3d<T> getMemberPoint() const
00151 {
00152 return Normal * -D;
00153 }
00154
00156
00157 bool existsIntersection(const plane3d<T>& other) const
00158 {
00159 vector3d<T> cross = other.Normal.crossProduct(Normal);
00160 return cross.getLength() > core::ROUNDING_ERROR_f32;
00161 }
00162
00164
00168 bool getIntersectionWithPlane(const plane3d<T>& other,
00169 vector3d<T>& outLinePoint,
00170 vector3d<T>& outLineVect) const
00171 {
00172 const T fn00 = Normal.getLength();
00173 const T fn01 = Normal.dotProduct(other.Normal);
00174 const T fn11 = other.Normal.getLength();
00175 const f64 det = fn00*fn11 - fn01*fn01;
00176
00177 if (fabs(det) < ROUNDING_ERROR_f64 )
00178 return false;
00179
00180 const f64 invdet = 1.0 / det;
00181 const f64 fc0 = (fn11*-D + fn01*other.D) * invdet;
00182 const f64 fc1 = (fn00*-other.D + fn01*D) * invdet;
00183
00184 outLineVect = Normal.crossProduct(other.Normal);
00185 outLinePoint = Normal*(T)fc0 + other.Normal*(T)fc1;
00186 return true;
00187 }
00188
00190 bool getIntersectionWithPlanes(const plane3d<T>& o1,
00191 const plane3d<T>& o2, vector3d<T>& outPoint) const
00192 {
00193 vector3d<T> linePoint, lineVect;
00194 if (getIntersectionWithPlane(o1, linePoint, lineVect))
00195 return o2.getIntersectionWithLine(linePoint, lineVect, outPoint);
00196
00197 return false;
00198 }
00199
00201
00209 bool isFrontFacing(const vector3d<T>& lookDirection) const
00210 {
00211 const f32 d = Normal.dotProduct(lookDirection);
00212 return F32_LOWER_EQUAL_0 ( d );
00213 }
00214
00216
00217 T getDistanceTo(const vector3d<T>& point) const
00218 {
00219 return point.dotProduct(Normal) + D;
00220 }
00221
00223 vector3d<T> Normal;
00224
00226 T D;
00227 };
00228
00229
00231 typedef plane3d<f32> plane3df;
00232
00234 typedef plane3d<s32> plane3di;
00235
00236 }
00237 }
00238
00239 #endif
00240