|
IrrlichtEngine
|
00001 // Copyright (C) 2002-2011 Nikolaus Gebhardt 00002 // This file is part of the "Irrlicht Engine". 00003 // For conditions of distribution and use, see copyright notice in irrlicht.h 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 // Constructors 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 // operators 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 // functions 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 // creates the plane from 3 memberpoints 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 } // end namespace core 00242 } // end namespace irr 00243 00244 #endif 00245