mPlane.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. #include "platform/platform.h"
  23. #include "math/mPlane.h"
  24. #include "math/mathUtils.h"
  25. #include "math/mBox.h"
  26. #include "math/mOrientedBox.h"
  27. #include "math/mSphere.h"
  28. //-----------------------------------------------------------------------------
  29. bool PlaneF::intersect( const PlaneF& plane, Point3F& outLinePt, VectorF& outLineDir ) const
  30. {
  31. // Compute direction of intersection line.
  32. outLineDir = mCross( *this, plane );
  33. // If d is zero, the planes are parallel (and separated)
  34. // or coincident, so they're not considered intersecting
  35. F32 denom = mDot( outLineDir, outLineDir );
  36. if ( denom < 0.00001f )
  37. return false;
  38. // Compute point on intersection line
  39. outLinePt = - mCross( d * plane - plane.d * *this,
  40. outLineDir ) / denom;
  41. return true;
  42. }
  43. //-----------------------------------------------------------------------------
  44. bool PlaneF::isParallelTo( const PlaneF& plane, F32 epsilon ) const
  45. {
  46. F32 val = 1.0f - mFabs( mDot( *this, plane ) );
  47. return ( val > - epsilon ) && ( val < epsilon );
  48. }
  49. //-----------------------------------------------------------------------------
  50. bool PlaneF::isPerpendicularTo( const PlaneF& plane, F32 epsilon ) const
  51. {
  52. F32 val = mDot( *this, plane );
  53. return ( val > - epsilon) && ( val < epsilon );
  54. }
  55. //-----------------------------------------------------------------------------
  56. bool PlaneF::clipSegment( const Point3F& start, const Point3F& end, Point3F& outNewEnd ) const
  57. {
  58. // Intersect ray with plane.
  59. F32 dist = intersect( start, end );
  60. if( dist == PARALLEL_PLANE || dist < 0.f || dist > 1.f )
  61. return false;
  62. // Compute distance to point on segment.
  63. Point3F dir = end - start;
  64. dir *= dist;
  65. // Compute new end point.
  66. outNewEnd = start + dir;
  67. return true;
  68. }
  69. //-----------------------------------------------------------------------------
  70. U32 PlaneF::clipPolygon( const Point3F* inVertices, U32 inNumVertices, Point3F* outVertices ) const
  71. {
  72. // Find the first vertex that lies on the front of the plane.
  73. S32 start = -1;
  74. for( U32 i = 0; i < inNumVertices; i ++ )
  75. {
  76. Side side = whichSide( inVertices[ i ] );
  77. if( side == PlaneF::Front )
  78. {
  79. start = i;
  80. break;
  81. }
  82. }
  83. // If nothing was in front of the plane, we're done.
  84. if( start == -1 )
  85. return 0;
  86. Point3F finalPoints[ 128 ];
  87. U32 numFinalPoints = 0;
  88. U32 baseStart = start;
  89. U32 end = ( start + 1 ) % inNumVertices;
  90. dMemcpy( outVertices, inVertices, inNumVertices * sizeof( Point3F ) );
  91. while( end != baseStart )
  92. {
  93. const Point3F& rStartPoint = outVertices[ start ];
  94. const Point3F& rEndPoint = outVertices[ end ];
  95. PlaneF::Side fSide = whichSide( rStartPoint );
  96. PlaneF::Side eSide = whichSide( rEndPoint );
  97. S32 code = fSide * 3 + eSide;
  98. switch( code )
  99. {
  100. case 4: // f f
  101. case 3: // f o
  102. case 1: // o f
  103. case 0: // o o
  104. // No Clipping required
  105. finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
  106. start = end;
  107. end = ( end + 1 ) % inNumVertices;
  108. break;
  109. case 2: // f b
  110. {
  111. // In this case, we emit the front point, Insert the intersection,
  112. // and advancing to point to first point that is in front or on...
  113. //
  114. finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
  115. Point3F vector = rEndPoint - rStartPoint;
  116. F32 t = - ( distToPlane( rStartPoint ) / mDot( *this, vector ) );
  117. Point3F intersection = rStartPoint + ( vector * t );
  118. finalPoints[ numFinalPoints ++ ] = intersection;
  119. U32 endSeek = ( end + 1 ) % inNumVertices;
  120. while( whichSide( outVertices[ endSeek ] ) == PlaneF::Back )
  121. endSeek = ( endSeek + 1 ) % inNumVertices;
  122. end = endSeek;
  123. start = ( end + ( inNumVertices - 1 ) ) % inNumVertices;
  124. const Point3F& rNewStartPoint = outVertices[ start ];
  125. const Point3F& rNewEndPoint = outVertices[ end ];
  126. vector = rNewEndPoint - rNewStartPoint;
  127. t = - ( distToPlane( rNewStartPoint ) / mDot( *this, vector ) );
  128. intersection = rNewStartPoint + ( vector * t );
  129. outVertices[ start ] = intersection;
  130. }
  131. break;
  132. case -1: // o b
  133. {
  134. // In this case, we emit the front point, and advance to point to first
  135. // point that is in front or on...
  136. //
  137. finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
  138. U32 endSeek = ( end + 1 ) % inNumVertices;
  139. while( whichSide( outVertices[ endSeek ] ) == PlaneF::Back)
  140. endSeek = ( endSeek + 1 ) % inNumVertices;
  141. end = endSeek;
  142. start = (end + ( inNumVertices - 1 ) ) % inNumVertices;
  143. const Point3F& rNewStartPoint = outVertices[ start ];
  144. const Point3F& rNewEndPoint = outVertices[ end ];
  145. Point3F vector = rNewEndPoint - rNewStartPoint;
  146. F32 t = - ( distToPlane( rNewStartPoint ) / mDot( *this, vector ) );
  147. Point3F intersection = rNewStartPoint + ( vector * t );
  148. outVertices[ start ] = intersection;
  149. }
  150. break;
  151. case -2: // b f
  152. case -3: // b o
  153. case -4: // b b
  154. // In the algorithm used here, this should never happen...
  155. AssertISV(false, "SGUtil::clipToPlane: error in polygon clipper");
  156. break;
  157. default:
  158. AssertFatal(false, "SGUtil::clipToPlane: bad outcode");
  159. break;
  160. }
  161. }
  162. // Emit the last point.
  163. finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
  164. AssertFatal( numFinalPoints >= 3, avar("Error, this shouldn't happen! Invalid winding in clipToPlane: %d", numFinalPoints ) );
  165. // Copy the new rWinding, and we're set!
  166. //
  167. dMemcpy( outVertices, finalPoints, numFinalPoints * sizeof( Point3F ) );
  168. AssertISV( numFinalPoints <= 128, "MaxWindingPoints exceeded in scenegraph. Fatal error.");
  169. return numFinalPoints;
  170. }