mPlane.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _MPLANE_H_
  23. #define _MPLANE_H_
  24. #ifndef _MPOINT3_H_
  25. #include "math/mPoint3.h"
  26. #endif
  27. #ifndef _MBOX_H_
  28. #include "math/mBox.h"
  29. #endif
  30. #ifndef _MORIENTEDBOX_H_
  31. #include "math/mOrientedBox.h"
  32. #endif
  33. #ifndef _MSPHERE_H_
  34. #include "math/mSphere.h"
  35. #endif
  36. /// A 3D plane defined by a normal and a distance along the normal.
  37. ///
  38. /// @note The distance is stored negative.
  39. class PlaneF : public Point3F
  40. {
  41. public:
  42. /// *NEGATIVE* distance along the xyz normal.
  43. F32 d;
  44. /// Return the plane's normal.
  45. const Point3F& getNormal() const { return *this; }
  46. /// Return the plane's position.
  47. Point3F getPosition() const { return Point3F( x, y, z ) * -d; }
  48. bool isHorizontal() const;
  49. bool isVertical() const;
  50. bool isParallelTo( const PlaneF& plane, F32 epsilon = POINT_EPSILON ) const;
  51. bool isPerpendicularTo( const PlaneF& plane, F32 epsilon = POINT_EPSILON ) const;
  52. /// @name Initialization
  53. /// @{
  54. PlaneF() {}
  55. PlaneF( const Point3F& p, const Point3F& n );
  56. /// NOTE: d is the NEGATIVE distance along the xyz normal.
  57. PlaneF( F32 _x, F32 _y, F32 _z, F32 _d);
  58. PlaneF( const Point3F& j, const Point3F& k, const Point3F& l );
  59. void set( F32 _x, F32 _y, F32 _z );
  60. /// NOTE: d is the NEGATIVE distance along the xyz normal.
  61. void set( F32 _x, F32 _y, F32 _z, F32 _d );
  62. void set( const Point3F& p, const Point3F& n);
  63. void set( const Point3F& k, const Point3F& j, const Point3F& l );
  64. void setPoint(const Point3F &p); // assumes the x,y,z fields are already set
  65. // creates an un-normalized plane
  66. void setXY(F32 zz);
  67. void setYZ(F32 xx);
  68. void setXZ(F32 yy);
  69. void setXY(const Point3F& P, F32 dir);
  70. void setYZ(const Point3F& P, F32 dir);
  71. void setXZ(const Point3F& P, F32 dir);
  72. /// @}
  73. void shiftX(F32 xx);
  74. void shiftY(F32 yy);
  75. void shiftZ(F32 zz);
  76. void invert();
  77. void neg();
  78. /// Return the distance of the given point from the plane.
  79. F32 distToPlane( const Point3F& cp ) const;
  80. /// Project the given point onto the plane.
  81. Point3F project(const Point3F &pt) const;
  82. /// @name Intersection
  83. /// @{
  84. enum Side
  85. {
  86. Front = 1,
  87. On = 0,
  88. Back = -1
  89. };
  90. /// Compute on which side of the plane the given point lies.
  91. Side whichSide( const Point3F& cp ) const;
  92. /// Compute which side the given sphere lies on.
  93. Side whichSide( const SphereF& sphere ) const;
  94. /// Compute which side the given AABB lies on.
  95. Side whichSide( const Box3F& aabb ) const;
  96. /// Compute which side the given OBB lies on.
  97. Side whichSide( const OrientedBox3F& obb ) const;
  98. /// Compute which side the given box lies on.
  99. ///
  100. /// @param center Center point.
  101. /// @param axisx X-Axis vector. Length is box half-extent along X.
  102. /// @param axisy Y-Axis vector. Length is box half-extent along Y.
  103. /// @param axisz Z-Axis vector. Length is box half-extent along Z.
  104. ///
  105. /// @return Side that the given box is on.
  106. Side whichSideBox( const Point3F& center,
  107. const Point3F& axisx,
  108. const Point3F& axisy,
  109. const Point3F& axisz ) const;
  110. /// @}
  111. /// @name Intersection
  112. /// @{
  113. /// Compute the distance at which the ray traveling from @a start in the direction
  114. /// of @end intersects the plane
  115. /// @param start Starting point of the ray.
  116. /// @param end Point in the direction of which the ray travels from @a start.
  117. /// @return The distance (as a fraction/multiple of the length of the vector between
  118. /// @a start and @a end) at which the ray intersects the plane or PARALLEL_PLANE if the
  119. /// ray is parallel to the plane.
  120. F32 intersect( const Point3F &start, const Point3F &end ) const;
  121. /// Compute the intersection of the ray that emanates at @a start in the direction
  122. /// @dir.
  123. /// @param start Point where the ray emanates.
  124. /// @param dir Direction in which the ray travels. Must be normalized.
  125. /// @param outHit Resulting intersection point. Only set if there indeed is a hit.
  126. /// @return True if the ray intersects the plane or false if not.
  127. bool intersect( const Point3F &start, const Point3F &dir, Point3F *outHit ) const;
  128. /// Compute the intersection between two planes.
  129. ///
  130. /// @param plane Plane to intersect with.
  131. /// @param outLineOrigin Used to store the origin of the resulting intersection line.
  132. /// @param outLineDirection Used to store the direction of the resulting intersection line.
  133. ///
  134. /// @return True if there is an intersection or false if the two planes are coplanar.
  135. bool intersect( const PlaneF& plane, Point3F& outLineOrigin, Point3F& outLineDirection ) const;
  136. /// @}
  137. /// @name Clipping
  138. /// @{
  139. /// Clip a convex polygon by the plane.
  140. ///
  141. /// The resulting polygon will be the input polygon minus the part on the negative side
  142. /// of the plane. The input polygon must be convex and @a inVertices must be in CCW or CW order.
  143. ///
  144. /// @param inVertices Array holding the vertices of the input polygon.
  145. /// @param inNumVertices Number of vertices in @a inVertices.
  146. /// @param outVertices Array to hold the vertices of the clipped polygon. Must have space for one additional
  147. /// vertex in case the polygon is split by the plane such that an additional vertex appears. Must not
  148. /// be the same as @a inVertices.
  149. /// @return Number of vertices in the clipped polygon, i.e. number of vertices in @a outVertices.
  150. ///
  151. /// @note Be aware that if the polygon fully lies on the negative side of the plane,
  152. /// the resulting @a outNumVertices will be zero, i.e. no polygon will result from the clip.
  153. U32 clipPolygon( const Point3F* inVertices, U32 inNumVertices, Point3F* outVertices ) const;
  154. /// Clip a line segment by the plane.
  155. ///
  156. /// @param start Start point of the line segment.
  157. /// @param end End point of the line segment.
  158. /// @param outNewEnd New end point if there is an intersection with the plane.
  159. ///
  160. /// @return True
  161. bool clipSegment( const Point3F& start, const Point3F& end, Point3F& outNewEnd ) const;
  162. /// @}
  163. };
  164. #define PARALLEL_PLANE 1e20f
  165. #define PlaneSwitchCode(s, e) (s * 3 + e)
  166. //---------------------------------------------------------------------------
  167. inline PlaneF::PlaneF( F32 _x, F32 _y, F32 _z, F32 _d )
  168. {
  169. set( _x, _y, _z, _d );
  170. }
  171. //-----------------------------------------------------------------------------
  172. inline PlaneF::PlaneF( const Point3F& p, const Point3F& n )
  173. {
  174. set(p,n);
  175. }
  176. //-----------------------------------------------------------------------------
  177. inline PlaneF::PlaneF( const Point3F& j, const Point3F& k, const Point3F& l )
  178. {
  179. set(j,k,l);
  180. }
  181. //-----------------------------------------------------------------------------
  182. inline void PlaneF::setXY( F32 zz )
  183. {
  184. x = y = 0.0f; z = 1.0f; d = -zz;
  185. }
  186. //-----------------------------------------------------------------------------
  187. inline void PlaneF::setYZ( F32 xx )
  188. {
  189. x = 1.0f; z = y = 0.0f; d = -xx;
  190. }
  191. //-----------------------------------------------------------------------------
  192. inline void PlaneF::setXZ( F32 yy )
  193. {
  194. x = z = 0.0f; y = 1.0f; d = -yy;
  195. }
  196. //-----------------------------------------------------------------------------
  197. inline void PlaneF::setXY(const Point3F& point, F32 dir) // Normal = (0, 0, -1|1)
  198. {
  199. x = y = 0.0f;
  200. d = -((z = dir) * point.z);
  201. }
  202. //-----------------------------------------------------------------------------
  203. inline void PlaneF::setYZ(const Point3F& point, F32 dir) // Normal = (-1|1, 0, 0)
  204. {
  205. z = y = 0.0f;
  206. d = -((x = dir) * point.x);
  207. }
  208. //-----------------------------------------------------------------------------
  209. inline void PlaneF::setXZ(const Point3F& point, F32 dir) // Normal = (0, -1|1, 0)
  210. {
  211. x = z = 0.0f;
  212. d = -((y = dir) * point.y);
  213. }
  214. //-----------------------------------------------------------------------------
  215. inline void PlaneF::shiftX( F32 xx )
  216. {
  217. d -= xx * x;
  218. }
  219. //-----------------------------------------------------------------------------
  220. inline void PlaneF::shiftY( F32 yy )
  221. {
  222. d -= yy * y;
  223. }
  224. //-----------------------------------------------------------------------------
  225. inline void PlaneF::shiftZ( F32 zz )
  226. {
  227. d -= zz * z;
  228. }
  229. //-----------------------------------------------------------------------------
  230. inline bool PlaneF::isHorizontal() const
  231. {
  232. return (x == 0.0f && y == 0.0f) ? true : false;
  233. }
  234. //-----------------------------------------------------------------------------
  235. inline bool PlaneF::isVertical() const
  236. {
  237. return ((x != 0.0f || y != 0.0f) && z == 0.0f) ? true : false;
  238. }
  239. //-----------------------------------------------------------------------------
  240. inline Point3F PlaneF::project(const Point3F &pt) const
  241. {
  242. F32 dist = distToPlane(pt);
  243. return Point3F(pt.x - x * dist, pt.y - y * dist, pt.z - z * dist);
  244. }
  245. //-----------------------------------------------------------------------------
  246. inline F32 PlaneF::distToPlane( const Point3F& cp ) const
  247. {
  248. // return mDot(*this,cp) + d;
  249. return (x * cp.x + y * cp.y + z * cp.z) + d;
  250. }
  251. //-----------------------------------------------------------------------------
  252. inline PlaneF::Side PlaneF::whichSide(const Point3F& cp) const
  253. {
  254. F32 dist = distToPlane(cp);
  255. if (dist >= 0.005f) // if (mFabs(dist) < 0.005f)
  256. return Front; // return On;
  257. else if (dist <= -0.005f) // else if (dist > 0.0f)
  258. return Back; // return Front;
  259. else // else
  260. return On; // return Back;
  261. }
  262. //-----------------------------------------------------------------------------
  263. inline PlaneF::Side PlaneF::whichSide( const SphereF& sphere ) const
  264. {
  265. const F32 dist = distToPlane( sphere.center );
  266. if( dist > sphere.radius )
  267. return Front;
  268. else if( dist < - sphere.radius )
  269. return Back;
  270. else
  271. return On;
  272. }
  273. //-----------------------------------------------------------------------------
  274. inline PlaneF::Side PlaneF::whichSide( const Box3F& aabb ) const
  275. {
  276. // See Graphics Gems IV, 1.7 and "A Faster Overlap Test for a Plane and a Bounding Box"
  277. // (http://replay.waybackmachine.org/19981203032829/http://www.cs.unc.edu/~hoff/research/vfculler/boxplane.html)
  278. // for details.
  279. Point3F pVertex;
  280. Point3F nVertex;
  281. pVertex.x = ( x > 0.0f ) ? aabb.maxExtents.x : aabb.minExtents.x;
  282. pVertex.y = ( y > 0.0f ) ? aabb.maxExtents.y : aabb.minExtents.y;
  283. pVertex.z = ( z > 0.0f ) ? aabb.maxExtents.z : aabb.minExtents.z;
  284. if( whichSide( pVertex ) == Back )
  285. return Back;
  286. nVertex.x = ( x > 0.0f ) ? aabb.minExtents.x : aabb.maxExtents.x;
  287. nVertex.y = ( y > 0.0f ) ? aabb.minExtents.y : aabb.maxExtents.y;
  288. nVertex.z = ( z > 0.0f ) ? aabb.minExtents.z : aabb.maxExtents.z;
  289. if( whichSide( nVertex ) == Front )
  290. return Front;
  291. return On;
  292. }
  293. //-----------------------------------------------------------------------------
  294. inline PlaneF::Side PlaneF::whichSide( const OrientedBox3F& obb ) const
  295. {
  296. // Project the box onto the line defined by the plane center and normal.
  297. // See "3D Game Engine Design" chapter 4.3.2.
  298. const F32 r = obb.getHalfExtents().x * mFabs( mDot( obb.getAxis( 0 ), *this ) ) +
  299. obb.getHalfExtents().y * mFabs( mDot( obb.getAxis( 1 ), *this ) ) +
  300. obb.getHalfExtents().z * mFabs( mDot( obb.getAxis( 2 ), *this ) );
  301. const F32 dist = distToPlane( obb.getCenter() );
  302. if( dist > r )
  303. return Front;
  304. else if( dist < - r )
  305. return Back;
  306. else
  307. return On;
  308. }
  309. //-----------------------------------------------------------------------------
  310. inline PlaneF::Side PlaneF::whichSideBox(const Point3F& center,
  311. const Point3F& axisx,
  312. const Point3F& axisy,
  313. const Point3F& axisz) const
  314. {
  315. F32 baseDist = distToPlane(center);
  316. F32 compDist = mFabs(mDot(axisx, *this)) +
  317. mFabs(mDot(axisy, *this)) +
  318. mFabs(mDot(axisz, *this));
  319. if (baseDist >= compDist)
  320. return Front;
  321. else if (baseDist <= -compDist)
  322. return Back;
  323. else
  324. return On;
  325. }
  326. inline void PlaneF::set( F32 _x, F32 _y, F32 _z )
  327. {
  328. Point3F::set(_x,_y,_z);
  329. }
  330. inline void PlaneF::set( F32 _x, F32 _y, F32 _z, F32 _d )
  331. {
  332. Point3F::set(_x,_y,_z);
  333. d = _d;
  334. }
  335. //---------------------------------------------------------------------------
  336. /// Calculate the coefficients of the plane passing through
  337. /// a point with the given normal.
  338. inline void PlaneF::setPoint(const Point3F &p)
  339. {
  340. d = -(p.x * x + p.y * y + p.z * z);
  341. }
  342. inline void PlaneF::set( const Point3F& p, const Point3F& n )
  343. {
  344. x = n.x; y = n.y; z = n.z;
  345. normalize();
  346. // Calculate the last plane coefficient.
  347. d = -(p.x * x + p.y * y + p.z * z);
  348. }
  349. //---------------------------------------------------------------------------
  350. // Calculate the coefficients of the plane passing through
  351. // three points. Basically it calculates the normal to the three
  352. // points then calculates a plane through the middle point with that
  353. // normal.
  354. inline void PlaneF::set( const Point3F& k, const Point3F& j, const Point3F& l )
  355. {
  356. // Point3F kj, lj, pv;
  357. // kj = k - j;
  358. // lj = l - j;
  359. // mCross( kj, lj, &pv );
  360. // set(j, pv);
  361. // Inline for speed...
  362. const F32 ax = k.x-j.x;
  363. const F32 ay = k.y-j.y;
  364. const F32 az = k.z-j.z;
  365. const F32 bx = l.x-j.x;
  366. const F32 by = l.y-j.y;
  367. const F32 bz = l.z-j.z;
  368. x = ay*bz - az*by;
  369. y = az*bx - ax*bz;
  370. z = ax*by - ay*bx;
  371. m_point3F_normalize( (F32 *)(&x) );
  372. d = -(j.x * x + j.y * y + j.z * z);
  373. }
  374. inline void PlaneF::invert()
  375. {
  376. x = -x;
  377. y = -y;
  378. z = -z;
  379. d = -d;
  380. }
  381. inline void PlaneF::neg()
  382. {
  383. invert();
  384. }
  385. inline F32 PlaneF::intersect(const Point3F &p1, const Point3F &p2) const
  386. {
  387. const F32 den = mDot(p2 - p1, *this);
  388. if( mIsZero( den ) )
  389. return PARALLEL_PLANE;
  390. return -distToPlane(p1) / den;
  391. }
  392. inline bool PlaneF::intersect( const Point3F &start, const Point3F &dir, Point3F *outHit ) const
  393. {
  394. const F32 den = mDot( dir, *this );
  395. if ( mIsZero( den ) )
  396. return false;
  397. F32 dist = -distToPlane( start ) / den;
  398. *outHit = start + dir * dist;
  399. return true;
  400. }
  401. class PlaneD: public Point3D
  402. {
  403. public:
  404. /// NOTE: d is the NEGATIVE distance along the xyz normal.
  405. F64 d;
  406. PlaneD();
  407. PlaneD( const PlaneF& copy);
  408. PlaneD( const Point3D& p, const Point3D& n );
  409. /// NOTE: d is the NEGATIVE distance along the xyz normal.
  410. PlaneD( F64 _x, F64 _y, F64 _z, F64 _d);
  411. PlaneD( const Point3D& j, const Point3D& k, const Point3D& l );
  412. // Methods
  413. //using Point3D::set;
  414. void set(const F64 _x, const F64 _y, const F64 _z);
  415. void set( const Point3D& p, const Point3D& n);
  416. void set( const Point3D& k, const Point3D& j, const Point3D& l );
  417. void setPoint(const Point3D &p); // assumes the x,y,z fields are already set
  418. // creates an un-normalized plane
  419. void setXY(F64 zz);
  420. void setYZ(F64 xx);
  421. void setXZ(F64 yy);
  422. void setXY(const Point3D& P, F64 dir);
  423. void setYZ(const Point3D& P, F64 dir);
  424. void setXZ(const Point3D& P, F64 dir);
  425. void shiftX(F64 xx);
  426. void shiftY(F64 yy);
  427. void shiftZ(F64 zz);
  428. void invert();
  429. void neg();
  430. Point3D project(const Point3D &pt) const; // projects the point onto the plane.
  431. F64 distToPlane( const Point3D& cp ) const;
  432. enum Side {
  433. Front = 1,
  434. On = 0,
  435. Back = -1
  436. };
  437. Side whichSide(const Point3D& cp) const;
  438. F64 intersect(const Point3D &start, const Point3D &end) const;
  439. //DLLAPI bool split( const Poly3F& poly, Poly3F* front, Poly3F* back );
  440. bool isHorizontal() const;
  441. bool isVertical() const;
  442. Side whichSideBox(const Point3D& center,
  443. const Point3D& axisx,
  444. const Point3D& axisy,
  445. const Point3D& axisz) const;
  446. };
  447. //#define PARALLEL_PLANE 1e20f
  448. //#define PlaneSwitchCode(s, e) (s * 3 + e)
  449. //---------------------------------------------------------------------------
  450. inline PlaneD::PlaneD()
  451. {
  452. }
  453. inline PlaneD::
  454. PlaneD( F64 _x, F64 _y, F64 _z, F64 _d )
  455. {
  456. x = _x; y = _y; z = _z; d = _d;
  457. }
  458. inline PlaneD::PlaneD( const PlaneF& copy)
  459. {
  460. x = copy.x; y = copy.y; z = copy.z; d = copy.d;
  461. }
  462. inline PlaneD::PlaneD( const Point3D& p, const Point3D& n )
  463. {
  464. set(p,n);
  465. }
  466. inline PlaneD::PlaneD( const Point3D& j, const Point3D& k, const Point3D& l )
  467. {
  468. set(j,k,l);
  469. }
  470. inline void PlaneD::setXY( F64 zz )
  471. {
  472. x = y = 0; z = 1; d = -zz;
  473. }
  474. inline void PlaneD::setYZ( F64 xx )
  475. {
  476. x = 1; z = y = 0; d = -xx;
  477. }
  478. inline void PlaneD::setXZ( F64 yy )
  479. {
  480. x = z = 0; y = 1; d = -yy;
  481. }
  482. inline void PlaneD::setXY(const Point3D& point, F64 dir) // Normal = (0, 0, -1|1)
  483. {
  484. x = y = 0;
  485. d = -((z = dir) * point.z);
  486. }
  487. inline void PlaneD::setYZ(const Point3D& point, F64 dir) // Normal = (-1|1, 0, 0)
  488. {
  489. z = y = 0;
  490. d = -((x = dir) * point.x);
  491. }
  492. inline void PlaneD::setXZ(const Point3D& point, F64 dir) // Normal = (0, -1|1, 0)
  493. {
  494. x = z = 0;
  495. d = -((y = dir) * point.y);
  496. }
  497. inline void PlaneD::shiftX( F64 xx )
  498. {
  499. d -= xx * x;
  500. }
  501. inline void PlaneD::shiftY( F64 yy )
  502. {
  503. d -= yy * y;
  504. }
  505. inline void PlaneD::shiftZ( F64 zz )
  506. {
  507. d -= zz * z;
  508. }
  509. inline bool PlaneD::isHorizontal() const
  510. {
  511. return (x == 0 && y == 0) ? true : false;
  512. }
  513. inline bool PlaneD::isVertical() const
  514. {
  515. return ((x != 0 || y != 0) && z == 0) ? true : false;
  516. }
  517. inline Point3D PlaneD::project(const Point3D &pt) const
  518. {
  519. F64 dist = distToPlane(pt);
  520. return Point3D(pt.x - x * dist, pt.y - y * dist, pt.z - z * dist);
  521. }
  522. inline F64 PlaneD::distToPlane( const Point3D& cp ) const
  523. {
  524. // return mDot(*this,cp) + d;
  525. return (x * cp.x + y * cp.y + z * cp.z) + d;
  526. }
  527. inline PlaneD::Side PlaneD::whichSide(const Point3D& cp) const
  528. {
  529. F64 dist = distToPlane(cp);
  530. if (dist >= 0.005f) // if (mFabs(dist) < 0.005f)
  531. return Front; // return On;
  532. else if (dist <= -0.005f) // else if (dist > 0.0f)
  533. return Back; // return Front;
  534. else // else
  535. return On; // return Back;
  536. }
  537. inline void PlaneD::set(const F64 _x, const F64 _y, const F64 _z)
  538. {
  539. Point3D::set(_x,_y,_z);
  540. }
  541. //---------------------------------------------------------------------------
  542. // Calculate the coefficients of the plane passing through
  543. // a point with the given normal.
  544. ////inline void PlaneD::set( const Point3D& p, const Point3D& n )
  545. inline void PlaneD::setPoint(const Point3D &p)
  546. {
  547. d = -(p.x * x + p.y * y + p.z * z);
  548. }
  549. inline void PlaneD::set( const Point3D& p, const Point3D& n )
  550. {
  551. x = n.x; y = n.y; z = n.z;
  552. normalize();
  553. // Calculate the last plane coefficient.
  554. d = -(p.x * x + p.y * y + p.z * z);
  555. }
  556. //---------------------------------------------------------------------------
  557. // Calculate the coefficients of the plane passing through
  558. // three points. Basically it calculates the normal to the three
  559. // points then calculates a plane through the middle point with that
  560. // normal.
  561. inline void PlaneD::set( const Point3D& k, const Point3D& j, const Point3D& l )
  562. {
  563. // Point3D kj,lj,pv;
  564. // kj = k;
  565. // kj -= j;
  566. // lj = l;
  567. // lj -= j;
  568. // mCross( kj, lj, &pv );
  569. // set(j,pv);
  570. // Above ends up making function calls up the %*#...
  571. // This is called often enough to be a little more direct
  572. // about it (sqrt should become intrinsic in the future)...
  573. F64 ax = k.x-j.x;
  574. F64 ay = k.y-j.y;
  575. F64 az = k.z-j.z;
  576. F64 bx = l.x-j.x;
  577. F64 by = l.y-j.y;
  578. F64 bz = l.z-j.z;
  579. x = ay*bz - az*by;
  580. y = az*bx - ax*bz;
  581. z = ax*by - ay*bx;
  582. F64 squared = x*x + y*y + z*z;
  583. AssertFatal(squared != 0.0, "Error, no plane possible!");
  584. // In non-debug mode
  585. if (squared != 0)
  586. {
  587. F64 invSqrt = 1.0 / (F64)mSqrt(x*x + y*y + z*z);
  588. x *= invSqrt;
  589. y *= invSqrt;
  590. z *= invSqrt;
  591. d = -(j.x * x + j.y * y + j.z * z);
  592. }
  593. else
  594. {
  595. x = 0;
  596. y = 0;
  597. z = 1;
  598. d = -(j.x * x + j.y * y + j.z * z);
  599. }
  600. }
  601. inline void PlaneD::invert()
  602. {
  603. x = -x;
  604. y = -y;
  605. z = -z;
  606. d = -d;
  607. }
  608. inline void PlaneD::neg()
  609. {
  610. invert();
  611. }
  612. inline F64 PlaneD::intersect(const Point3D &p1, const Point3D &p2) const
  613. {
  614. F64 den = mDot(p2 - p1, *this);
  615. if(den == 0)
  616. return PARALLEL_PLANE;
  617. return -distToPlane(p1) / den;
  618. }
  619. inline PlaneD::Side PlaneD::whichSideBox(const Point3D& center,
  620. const Point3D& axisx,
  621. const Point3D& axisy,
  622. const Point3D& axisz) const
  623. {
  624. F64 baseDist = distToPlane(center);
  625. F64 compDist = mFabs(mDot(axisx, *this)) +
  626. mFabs(mDot(axisy, *this)) +
  627. mFabs(mDot(axisz, *this));
  628. // Intersects
  629. if (baseDist >= compDist)
  630. return Front;
  631. else if (baseDist <= -compDist)
  632. return Back;
  633. else
  634. return On;
  635. // if (compDist > mFabs(baseDist))
  636. // return On;
  637. // else
  638. // return baseDist < 0.0 ? Back : Front;
  639. }
  640. #endif // _MPLANE_H_