mPlane.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  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() :d(0.0f) {}
  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. d = 0.0;
  454. }
  455. inline PlaneD::
  456. PlaneD( F64 _x, F64 _y, F64 _z, F64 _d )
  457. {
  458. x = _x; y = _y; z = _z; d = _d;
  459. }
  460. inline PlaneD::PlaneD( const PlaneF& copy)
  461. {
  462. x = copy.x; y = copy.y; z = copy.z; d = copy.d;
  463. }
  464. inline PlaneD::PlaneD( const Point3D& p, const Point3D& n )
  465. {
  466. set(p,n);
  467. }
  468. inline PlaneD::PlaneD( const Point3D& j, const Point3D& k, const Point3D& l )
  469. {
  470. set(j,k,l);
  471. }
  472. inline void PlaneD::setXY( F64 zz )
  473. {
  474. x = y = 0; z = 1; d = -zz;
  475. }
  476. inline void PlaneD::setYZ( F64 xx )
  477. {
  478. x = 1; z = y = 0; d = -xx;
  479. }
  480. inline void PlaneD::setXZ( F64 yy )
  481. {
  482. x = z = 0; y = 1; d = -yy;
  483. }
  484. inline void PlaneD::setXY(const Point3D& point, F64 dir) // Normal = (0, 0, -1|1)
  485. {
  486. x = y = 0;
  487. d = -((z = dir) * point.z);
  488. }
  489. inline void PlaneD::setYZ(const Point3D& point, F64 dir) // Normal = (-1|1, 0, 0)
  490. {
  491. z = y = 0;
  492. d = -((x = dir) * point.x);
  493. }
  494. inline void PlaneD::setXZ(const Point3D& point, F64 dir) // Normal = (0, -1|1, 0)
  495. {
  496. x = z = 0;
  497. d = -((y = dir) * point.y);
  498. }
  499. inline void PlaneD::shiftX( F64 xx )
  500. {
  501. d -= xx * x;
  502. }
  503. inline void PlaneD::shiftY( F64 yy )
  504. {
  505. d -= yy * y;
  506. }
  507. inline void PlaneD::shiftZ( F64 zz )
  508. {
  509. d -= zz * z;
  510. }
  511. inline bool PlaneD::isHorizontal() const
  512. {
  513. return (x == 0 && y == 0) ? true : false;
  514. }
  515. inline bool PlaneD::isVertical() const
  516. {
  517. return ((x != 0 || y != 0) && z == 0) ? true : false;
  518. }
  519. inline Point3D PlaneD::project(const Point3D &pt) const
  520. {
  521. F64 dist = distToPlane(pt);
  522. return Point3D(pt.x - x * dist, pt.y - y * dist, pt.z - z * dist);
  523. }
  524. inline F64 PlaneD::distToPlane( const Point3D& cp ) const
  525. {
  526. // return mDot(*this,cp) + d;
  527. return (x * cp.x + y * cp.y + z * cp.z) + d;
  528. }
  529. inline PlaneD::Side PlaneD::whichSide(const Point3D& cp) const
  530. {
  531. F64 dist = distToPlane(cp);
  532. if (dist >= 0.005f) // if (mFabs(dist) < 0.005f)
  533. return Front; // return On;
  534. else if (dist <= -0.005f) // else if (dist > 0.0f)
  535. return Back; // return Front;
  536. else // else
  537. return On; // return Back;
  538. }
  539. inline void PlaneD::set(const F64 _x, const F64 _y, const F64 _z)
  540. {
  541. Point3D::set(_x,_y,_z);
  542. }
  543. //---------------------------------------------------------------------------
  544. // Calculate the coefficients of the plane passing through
  545. // a point with the given normal.
  546. ////inline void PlaneD::set( const Point3D& p, const Point3D& n )
  547. inline void PlaneD::setPoint(const Point3D &p)
  548. {
  549. d = -(p.x * x + p.y * y + p.z * z);
  550. }
  551. inline void PlaneD::set( const Point3D& p, const Point3D& n )
  552. {
  553. x = n.x; y = n.y; z = n.z;
  554. normalize();
  555. // Calculate the last plane coefficient.
  556. d = -(p.x * x + p.y * y + p.z * z);
  557. }
  558. //---------------------------------------------------------------------------
  559. // Calculate the coefficients of the plane passing through
  560. // three points. Basically it calculates the normal to the three
  561. // points then calculates a plane through the middle point with that
  562. // normal.
  563. inline void PlaneD::set( const Point3D& k, const Point3D& j, const Point3D& l )
  564. {
  565. // Point3D kj,lj,pv;
  566. // kj = k;
  567. // kj -= j;
  568. // lj = l;
  569. // lj -= j;
  570. // mCross( kj, lj, &pv );
  571. // set(j,pv);
  572. // Above ends up making function calls up the %*#...
  573. // This is called often enough to be a little more direct
  574. // about it (sqrt should become intrinsic in the future)...
  575. F64 ax = k.x-j.x;
  576. F64 ay = k.y-j.y;
  577. F64 az = k.z-j.z;
  578. F64 bx = l.x-j.x;
  579. F64 by = l.y-j.y;
  580. F64 bz = l.z-j.z;
  581. x = ay*bz - az*by;
  582. y = az*bx - ax*bz;
  583. z = ax*by - ay*bx;
  584. F64 squared = x*x + y*y + z*z;
  585. AssertFatal(squared != 0.0, "Error, no plane possible!");
  586. // In non-debug mode
  587. if (squared != 0)
  588. {
  589. F64 invSqrt = 1.0 / (F64)mSqrt(x*x + y*y + z*z);
  590. x *= invSqrt;
  591. y *= invSqrt;
  592. z *= invSqrt;
  593. d = -(j.x * x + j.y * y + j.z * z);
  594. }
  595. else
  596. {
  597. x = 0;
  598. y = 0;
  599. z = 1;
  600. d = -(j.x * x + j.y * y + j.z * z);
  601. }
  602. }
  603. inline void PlaneD::invert()
  604. {
  605. x = -x;
  606. y = -y;
  607. z = -z;
  608. d = -d;
  609. }
  610. inline void PlaneD::neg()
  611. {
  612. invert();
  613. }
  614. inline F64 PlaneD::intersect(const Point3D &p1, const Point3D &p2) const
  615. {
  616. F64 den = mDot(p2 - p1, *this);
  617. if(den == 0)
  618. return PARALLEL_PLANE;
  619. return -distToPlane(p1) / den;
  620. }
  621. inline PlaneD::Side PlaneD::whichSideBox(const Point3D& center,
  622. const Point3D& axisx,
  623. const Point3D& axisy,
  624. const Point3D& axisz) const
  625. {
  626. F64 baseDist = distToPlane(center);
  627. F64 compDist = mFabs(mDot(axisx, *this)) +
  628. mFabs(mDot(axisy, *this)) +
  629. mFabs(mDot(axisz, *this));
  630. // Intersects
  631. if (baseDist >= compDist)
  632. return Front;
  633. else if (baseDist <= -compDist)
  634. return Back;
  635. else
  636. return On;
  637. // if (compDist > mFabs(baseDist))
  638. // return On;
  639. // else
  640. // return baseDist < 0.0 ? Back : Front;
  641. }
  642. #endif // _MPLANE_H_