mathUtils.h

Engine/source/math/mathUtils.h

More...

Classes:

class

Used by mTriangleDistance() to pass along collision info.

class

A simple helper struct to define a line.

class

A simple helper struct to define a line segment.

class

A simple helper struct to define a clockwise winding quad.

Namespaces:

namespace

Miscellaneous math utility functions.

Detailed Description

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