]> git.lizzy.rs Git - irrlicht.git/blob - include/plane3d.h
Replace core::string implementation with std::basic_string
[irrlicht.git] / include / plane3d.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __IRR_PLANE_3D_H_INCLUDED__\r
6 #define __IRR_PLANE_3D_H_INCLUDED__\r
7 \r
8 #include "irrMath.h"\r
9 #include "vector3d.h"\r
10 \r
11 namespace irr\r
12 {\r
13 namespace core\r
14 {\r
15 \r
16 //! Enumeration for intersection relations of 3d objects\r
17 enum EIntersectionRelation3D\r
18 {\r
19         ISREL3D_FRONT = 0,\r
20         ISREL3D_BACK,\r
21         ISREL3D_PLANAR,\r
22         ISREL3D_SPANNING,\r
23         ISREL3D_CLIPPED\r
24 };\r
25 \r
26 //! Template plane class with some intersection testing methods.\r
27 /** It has to be ensured, that the normal is always normalized. The constructors\r
28     and setters of this class will not ensure this automatically. So any normal\r
29     passed in has to be normalized in advance. No change to the normal will be\r
30     made by any of the class methods.\r
31 */\r
32 template <class T>\r
33 class plane3d\r
34 {\r
35         public:\r
36 \r
37                 // Constructors\r
38 \r
39                 plane3d(): Normal(0,1,0) { recalculateD(vector3d<T>(0,0,0)); }\r
40 \r
41                 plane3d(const vector3d<T>& MPoint, const vector3d<T>& Normal) : Normal(Normal) { recalculateD(MPoint); }\r
42 \r
43                 plane3d(T px, T py, T pz, T nx, T ny, T nz) : Normal(nx, ny, nz) { recalculateD(vector3d<T>(px, py, pz)); }\r
44 \r
45                 plane3d(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3)\r
46                 { setPlane(point1, point2, point3); }\r
47 \r
48                 plane3d(const vector3d<T> & normal, const T d) : Normal(normal), D(d) { }\r
49 \r
50                 // operators\r
51 \r
52                 inline bool operator==(const plane3d<T>& other) const { return (equals(D, other.D) && Normal==other.Normal);}\r
53 \r
54                 inline bool operator!=(const plane3d<T>& other) const { return !(*this == other);}\r
55 \r
56                 // functions\r
57 \r
58                 void setPlane(const vector3d<T>& point, const vector3d<T>& nvector)\r
59                 {\r
60                         Normal = nvector;\r
61                         recalculateD(point);\r
62                 }\r
63 \r
64                 void setPlane(const vector3d<T>& nvect, T d)\r
65                 {\r
66                         Normal = nvect;\r
67                         D = d;\r
68                 }\r
69 \r
70                 void setPlane(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3)\r
71                 {\r
72                         // creates the plane from 3 memberpoints\r
73                         Normal = (point2 - point1).crossProduct(point3 - point1);\r
74                         Normal.normalize();\r
75 \r
76                         recalculateD(point1);\r
77                 }\r
78 \r
79 \r
80                 //! Get an intersection with a 3d line.\r
81                 /** \param lineVect Vector of the line to intersect with.\r
82                 \param linePoint Point of the line to intersect with.\r
83                 \param outIntersection Place to store the intersection point, if there is one.\r
84                 \return True if there was an intersection, false if there was not.\r
85                 */\r
86                 bool getIntersectionWithLine(const vector3d<T>& linePoint,\r
87                                 const vector3d<T>& lineVect,\r
88                                 vector3d<T>& outIntersection) const\r
89                 {\r
90                         T t2 = Normal.dotProduct(lineVect);\r
91 \r
92                         if (t2 == 0)\r
93                                 return false;\r
94 \r
95                         T t =- (Normal.dotProduct(linePoint) + D) / t2;\r
96                         outIntersection = linePoint + (lineVect * t);\r
97                         return true;\r
98                 }\r
99 \r
100                 //! Get percentage of line between two points where an intersection with this plane happens.\r
101                 /** Only useful if known that there is an intersection.\r
102                 \param linePoint1 Point1 of the line to intersect with.\r
103                 \param linePoint2 Point2 of the line to intersect with.\r
104                 \return Where on a line between two points an intersection with this plane happened.\r
105                 For example, 0.5 is returned if the intersection happened exactly in the middle of the two points.\r
106                 */\r
107                 f32 getKnownIntersectionWithLine(const vector3d<T>& linePoint1,\r
108                         const vector3d<T>& linePoint2) const\r
109                 {\r
110                         vector3d<T> vect = linePoint2 - linePoint1;\r
111                         T t2 = (f32)Normal.dotProduct(vect);\r
112                         return (f32)-((Normal.dotProduct(linePoint1) + D) / t2);\r
113                 }\r
114 \r
115                 //! Get an intersection with a 3d line, limited between two 3d points.\r
116                 /** \param linePoint1 Point 1 of the line.\r
117                 \param linePoint2 Point 2 of the line.\r
118                 \param outIntersection Place to store the intersection point, if there is one.\r
119                 \return True if there was an intersection, false if there was not.\r
120                 */\r
121                 bool getIntersectionWithLimitedLine(\r
122                                 const vector3d<T>& linePoint1,\r
123                                 const vector3d<T>& linePoint2,\r
124                                 vector3d<T>& outIntersection) const\r
125                 {\r
126                         return (getIntersectionWithLine(linePoint1, linePoint2 - linePoint1, outIntersection) &&\r
127                                         outIntersection.isBetweenPoints(linePoint1, linePoint2));\r
128                 }\r
129 \r
130                 //! Classifies the relation of a point to this plane.\r
131                 /** \param point Point to classify its relation.\r
132                 \return ISREL3D_FRONT if the point is in front of the plane,\r
133                 ISREL3D_BACK if the point is behind of the plane, and\r
134                 ISREL3D_PLANAR if the point is within the plane. */\r
135                 EIntersectionRelation3D classifyPointRelation(const vector3d<T>& point) const\r
136                 {\r
137                         const T d = Normal.dotProduct(point) + D;\r
138 \r
139                         if (d < -ROUNDING_ERROR_f32)\r
140                                 return ISREL3D_BACK;\r
141 \r
142                         if (d > ROUNDING_ERROR_f32)\r
143                                 return ISREL3D_FRONT;\r
144 \r
145                         return ISREL3D_PLANAR;\r
146                 }\r
147 \r
148                 //! Recalculates the distance from origin by applying a new member point to the plane.\r
149                 void recalculateD(const vector3d<T>& MPoint)\r
150                 {\r
151                         D = - MPoint.dotProduct(Normal);\r
152                 }\r
153 \r
154                 //! Gets a member point of the plane.\r
155                 vector3d<T> getMemberPoint() const\r
156                 {\r
157                         return Normal * -D;\r
158                 }\r
159 \r
160                 //! Tests if there is an intersection with the other plane\r
161                 /** \return True if there is a intersection. */\r
162                 bool existsIntersection(const plane3d<T>& other) const\r
163                 {\r
164                         vector3d<T> cross = other.Normal.crossProduct(Normal);\r
165                         return cross.getLength() > core::ROUNDING_ERROR_f32;\r
166                 }\r
167 \r
168                 //! Intersects this plane with another.\r
169                 /** \param other Other plane to intersect with.\r
170                 \param outLinePoint Base point of intersection line.\r
171                 \param outLineVect Vector of intersection.\r
172                 \return True if there is a intersection, false if not. */\r
173                 bool getIntersectionWithPlane(const plane3d<T>& other,\r
174                                 vector3d<T>& outLinePoint,\r
175                                 vector3d<T>& outLineVect) const\r
176                 {\r
177                         const T fn00 = Normal.getLength();\r
178                         const T fn01 = Normal.dotProduct(other.Normal);\r
179                         const T fn11 = other.Normal.getLength();\r
180                         const f64 det = fn00*fn11 - fn01*fn01;\r
181 \r
182                         if (fabs(det) < ROUNDING_ERROR_f64 )\r
183                                 return false;\r
184 \r
185                         const f64 invdet = 1.0 / det;\r
186                         const f64 fc0 = (fn11*-D + fn01*other.D) * invdet;\r
187                         const f64 fc1 = (fn00*-other.D + fn01*D) * invdet;\r
188 \r
189                         outLineVect = Normal.crossProduct(other.Normal);\r
190                         outLinePoint = Normal*(T)fc0 + other.Normal*(T)fc1;\r
191                         return true;\r
192                 }\r
193 \r
194                 //! Get the intersection point with two other planes if there is one.\r
195                 bool getIntersectionWithPlanes(const plane3d<T>& o1,\r
196                                 const plane3d<T>& o2, vector3d<T>& outPoint) const\r
197                 {\r
198                         vector3d<T> linePoint, lineVect;\r
199                         if (getIntersectionWithPlane(o1, linePoint, lineVect))\r
200                                 return o2.getIntersectionWithLine(linePoint, lineVect, outPoint);\r
201 \r
202                         return false;\r
203                 }\r
204 \r
205                 //! Test if the triangle would be front or backfacing from any point.\r
206                 /** Thus, this method assumes a camera position from\r
207                 which the triangle is definitely visible when looking into\r
208                 the given direction.\r
209                 Note that this only works if the normal is Normalized.\r
210                 Do not use this method with points as it will give wrong results!\r
211                 \param lookDirection: Look direction.\r
212                 \return True if the plane is front facing and\r
213                 false if it is backfacing. */\r
214                 bool isFrontFacing(const vector3d<T>& lookDirection) const\r
215                 {\r
216                         const f32 d = Normal.dotProduct(lookDirection);\r
217                         return F32_LOWER_EQUAL_0 ( d );\r
218                 }\r
219 \r
220                 //! Get the distance to a point.\r
221                 /** Note that this only works if the normal is normalized. */\r
222                 T getDistanceTo(const vector3d<T>& point) const\r
223                 {\r
224                         return point.dotProduct(Normal) + D;\r
225                 }\r
226 \r
227                 //! Normal vector of the plane.\r
228                 vector3d<T> Normal;\r
229 \r
230                 //! Distance from origin.\r
231                 T D;\r
232 };\r
233 \r
234 \r
235 //! Typedef for a f32 3d plane.\r
236 typedef plane3d<f32> plane3df;\r
237 \r
238 //! Typedef for an integer 3d plane.\r
239 typedef plane3d<s32> plane3di;\r
240 \r
241 } // end namespace core\r
242 } // end namespace irr\r
243 \r
244 #endif\r
245 \r