Plane 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSG_PLANE
  14. #define OSG_PLANE 1
  15. #include <osg/Config>
  16. #include <osg/Export>
  17. #include <osg/Vec3>
  18. #include <osg/Vec4>
  19. #include <osg/Matrix>
  20. #include <osg/BoundingSphere>
  21. #include <osg/BoundingBox>
  22. #include <vector>
  23. namespace osg {
  24. /** @brief A plane class. It can be used to represent an infinite plane.
  25. *
  26. * The infinite plane is described by an implicit plane equation a*x+b*y+c*z+d = 0. Though it is not mandatory that
  27. * a^2+b^2+c^2 = 1 is fulfilled in general some methods require it (@see osg::Plane::distance). */
  28. class OSG_EXPORT Plane
  29. {
  30. public:
  31. #ifdef OSG_USE_FLOAT_PLANE
  32. /** Type of Plane class.*/
  33. typedef float value_type;
  34. typedef Vec3f Vec3_type;
  35. typedef Vec4f Vec4_type;
  36. #else
  37. /** Type of Plane class.*/
  38. typedef double value_type;
  39. typedef Vec3d Vec3_type;
  40. typedef Vec4d Vec4_type;
  41. #endif
  42. /** Number of vector components. */
  43. enum { num_components = 3 };
  44. /// Default constructor
  45. /** The default constructor initializes all values to zero.
  46. * @warning Although the method osg::Plane::valid() will return true after the default constructors call the plane
  47. * is mathematically invalid! Default data do not describe a valid plane. */
  48. inline Plane() { _fv[0]=0.0; _fv[1]=0.0; _fv[2]=0.0; _fv[3]=0.0; _lowerBBCorner = 0; _upperBBCorner = 0; }
  49. inline Plane(const Plane& pl) { set(pl); }
  50. /// Constructor
  51. /** The plane is described as a*x+b*y+c*z+d = 0.
  52. * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed values are not normalized. */
  53. inline Plane(value_type a,value_type b,value_type c,value_type d) { set(a,b,c,d); }
  54. /// Constructor
  55. /** The plane can also be described as vec*[x,y,z,1].
  56. * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed values are not normalized. */
  57. inline Plane(const Vec4f& vec) { set(vec); }
  58. /// Constructor
  59. /** The plane can also be described as vec*[x,y,z,1].
  60. * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed values are not normalized. */
  61. inline Plane(const Vec4d& vec) { set(vec); }
  62. /// Constructor
  63. /** This constructor initializes the internal values directly without any checking or manipulation.
  64. * @param norm The normal of the plane.
  65. * @param d The negative distance from the point of origin to the plane.
  66. * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed normal was not normalized. */
  67. inline Plane(const Vec3_type& norm,value_type d) { set(norm,d); }
  68. /// Constructor
  69. /** This constructor calculates from the three points describing an infinite plane the internal values.
  70. * @param v1 Point in the plane.
  71. * @param v2 Point in the plane.
  72. * @param v3 Point in the plane.
  73. * @remark After this constructor call the plane's normal is normalized in case the three points described a mathematically
  74. * valid plane.
  75. * @remark The normal is determined by building the cross product of (v2-v1) ^ (v3-v2). */
  76. inline Plane(const Vec3_type& v1, const Vec3_type& v2, const Vec3_type& v3) { set(v1,v2,v3); }
  77. /// Constructor
  78. /** This constructor initializes the internal values directly without any checking or manipulation.
  79. * @param norm The normal of the plane.
  80. * @param point A point of the plane.
  81. * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed normal was not normalized. */
  82. inline Plane(const Vec3_type& norm, const Vec3_type& point) { set(norm,point); }
  83. inline Plane& operator = (const Plane& pl)
  84. {
  85. if (&pl==this) return *this;
  86. set(pl);
  87. return *this;
  88. }
  89. inline void set(const Plane& pl) { _fv[0]=pl._fv[0]; _fv[1]=pl._fv[1]; _fv[2]=pl._fv[2]; _fv[3]=pl._fv[3]; calculateUpperLowerBBCorners(); }
  90. inline void set(value_type a, value_type b, value_type c, value_type d) { _fv[0]=a; _fv[1]=b; _fv[2]=c; _fv[3]=d; calculateUpperLowerBBCorners(); }
  91. inline void set(const Vec4f& vec) { set(vec[0],vec[1],vec[2],vec[3]); }
  92. inline void set(const Vec4d& vec) { set(vec[0],vec[1],vec[2],vec[3]); }
  93. inline void set(const Vec3_type& norm, double d) { set(norm[0],norm[1],norm[2],d); }
  94. inline void set(const Vec3_type& v1, const Vec3_type& v2, const Vec3_type& v3)
  95. {
  96. Vec3_type norm = (v2-v1)^(v3-v2);
  97. value_type length = norm.length();
  98. if (length>1e-6) norm/= length;
  99. else norm.set(0.0,0.0,0.0);
  100. set(norm[0],norm[1],norm[2],-(v1*norm));
  101. }
  102. inline void set(const Vec3_type& norm, const Vec3_type& point)
  103. {
  104. value_type d = -norm[0]*point[0] - norm[1]*point[1] - norm[2]*point[2];
  105. set(norm[0],norm[1],norm[2],d);
  106. }
  107. /** flip/reverse the orientation of the plane.*/
  108. inline void flip()
  109. {
  110. _fv[0] = -_fv[0];
  111. _fv[1] = -_fv[1];
  112. _fv[2] = -_fv[2];
  113. _fv[3] = -_fv[3];
  114. calculateUpperLowerBBCorners();
  115. }
  116. /** This method multiplies the coefficients of the plane equation with a constant factor so that the
  117. * equation a^2+b^2+c^2 = 1 holds. */
  118. inline void makeUnitLength()
  119. {
  120. value_type inv_length = 1.0 / sqrt(_fv[0]*_fv[0] + _fv[1]*_fv[1]+ _fv[2]*_fv[2]);
  121. _fv[0] *= inv_length;
  122. _fv[1] *= inv_length;
  123. _fv[2] *= inv_length;
  124. _fv[3] *= inv_length;
  125. }
  126. /** calculate the upper and lower bounding box corners to be used
  127. * in the intersect(BoundingBox&) method for speeding calculations.*/
  128. inline void calculateUpperLowerBBCorners()
  129. {
  130. _upperBBCorner = (_fv[0]>=0.0?1:0) |
  131. (_fv[1]>=0.0?2:0) |
  132. (_fv[2]>=0.0?4:0);
  133. _lowerBBCorner = (~_upperBBCorner)&7;
  134. }
  135. /// Checks if all internal values describing the plane have valid numbers
  136. /** @warning This method does not check if the plane is mathematically correctly described!
  137. * @remark The only case where all elements have valid numbers and the plane description is invalid occurs if the plane's normal
  138. * is zero. */
  139. inline bool valid() const { return !isNaN(); }
  140. inline bool isNaN() const { return osg::isNaN(_fv[0]) || osg::isNaN(_fv[1]) || osg::isNaN(_fv[2]) || osg::isNaN(_fv[3]); }
  141. inline bool operator == (const Plane& plane) const { return _fv[0]==plane._fv[0] && _fv[1]==plane._fv[1] && _fv[2]==plane._fv[2] && _fv[3]==plane._fv[3]; }
  142. inline bool operator != (const Plane& plane) const { return _fv[0]!=plane._fv[0] || _fv[1]!=plane._fv[1] || _fv[2]!=plane._fv[2] || _fv[3]!=plane._fv[3]; }
  143. /** A plane is said to be smaller than another plane if the first non-identical element of the internal array is smaller than the
  144. * corresponding element of the other plane. */
  145. inline bool operator < (const Plane& plane) const
  146. {
  147. if (_fv[0]<plane._fv[0]) return true;
  148. else if (_fv[0]>plane._fv[0]) return false;
  149. else if (_fv[1]<plane._fv[1]) return true;
  150. else if (_fv[1]>plane._fv[1]) return false;
  151. else if (_fv[2]<plane._fv[2]) return true;
  152. else if (_fv[2]>plane._fv[2]) return false;
  153. else return (_fv[3]<plane._fv[3]);
  154. }
  155. inline value_type* ptr() { return _fv; }
  156. inline const value_type* ptr() const { return _fv; }
  157. inline Vec4_type asVec4() const { return Vec4_type(_fv[0],_fv[1],_fv[2],_fv[3]); }
  158. inline value_type& operator [] (unsigned int i) { return _fv[i]; }
  159. inline value_type operator [] (unsigned int i) const { return _fv[i]; }
  160. inline Vec3_type getNormal() const { return Vec3_type(_fv[0],_fv[1],_fv[2]); }
  161. /** Calculate the distance between a point and the plane.
  162. * @remark This method only leads to real distance values if the plane's norm is 1.
  163. * @sa osg::Plane::makeUnitLength */
  164. inline float distance(const osg::Vec3f& v) const
  165. {
  166. return _fv[0]*v.x()+
  167. _fv[1]*v.y()+
  168. _fv[2]*v.z()+
  169. _fv[3];
  170. }
  171. /** Calculate the distance between a point and the plane.
  172. * @remark This method only leads to real distance values if the plane's norm is 1.
  173. * @sa osg::Plane::makeUnitLength */
  174. inline double distance(const osg::Vec3d& v) const
  175. {
  176. return _fv[0]*v.x()+
  177. _fv[1]*v.y()+
  178. _fv[2]*v.z()+
  179. _fv[3];
  180. }
  181. /** calculate the dot product of the plane normal and a point.*/
  182. inline float dotProductNormal(const osg::Vec3f& v) const
  183. {
  184. return _fv[0]*v.x()+
  185. _fv[1]*v.y()+
  186. _fv[2]*v.z();
  187. }
  188. /** calculate the dot product of the plane normal and a point.*/
  189. inline double dotProductNormal(const osg::Vec3d& v) const
  190. {
  191. return _fv[0]*v.x()+
  192. _fv[1]*v.y()+
  193. _fv[2]*v.z();
  194. }
  195. /** intersection test between plane and vertex list
  196. return 1 if the bs is completely above plane,
  197. return 0 if the bs intersects the plane,
  198. return -1 if the bs is completely below the plane.*/
  199. inline int intersect(const std::vector<Vec3f>& vertices) const
  200. {
  201. if (vertices.empty()) return -1;
  202. int noAbove = 0;
  203. int noBelow = 0;
  204. int noOn = 0;
  205. for(std::vector<Vec3f>::const_iterator itr=vertices.begin();
  206. itr != vertices.end();
  207. ++itr)
  208. {
  209. float d = distance(*itr);
  210. if (d>0.0f) ++noAbove;
  211. else if (d<0.0f) ++noBelow;
  212. else ++noOn;
  213. }
  214. if (noAbove>0)
  215. {
  216. if (noBelow>0) return 0;
  217. else return 1;
  218. }
  219. return -1; // treat points on line as outside...
  220. }
  221. /** intersection test between plane and vertex list
  222. return 1 if the bs is completely above plane,
  223. return 0 if the bs intersects the plane,
  224. return -1 if the bs is completely below the plane.*/
  225. inline int intersect(const std::vector<Vec3d>& vertices) const
  226. {
  227. if (vertices.empty()) return -1;
  228. int noAbove = 0;
  229. int noBelow = 0;
  230. int noOn = 0;
  231. for(std::vector<Vec3d>::const_iterator itr=vertices.begin();
  232. itr != vertices.end();
  233. ++itr)
  234. {
  235. double d = distance(*itr);
  236. if (d>0.0) ++noAbove;
  237. else if (d<0.0) ++noBelow;
  238. else ++noOn;
  239. }
  240. if (noAbove>0)
  241. {
  242. if (noBelow>0) return 0;
  243. else return 1;
  244. }
  245. return -1; // treat points on line as outside...
  246. }
  247. /** intersection test between plane and bounding sphere.
  248. return 1 if the bs is completely above plane,
  249. return 0 if the bs intersects the plane,
  250. return -1 if the bs is completely below the plane.*/
  251. inline int intersect(const BoundingSphere& bs) const
  252. {
  253. float d = distance(bs.center());
  254. if (d>bs.radius()) return 1;
  255. else if (d<-bs.radius()) return -1;
  256. else return 0;
  257. }
  258. /** intersection test between plane and bounding sphere.
  259. return 1 if the bs is completely above plane,
  260. return 0 if the bs intersects the plane,
  261. return -1 if the bs is completely below the plane.*/
  262. inline int intersect(const BoundingBox& bb) const
  263. {
  264. // if lowest point above plane than all above.
  265. if (distance(bb.corner(_lowerBBCorner))>0.0f) return 1;
  266. // if highest point is below plane then all below.
  267. if (distance(bb.corner(_upperBBCorner))<0.0f) return -1;
  268. // d_lower<=0.0f && d_upper>=0.0f
  269. // therefore must be crossing plane.
  270. return 0;
  271. }
  272. /** Transform the plane by matrix. Note, this operation carries out
  273. * the calculation of the inverse of the matrix since a plane
  274. * must be multiplied by the inverse transposed to transform it. This
  275. * make this operation expensive. If the inverse has been already
  276. * calculated elsewhere then use transformProvidingInverse() instead.
  277. * See http://www.worldserver.com/turk/computergraphics/NormalTransformations.pdf*/
  278. inline void transform(const osg::Matrix& matrix)
  279. {
  280. osg::Matrix inverse;
  281. inverse.invert(matrix);
  282. transformProvidingInverse(inverse);
  283. }
  284. /** Transform the plane by providing a pre inverted matrix.
  285. * see transform for details. */
  286. inline void transformProvidingInverse(const osg::Matrix& matrix)
  287. {
  288. // note pre multiplications, which effectively transposes matrix.
  289. Vec4_type vec(_fv[0],_fv[1],_fv[2],_fv[3]);
  290. vec = matrix * vec;
  291. set(vec);
  292. makeUnitLength();
  293. }
  294. protected:
  295. /** Vec member variable. */
  296. value_type _fv[4];
  297. // variables cached to optimize calcs against bounding boxes.
  298. unsigned int _upperBBCorner;
  299. unsigned int _lowerBBCorner;
  300. };
  301. } // end of namespace
  302. #endif