plane3d.h 7.7 KB

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