mathUtils.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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 _MATHUTILS_H_
  23. #define _MATHUTILS_H_
  24. #ifndef _MPOINT3_H_
  25. #include "math/mPoint3.h"
  26. #endif
  27. #ifndef _MMATRIX_H_
  28. #include "math/mMatrix.h"
  29. #endif
  30. #ifndef _MRECT_H_
  31. #include "math/mRect.h"
  32. #endif
  33. #ifndef _TVECTOR_H_
  34. #include "core/util/tVector.h"
  35. #endif
  36. #ifndef _MATHUTIL_FRUSTUM_H_
  37. #include "math/util/frustum.h"
  38. #endif
  39. class Box3F;
  40. class RectI;
  41. class Frustum;
  42. /// Miscellaneous math utility functions.
  43. namespace MathUtils
  44. {
  45. /// A simple helper struct to define a line.
  46. struct Line
  47. {
  48. Point3F origin;
  49. VectorF direction;
  50. };
  51. /// A ray is also a line.
  52. typedef Line Ray;
  53. /// A simple helper struct to define a line segment.
  54. struct LineSegment
  55. {
  56. Point3F p0;
  57. Point3F p1;
  58. };
  59. /// A simple helper struct to define a clockwise
  60. /// winding quad.
  61. struct Quad
  62. {
  63. Point3F p00;
  64. Point3F p01;
  65. Point3F p10;
  66. Point3F p11;
  67. };
  68. /// Used by mTriangleDistance() to pass along collision info
  69. struct IntersectInfo
  70. {
  71. LineSegment segment; // Starts at given point, ends at collision
  72. Point3F bary; // Barycentric coords for collision
  73. };
  74. /// Rotate the passed vector around the world-z axis by the passed radians.
  75. void vectorRotateZAxis( Point3F &vector, F32 radians );
  76. void vectorRotateZAxis( F32 radians, Point3F *vectors, U32 count );
  77. /// Generates a projection matrix with the near plane
  78. /// moved forward by the bias amount. This function is a helper primarily
  79. /// for working around z-fighting issues.
  80. ///
  81. /// @param bias The amount to move the near plane forward.
  82. /// @param frustum The frustum to generate the new projection matrix from.
  83. /// @param outMat The resulting z-biased projection matrix. Note: It must be initialized before the call.
  84. /// @param rotate Optional parameter specifying whether to rotate the projection matrix similarly to GFXDevice.
  85. ///
  86. void getZBiasProjectionMatrix( F32 bias, const Frustum &frustum, MatrixF *outMat, bool rotate = true );
  87. /// Creates orientation matrix from a direction vector. Assumes ( 0 0 1 ) is up.
  88. MatrixF createOrientFromDir( const Point3F &direction );
  89. /// Creates an orthonormal basis matrix with the unit length
  90. /// input vector in column 2 (up vector).
  91. ///
  92. /// @param up The non-zero unit length up vector.
  93. /// @param outMat The output matrix which must be initialized prior to the call.
  94. ///
  95. void getMatrixFromUpVector( const VectorF &up, MatrixF *outMat );
  96. /// Creates an orthonormal basis matrix with the unit length
  97. /// input vector in column 1 (forward vector).
  98. ///
  99. /// @param forward The non-zero unit length forward vector.
  100. /// @param outMat The output matrix which must be initialized prior to the call.
  101. ///
  102. void getMatrixFromForwardVector( const VectorF &forward, MatrixF *outMat );
  103. /// Creates random direction given angle parameters similar to the particle system.
  104. ///
  105. /// The angles are relative to the specified axis. Both phi and theta are in degrees.
  106. Point3F randomDir( const Point3F &axis, F32 thetaAngleMin, F32 thetaAngleMax, F32 phiAngleMin = 0.0, F32 phiAngleMax = 360.0 );
  107. /// Returns a random 3D point within a sphere of the specified radius
  108. /// centered at the origin.
  109. Point3F randomPointInSphere( F32 radius );
  110. /// Returns a random 2D point within a circle of the specified radius
  111. /// centered at the origin.
  112. Point2F randomPointInCircle( F32 radius );
  113. /// Returns yaw and pitch angles from a given vector.
  114. ///
  115. /// Angles are in RADIANS.
  116. ///
  117. /// Assumes north is (0.0, 1.0, 0.0), the degrees move upwards clockwise.
  118. ///
  119. /// The range of yaw is 0 - 2PI. The range of pitch is -PI/2 - PI/2.
  120. ///
  121. /// <b>ASSUMES Z AXIS IS UP</b>
  122. void getAnglesFromVector( const VectorF &vec, F32 &yawAng, F32 &pitchAng );
  123. /// Returns vector from given yaw and pitch angles.
  124. ///
  125. /// Angles are in RADIANS.
  126. ///
  127. /// Assumes north is (0.0, 1.0, 0.0), the degrees move upwards clockwise.
  128. ///
  129. /// The range of yaw is 0 - 2PI. The range of pitch is -PI/2 - PI/2.
  130. ///
  131. /// <b>ASSUMES Z AXIS IS UP</b>
  132. void getVectorFromAngles( VectorF &vec, F32 yawAng, F32 pitchAng );
  133. /// Returns the angle between two given vectors
  134. ///
  135. /// Angles is in RADIANS
  136. ///
  137. F32 getAngleBetweenVectors(VectorF vecA, VectorF vecB);
  138. /// Returns the angle between two given vectors, utilizing a normal vector to discertain the angle's sign
  139. ///
  140. /// Angles is in RADIANS
  141. ///
  142. F32 getSignedAngleBetweenVectors(VectorF vecA, VectorF vecB, VectorF norm);
  143. /// Simple reflection equation - pass in a vector and a normal to reflect off of
  144. inline Point3F reflect( Point3F &inVec, Point3F &norm )
  145. {
  146. return inVec - norm * ( mDot( inVec, norm ) * 2.0f );
  147. }
  148. /// Collide two capsules (sphere swept lines) against each other, reporting only if they intersect or not.
  149. /// Based on routine from "Real Time Collision Detection" by Christer Ericson pp 114.
  150. bool capsuleCapsuleOverlap(const Point3F & a1, const Point3F & b1, F32 radius1, const Point3F & a2, const Point3F & b2, F32 radius2);
  151. /// Return capsule-sphere overlap. Returns time of first overlap, where time
  152. /// is viewed as a sphere of radius radA moving from point A0 to A1.
  153. bool capsuleSphereNearestOverlap(const Point3F & A0, const Point3F A1, F32 radA, const Point3F & B, F32 radB, F32 & t);
  154. /// Intersect two line segments (p1,q1) and (p2,q2), returning points on lines (c1 & c2) and line parameters (s,t).
  155. /// Based on routine from "Real Time Collision Detection" by Christer Ericson pp 149.
  156. F32 segmentSegmentNearest(const Point3F & p1, const Point3F & q1, const Point3F & p2, const Point3F & q2, F32 & s, F32 & t, Point3F & c1, Point3F & c2);
  157. /// Transform bounding box making sure to keep original box entirely contained.
  158. void transformBoundingBox(const Box3F &sbox, const MatrixF &mat, const Point3F scale, Box3F &dbox);
  159. bool mProjectWorldToScreen( const Point3F &in,
  160. Point3F *out,
  161. const RectI &view,
  162. const MatrixF &world,
  163. const MatrixF &projection );
  164. bool mProjectWorldToScreen( const Point3F &in,
  165. Point3F *out,
  166. const RectI &view,
  167. const MatrixF &worldProjection );
  168. void mProjectScreenToWorld( const Point3F &in,
  169. Point3F *out,
  170. const RectI &view,
  171. const MatrixF &world,
  172. const MatrixF &projection,
  173. F32 far,
  174. F32 near);
  175. /// Clip @a inFrustum by the given polygon.
  176. ///
  177. /// @note The input polygon is limited to 58 vertices.
  178. ///
  179. /// @param points Polygon vertices.
  180. /// @param numPoints Number of vertices in @a points.
  181. /// @param viewport Screen viewport. Note that this corresponds to the root frustum and not necessarily to @a inFrustum.
  182. /// @param world World->view transform.
  183. /// @param projection Projection matrix.
  184. /// @param inFrustum Frustum to clip.
  185. /// @param rootFrustum Frustum corresponding to @a viewport.
  186. /// @param outFrustum Resulting clipped frustum.
  187. ///
  188. /// @return True if the frustum was successfully clipped and @a outFrustum is valid, false otherwise
  189. /// (if, for example, the input polygon is completely outside @a inFrustum).
  190. bool clipFrustumByPolygon( const Point3F* points,
  191. U32 numPoints,
  192. const RectI& viewport,
  193. const MatrixF& world,
  194. const MatrixF& projection,
  195. const Frustum& inFrustum,
  196. const Frustum& rootFrustum,
  197. Frustum& outFrustum );
  198. /// Returns true if the test point is within the polygon.
  199. /// @param verts The array of points which forms the polygon.
  200. /// @param vertCount The number of points in the polygon.
  201. /// @param testPt The point to test.
  202. bool pointInPolygon( const Point2F *verts, U32 vertCount, const Point2F &testPt );
  203. /// Remove all edges from the given polygon that have a total length shorter
  204. /// than @a epsilon.
  205. ///
  206. U32 removeShortPolygonEdges( const Point3F* verts, U32 vertCount, F32 epsilon );
  207. /// Calculates the shortest line segment between two lines.
  208. ///
  209. /// @param outSegment The result where .p0 is the point on line0 and .p1 is the point on line1.
  210. ///
  211. void mShortestSegmentBetweenLines( const Line &line0, const Line &line1, LineSegment *outSegment );
  212. /// Returns the greatest common divisor of two positive integers.
  213. U32 greatestCommonDivisor( U32 u, U32 v );
  214. /// Returns the barycentric coordinates and time of intersection between
  215. /// a line segment and a triangle.
  216. ///
  217. /// @param p1 The first point of the line segment.
  218. /// @param p2 The second point of the line segment.
  219. /// @param t1 The first point of the triangle.
  220. /// @param t2 The second point of the triangle.
  221. /// @param t2 The third point of the triangle.
  222. /// @param outUVW The optional output barycentric coords.
  223. /// @param outT The optional output time of intersection.
  224. ///
  225. /// @return Returns true if a collision occurs.
  226. ///
  227. bool mLineTriangleCollide( const Point3F &p1, const Point3F &p2,
  228. const Point3F &t1, const Point3F &t2, const Point3F &t3,
  229. Point3F *outUVW = NULL,
  230. F32 *outT = NULL );
  231. /// Returns the uv coords and time of intersection between
  232. /// a ray and a quad.
  233. ///
  234. /// @param quad The quad.
  235. /// @param ray The ray.
  236. /// @param outUV The optional output UV coords of the intersection.
  237. /// @param outT The optional output time of intersection.
  238. ///
  239. /// @return Returns true if a collision occurs.
  240. ///
  241. bool mRayQuadCollide( const Quad &quad,
  242. const Ray &ray,
  243. Point2F *outUV = NULL,
  244. F32 *outT = NULL );
  245. /// Returns the distance between a point and triangle 'abc'.
  246. F32 mTriangleDistance( const Point3F &a, const Point3F &b, const Point3F &c, const Point3F &p, IntersectInfo* info=NULL );
  247. /// Returns the normal of the passed triangle 'abc'.
  248. ///
  249. /// If we assume counter-clockwise triangle culling, normal will point
  250. /// out from the 'solid' side of the triangle.
  251. ///
  252. Point3F mTriangleNormal( const Point3F &a, const Point3F &b, const Point3F &c );
  253. /// Returns the closest point on the segment defined by
  254. /// points a, b to the point p.
  255. Point3F mClosestPointOnSegment( const Point3F &a,
  256. const Point3F &b,
  257. const Point3F &p );
  258. /// Sort the passed verts ( Point3F ) in a clockwise or counter-clockwise winding order.
  259. /// Verts must be co-planar and non-collinear.
  260. ///
  261. /// @param quadMat Transform matrix from vert space to quad space.
  262. /// @param clockwise Sort clockwise or counter-clockwise
  263. /// @param verts Array of Point3F verts.
  264. /// @param vertMap Output - Array of vert element ids sorted by winding order.
  265. /// @param count Element count of the verts and vertMap arrays which must be allocated prior to this call.
  266. ///
  267. void sortQuadWindingOrder( const MatrixF &quadMat, bool clockwise, const Point3F *verts, U32 *vertMap, U32 count );
  268. /// Same as above except we assume that the passed verts ( Point3F ) are already
  269. /// transformed into 'quad space'. If this was done correctly and the points
  270. /// are coplanar this means their z components will all be zero.
  271. void sortQuadWindingOrder( bool clockwise, const Point3F *verts, U32 *vertMap, U32 count );
  272. ///
  273. /// WORK IN PROGRESS
  274. ///
  275. /// Creates an orthonormal basis matrix from one, two, or three unit length
  276. /// input vectors. If more than one input vector is provided they must be
  277. /// mutually perpendicular.
  278. ///
  279. /// @param rvec Optional unit length right vector.
  280. /// @param fvec Optional unit length forward vector.
  281. /// @param uvec Optional unit length up vector.
  282. /// @param pos Optional position to initialize the matrix.
  283. /// @param outMat The output matrix which must be initialized prior to the call.
  284. ///
  285. void buildMatrix( const VectorF *rvec, const VectorF *fvec, const VectorF *uvec, const VectorF *pos, MatrixF *outMat );
  286. ///
  287. bool reduceFrustum( const Frustum& frustum, const RectI& viewport, const RectF& area, Frustum& outFrustum );
  288. /// Build the frustum near plane dimensions from the parameters.
  289. void makeFrustum( F32 *outLeft,
  290. F32 *outRight,
  291. F32 *outTop,
  292. F32 *outBottom,
  293. F32 fovYInRadians,
  294. F32 aspectRatio,
  295. F32 nearPlane );
  296. void makeFovPortFrustum( Frustum *outFrustum,
  297. bool isOrtho,
  298. F32 nearDist,
  299. F32 farDist,
  300. const FovPort &inPort,
  301. const MatrixF &transform = MatrixF(1) );
  302. /// Build a GFX projection matrix from the frustum parameters
  303. /// including the optional rotation required by GFX.
  304. void makeProjection( MatrixF *outMatrix,
  305. F32 fovYInRadians,
  306. F32 aspectRatio,
  307. F32 nearPlane,
  308. F32 farPlane,
  309. bool gfxRotate );
  310. /// Build a projection matrix from the frustum near plane dimensions
  311. /// including the optional rotation required by GFX.
  312. void makeProjection( MatrixF *outMatrix,
  313. F32 left,
  314. F32 right,
  315. F32 top,
  316. F32 bottom,
  317. F32 nearPlane,
  318. F32 farPlane,
  319. bool gfxRotate );
  320. /// Build an orthographic projection matrix from the frustum near
  321. /// plane dimensions including the optional rotation required by GFX.
  322. void makeOrthoProjection( MatrixF *outMatrix,
  323. F32 left,
  324. F32 right,
  325. F32 top,
  326. F32 bottom,
  327. F32 nearPlane,
  328. F32 farPlane,
  329. bool gfxRotate );
  330. /// Find the intersection of the line going from @a edgeA to @a edgeB with the triangle
  331. /// given by @a faceA, @a faceB, and @a faceC.
  332. /// @param edgeA Starting point of edge.
  333. /// @param edgeB End point of edge.
  334. /// @param faceA First vertex of triangle.
  335. /// @param faceB Second vertex of triangle.
  336. /// @param faceC Third vertex of triangle.
  337. /// @param intersection If there is an intersection, the point of intersection on the triangle's
  338. /// face is stored here.
  339. /// @param True if there is an intersection, false otherwise.
  340. bool edgeFaceIntersect( const Point3F &edgeA, const Point3F &edgeB,
  341. const Point3F &faceA, const Point3F &faceB, const Point3F &faceC, const Point3F &faceD, Point3F *intersection );
  342. /// Find out whether the given polygon is planar.
  343. /// @param vertices Array of vertices of the polygon.
  344. /// @param numVertices Number of vertices in @a vertices.
  345. /// @return True if the polygon is planar, false otherwise.
  346. bool isPlanarPolygon( const Point3F* vertices, U32 numVertices );
  347. /// Find out whether the given polygon is convex.
  348. /// @param vertices Array of vertices of the polygon.
  349. /// @param numVertices Number of vertices in @a vertices.
  350. /// @return True if the polygon is convex, false otherwise.
  351. bool isConvexPolygon( const Point3F* vertices, U32 numVertices );
  352. /// Extrude the given polygon along the given direction.
  353. U32 extrudePolygonEdges( const Point3F* vertices, U32 numVertices, const Point3F& direction, PlaneF* outPlanes );
  354. /// Extrude the edges of the given polygon away from @a fromPoint by constructing a set of planes
  355. /// that each go through @a fromPoint and a pair of vertices.
  356. ///
  357. /// The resulting planes are in the same order as the vertices and have their normals facing *inwards*,
  358. /// i.e. the resulting volume will enclose the polygon's interior space.
  359. ///
  360. /// @param vertices Vertices of the polygon in CCW or CW order (both are acceptable).
  361. /// @param numVertices Number of vertices in @a vertices.
  362. /// @param fromPoint
  363. /// @param outPlanes Array in which the resulting planes are stored. Must have room for at least as many
  364. /// planes are there are edges in the polygon.
  365. ///
  366. /// @return
  367. ///
  368. /// @note The input polygon does not necessarily need to be planar but it must be convex.
  369. U32 extrudePolygonEdgesFromPoint( const Point3F* vertices, U32 numVertices,
  370. const Point3F& fromPoint,
  371. PlaneF* outPlanes );
  372. //void findFarthestPoint( const Point3F* points, U32 numPoints, const Point3F& fromPoint, )
  373. /// Build a convex hull from a cloud of 2D points, first and last hull point are the same.
  374. void mBuildHull2D(const Vector<Point2F> inPoints, Vector<Point2F> &hullPoints);
  375. } // namespace MathUtils
  376. #endif // _MATHUTILS_H_