mPlane.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  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. Point3F mObbHalf = obb.getHalfExtents();
  299. const F32 r = mObbHalf.x * mFabs( mDot( obb.getAxis( 0 ), *this ) ) +
  300. mObbHalf.y * mFabs( mDot( obb.getAxis( 1 ), *this ) ) +
  301. mObbHalf.z * mFabs( mDot( obb.getAxis( 2 ), *this ) );
  302. const F32 dist = distToPlane( obb.getCenter() );
  303. if( dist > r )
  304. return Front;
  305. else if( dist < - r )
  306. return Back;
  307. else
  308. return On;
  309. }
  310. //-----------------------------------------------------------------------------
  311. inline PlaneF::Side PlaneF::whichSideBox(const Point3F& center,
  312. const Point3F& axisx,
  313. const Point3F& axisy,
  314. const Point3F& axisz) const
  315. {
  316. F32 baseDist = distToPlane(center);
  317. F32 compDist = mFabs(mDot(axisx, *this)) +
  318. mFabs(mDot(axisy, *this)) +
  319. mFabs(mDot(axisz, *this));
  320. if (baseDist >= compDist)
  321. return Front;
  322. else if (baseDist <= -compDist)
  323. return Back;
  324. else
  325. return On;
  326. }
  327. inline void PlaneF::set( F32 _x, F32 _y, F32 _z )
  328. {
  329. Point3F::set(_x,_y,_z);
  330. }
  331. inline void PlaneF::set( F32 _x, F32 _y, F32 _z, F32 _d )
  332. {
  333. Point3F::set(_x,_y,_z);
  334. d = _d;
  335. }
  336. //---------------------------------------------------------------------------
  337. /// Calculate the coefficients of the plane passing through
  338. /// a point with the given normal.
  339. inline void PlaneF::setPoint(const Point3F &p)
  340. {
  341. d = -(p.x * x + p.y * y + p.z * z);
  342. }
  343. inline void PlaneF::set( const Point3F& p, const Point3F& n )
  344. {
  345. x = n.x; y = n.y; z = n.z;
  346. normalize();
  347. // Calculate the last plane coefficient.
  348. d = -(p.x * x + p.y * y + p.z * z);
  349. }
  350. //---------------------------------------------------------------------------
  351. // Calculate the coefficients of the plane passing through
  352. // three points. Basically it calculates the normal to the three
  353. // points then calculates a plane through the middle point with that
  354. // normal.
  355. inline void PlaneF::set( const Point3F& k, const Point3F& j, const Point3F& l )
  356. {
  357. // Point3F kj, lj, pv;
  358. // kj = k - j;
  359. // lj = l - j;
  360. // mCross( kj, lj, &pv );
  361. // set(j, pv);
  362. // Inline for speed...
  363. const F32 ax = k.x-j.x;
  364. const F32 ay = k.y-j.y;
  365. const F32 az = k.z-j.z;
  366. const F32 bx = l.x-j.x;
  367. const F32 by = l.y-j.y;
  368. const F32 bz = l.z-j.z;
  369. x = ay*bz - az*by;
  370. y = az*bx - ax*bz;
  371. z = ax*by - ay*bx;
  372. m_point3F_normalize( (F32 *)(&x) );
  373. d = -(j.x * x + j.y * y + j.z * z);
  374. }
  375. inline void PlaneF::invert()
  376. {
  377. x = -x;
  378. y = -y;
  379. z = -z;
  380. d = -d;
  381. }
  382. inline void PlaneF::neg()
  383. {
  384. invert();
  385. }
  386. inline F32 PlaneF::intersect(const Point3F &p1, const Point3F &p2) const
  387. {
  388. const F32 den = mDot(p2 - p1, *this);
  389. if( mIsZero( den ) )
  390. return PARALLEL_PLANE;
  391. return -distToPlane(p1) / den;
  392. }
  393. inline bool PlaneF::intersect( const Point3F &start, const Point3F &dir, Point3F *outHit ) const
  394. {
  395. const F32 den = mDot( dir, *this );
  396. if ( mIsZero( den ) )
  397. return false;
  398. F32 dist = -distToPlane( start ) / den;
  399. *outHit = start + dir * dist;
  400. return true;
  401. }
  402. class PlaneD: public Point3D
  403. {
  404. public:
  405. /// NOTE: d is the NEGATIVE distance along the xyz normal.
  406. F64 d;
  407. PlaneD();
  408. PlaneD( const PlaneF& copy);
  409. PlaneD( const Point3D& p, const Point3D& n );
  410. /// NOTE: d is the NEGATIVE distance along the xyz normal.
  411. PlaneD( F64 _x, F64 _y, F64 _z, F64 _d);
  412. PlaneD( const Point3D& j, const Point3D& k, const Point3D& l );
  413. // Methods
  414. //using Point3D::set;
  415. void set(const F64 _x, const F64 _y, const F64 _z);
  416. void set( const Point3D& p, const Point3D& n);
  417. void set( const Point3D& k, const Point3D& j, const Point3D& l );
  418. void setPoint(const Point3D &p); // assumes the x,y,z fields are already set
  419. // creates an un-normalized plane
  420. void setXY(F64 zz);
  421. void setYZ(F64 xx);
  422. void setXZ(F64 yy);
  423. void setXY(const Point3D& P, F64 dir);
  424. void setYZ(const Point3D& P, F64 dir);
  425. void setXZ(const Point3D& P, F64 dir);
  426. void shiftX(F64 xx);
  427. void shiftY(F64 yy);
  428. void shiftZ(F64 zz);
  429. void invert();
  430. void neg();
  431. Point3D project(const Point3D &pt) const; // projects the point onto the plane.
  432. F64 distToPlane( const Point3D& cp ) const;
  433. enum Side {
  434. Front = 1,
  435. On = 0,
  436. Back = -1
  437. };
  438. Side whichSide(const Point3D& cp) const;
  439. F64 intersect(const Point3D &start, const Point3D &end) const;
  440. //DLLAPI bool split( const Poly3F& poly, Poly3F* front, Poly3F* back );
  441. bool isHorizontal() const;
  442. bool isVertical() const;
  443. Side whichSideBox(const Point3D& center,
  444. const Point3D& axisx,
  445. const Point3D& axisy,
  446. const Point3D& axisz) const;
  447. };
  448. //#define PARALLEL_PLANE 1e20f
  449. //#define PlaneSwitchCode(s, e) (s * 3 + e)
  450. //---------------------------------------------------------------------------
  451. inline PlaneD::PlaneD()
  452. {
  453. }
  454. inline PlaneD::
  455. PlaneD( F64 _x, F64 _y, F64 _z, F64 _d )
  456. {
  457. x = _x; y = _y; z = _z; d = _d;
  458. }
  459. inline PlaneD::PlaneD( const PlaneF& copy)
  460. {
  461. x = copy.x; y = copy.y; z = copy.z; d = copy.d;
  462. }
  463. inline PlaneD::PlaneD( const Point3D& p, const Point3D& n )
  464. {
  465. set(p,n);
  466. }
  467. inline PlaneD::PlaneD( const Point3D& j, const Point3D& k, const Point3D& l )
  468. {
  469. set(j,k,l);
  470. }
  471. inline void PlaneD::setXY( F64 zz )
  472. {
  473. x = y = 0; z = 1; d = -zz;
  474. }
  475. inline void PlaneD::setYZ( F64 xx )
  476. {
  477. x = 1; z = y = 0; d = -xx;
  478. }
  479. inline void PlaneD::setXZ( F64 yy )
  480. {
  481. x = z = 0; y = 1; d = -yy;
  482. }
  483. inline void PlaneD::setXY(const Point3D& point, F64 dir) // Normal = (0, 0, -1|1)
  484. {
  485. x = y = 0;
  486. d = -((z = dir) * point.z);
  487. }
  488. inline void PlaneD::setYZ(const Point3D& point, F64 dir) // Normal = (-1|1, 0, 0)
  489. {
  490. z = y = 0;
  491. d = -((x = dir) * point.x);
  492. }
  493. inline void PlaneD::setXZ(const Point3D& point, F64 dir) // Normal = (0, -1|1, 0)
  494. {
  495. x = z = 0;
  496. d = -((y = dir) * point.y);
  497. }
  498. inline void PlaneD::shiftX( F64 xx )
  499. {
  500. d -= xx * x;
  501. }
  502. inline void PlaneD::shiftY( F64 yy )
  503. {
  504. d -= yy * y;
  505. }
  506. inline void PlaneD::shiftZ( F64 zz )
  507. {
  508. d -= zz * z;
  509. }
  510. inline bool PlaneD::isHorizontal() const
  511. {
  512. return (x == 0 && y == 0) ? true : false;
  513. }
  514. inline bool PlaneD::isVertical() const
  515. {
  516. return ((x != 0 || y != 0) && z == 0) ? true : false;
  517. }
  518. inline Point3D PlaneD::project(const Point3D &pt) const
  519. {
  520. F64 dist = distToPlane(pt);
  521. return Point3D(pt.x - x * dist, pt.y - y * dist, pt.z - z * dist);
  522. }
  523. inline F64 PlaneD::distToPlane( const Point3D& cp ) const
  524. {
  525. // return mDot(*this,cp) + d;
  526. return (x * cp.x + y * cp.y + z * cp.z) + d;
  527. }
  528. inline PlaneD::Side PlaneD::whichSide(const Point3D& cp) const
  529. {
  530. F64 dist = distToPlane(cp);
  531. if (dist >= 0.005f) // if (mFabs(dist) < 0.005f)
  532. return Front; // return On;
  533. else if (dist <= -0.005f) // else if (dist > 0.0f)
  534. return Back; // return Front;
  535. else // else
  536. return On; // return Back;
  537. }
  538. inline void PlaneD::set(const F64 _x, const F64 _y, const F64 _z)
  539. {
  540. Point3D::set(_x,_y,_z);
  541. }
  542. //---------------------------------------------------------------------------
  543. // Calculate the coefficients of the plane passing through
  544. // a point with the given normal.
  545. ////inline void PlaneD::set( const Point3D& p, const Point3D& n )
  546. inline void PlaneD::setPoint(const Point3D &p)
  547. {
  548. d = -(p.x * x + p.y * y + p.z * z);
  549. }
  550. inline void PlaneD::set( const Point3D& p, const Point3D& n )
  551. {
  552. x = n.x; y = n.y; z = n.z;
  553. normalize();
  554. // Calculate the last plane coefficient.
  555. d = -(p.x * x + p.y * y + p.z * z);
  556. }
  557. //---------------------------------------------------------------------------
  558. // Calculate the coefficients of the plane passing through
  559. // three points. Basically it calculates the normal to the three
  560. // points then calculates a plane through the middle point with that
  561. // normal.
  562. inline void PlaneD::set( const Point3D& k, const Point3D& j, const Point3D& l )
  563. {
  564. // Point3D kj,lj,pv;
  565. // kj = k;
  566. // kj -= j;
  567. // lj = l;
  568. // lj -= j;
  569. // mCross( kj, lj, &pv );
  570. // set(j,pv);
  571. // Above ends up making function calls up the %*#...
  572. // This is called often enough to be a little more direct
  573. // about it (sqrt should become intrinsic in the future)...
  574. F64 ax = k.x-j.x;
  575. F64 ay = k.y-j.y;
  576. F64 az = k.z-j.z;
  577. F64 bx = l.x-j.x;
  578. F64 by = l.y-j.y;
  579. F64 bz = l.z-j.z;
  580. x = ay*bz - az*by;
  581. y = az*bx - ax*bz;
  582. z = ax*by - ay*bx;
  583. F64 squared = x*x + y*y + z*z;
  584. AssertFatal(squared != 0.0, "Error, no plane possible!");
  585. // In non-debug mode
  586. if (squared != 0)
  587. {
  588. F64 invSqrt = 1.0 / (F64)mSqrt(x*x + y*y + z*z);
  589. x *= invSqrt;
  590. y *= invSqrt;
  591. z *= invSqrt;
  592. d = -(j.x * x + j.y * y + j.z * z);
  593. }
  594. else
  595. {
  596. x = 0;
  597. y = 0;
  598. z = 1;
  599. d = -(j.x * x + j.y * y + j.z * z);
  600. }
  601. }
  602. inline void PlaneD::invert()
  603. {
  604. x = -x;
  605. y = -y;
  606. z = -z;
  607. d = -d;
  608. }
  609. inline void PlaneD::neg()
  610. {
  611. invert();
  612. }
  613. inline F64 PlaneD::intersect(const Point3D &p1, const Point3D &p2) const
  614. {
  615. F64 den = mDot(p2 - p1, *this);
  616. if(den == 0)
  617. return PARALLEL_PLANE;
  618. return -distToPlane(p1) / den;
  619. }
  620. inline PlaneD::Side PlaneD::whichSideBox(const Point3D& center,
  621. const Point3D& axisx,
  622. const Point3D& axisy,
  623. const Point3D& axisz) const
  624. {
  625. F64 baseDist = distToPlane(center);
  626. F64 compDist = mFabs(mDot(axisx, *this)) +
  627. mFabs(mDot(axisy, *this)) +
  628. mFabs(mDot(axisz, *this));
  629. // Intersects
  630. if (baseDist >= compDist)
  631. return Front;
  632. else if (baseDist <= -compDist)
  633. return Back;
  634. else
  635. return On;
  636. // if (compDist > mFabs(baseDist))
  637. // return On;
  638. // else
  639. // return baseDist < 0.0 ? Back : Front;
  640. }
  641. #endif // _MPLANE_H_