Irrlicht 3D Engine
plane3d.h
Go to the documentation of this file.
00001 // Copyright (C) 2002-2012 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