mathUtils.h
Engine/source/math/mathUtils.h
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 /// Returns the angle between two given vectors, utilizing a normal vector to discertain the angle's sign 166 /// 167 /// Angles is in RADIANS 168 /// 169 F32 getSignedAngleBetweenVectors(VectorF vecA, VectorF vecB, VectorF norm); 170 171 /// Simple reflection equation - pass in a vector and a normal to reflect off of 172 inline Point3F reflect( Point3F &inVec, Point3F &norm ) 173 { 174 return inVec - norm * ( mDot( inVec, norm ) * 2.0f ); 175 } 176 177 /// Collide two capsules (sphere swept lines) against each other, reporting only if they intersect or not. 178 /// Based on routine from "Real Time Collision Detection" by Christer Ericson pp 114. 179 bool capsuleCapsuleOverlap(const Point3F & a1, const Point3F & b1, F32 radius1, const Point3F & a2, const Point3F & b2, F32 radius2); 180 181 /// Return capsule-sphere overlap. Returns time of first overlap, where time 182 /// is viewed as a sphere of radius radA moving from point A0 to A1. 183 bool capsuleSphereNearestOverlap(const Point3F & A0, const Point3F A1, F32 radA, const Point3F & B, F32 radB, F32 & t); 184 185 /// Intersect two line segments (p1,q1) and (p2,q2), returning points on lines (c1 & c2) and line parameters (s,t). 186 /// Based on routine from "Real Time Collision Detection" by Christer Ericson pp 149. 187 F32 segmentSegmentNearest(const Point3F & p1, const Point3F & q1, const Point3F & p2, const Point3F & q2, F32 & s, F32 & t, Point3F & c1, Point3F & c2); 188 189 /// Transform bounding box making sure to keep original box entirely contained. 190 void transformBoundingBox(const Box3F &sbox, const MatrixF &mat, const Point3F scale, Box3F &dbox); 191 192 bool mProjectWorldToScreen( const Point3F &in, 193 Point3F *out, 194 const RectI &view, 195 const MatrixF &world, 196 const MatrixF &projection ); 197 bool mProjectWorldToScreen( const Point3F &in, 198 Point3F *out, 199 const RectI &view, 200 const MatrixF &worldProjection ); 201 202 void mProjectScreenToWorld( const Point3F &in, 203 Point3F *out, 204 const RectI &view, 205 const MatrixF &world, 206 const MatrixF &projection, 207 F32 far, 208 F32 near); 209 210 /// Clip @a inFrustum by the given polygon. 211 /// 212 /// @note The input polygon is limited to 58 vertices. 213 /// 214 /// @param points Polygon vertices. 215 /// @param numPoints Number of vertices in @a points. 216 /// @param viewport Screen viewport. Note that this corresponds to the root frustum and not necessarily to @a inFrustum. 217 /// @param world World->view transform. 218 /// @param projection Projection matrix. 219 /// @param inFrustum Frustum to clip. 220 /// @param rootFrustum Frustum corresponding to @a viewport. 221 /// @param outFrustum Resulting clipped frustum. 222 /// 223 /// @return True if the frustum was successfully clipped and @a outFrustum is valid, false otherwise 224 /// (if, for example, the input polygon is completely outside @a inFrustum). 225 bool clipFrustumByPolygon( const Point3F* points, 226 U32 numPoints, 227 const RectI& viewport, 228 const MatrixF& world, 229 const MatrixF& projection, 230 const Frustum& inFrustum, 231 const Frustum& rootFrustum, 232 Frustum& outFrustum ); 233 234 /// Returns true if the test point is within the polygon. 235 /// @param verts The array of points which forms the polygon. 236 /// @param vertCount The number of points in the polygon. 237 /// @param testPt The point to test. 238 bool pointInPolygon( const Point2F *verts, U32 vertCount, const Point2F &testPt ); 239 240 /// Remove all edges from the given polygon that have a total length shorter 241 /// than @a epsilon. 242 /// 243 U32 removeShortPolygonEdges( const Point3F* verts, U32 vertCount, F32 epsilon ); 244 245 /// Calculates the shortest line segment between two lines. 246 /// 247 /// @param outSegment The result where .p0 is the point on line0 and .p1 is the point on line1. 248 /// 249 void mShortestSegmentBetweenLines( const Line &line0, const Line &line1, LineSegment *outSegment ); 250 251 /// Returns the greatest common divisor of two positive integers. 252 U32 greatestCommonDivisor( U32 u, U32 v ); 253 254 /// Returns the barycentric coordinates and time of intersection between 255 /// a line segment and a triangle. 256 /// 257 /// @param p1 The first point of the line segment. 258 /// @param p2 The second point of the line segment. 259 /// @param t1 The first point of the triangle. 260 /// @param t2 The second point of the triangle. 261 /// @param t2 The third point of the triangle. 262 /// @param outUVW The optional output barycentric coords. 263 /// @param outT The optional output time of intersection. 264 /// 265 /// @return Returns true if a collision occurs. 266 /// 267 bool mLineTriangleCollide( const Point3F &p1, const Point3F &p2, 268 const Point3F &t1, const Point3F &t2, const Point3F &t3, 269 Point3F *outUVW = NULL, 270 F32 *outT = NULL ); 271 272 /// Returns the uv coords and time of intersection between 273 /// a ray and a quad. 274 /// 275 /// @param quad The quad. 276 /// @param ray The ray. 277 /// @param outUV The optional output UV coords of the intersection. 278 /// @param outT The optional output time of intersection. 279 /// 280 /// @return Returns true if a collision occurs. 281 /// 282 bool mRayQuadCollide( const Quad &quad, 283 const Ray &ray, 284 Point2F *outUV = NULL, 285 F32 *outT = NULL ); 286 287 /// Returns the distance between a point and triangle 'abc'. 288 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> ); 289 290 /// Returns the normal of the passed triangle 'abc'. 291 /// 292 /// If we assume counter-clockwise triangle culling, normal will point 293 /// out from the 'solid' side of the triangle. 294 /// 295 Point3F mTriangleNormal( const Point3F &a, const Point3F &b, const Point3F &c ); 296 297 /// Returns the closest point on the segment defined by 298 /// points a, b to the point p. 299 Point3F mClosestPointOnSegment( const Point3F &a, 300 const Point3F &b, 301 const Point3F &p ); 302 303 /// Sort the passed verts ( Point3F ) in a clockwise or counter-clockwise winding order. 304 /// Verts must be co-planar and non-collinear. 305 /// 306 /// @param quadMat Transform matrix from vert space to quad space. 307 /// @param clockwise Sort clockwise or counter-clockwise 308 /// @param verts Array of Point3F verts. 309 /// @param vertMap Output - Array of vert element ids sorted by winding order. 310 /// @param count Element count of the verts and vertMap arrays which must be allocated prior to this call. 311 /// 312 void sortQuadWindingOrder( const MatrixF &quadMat, bool clockwise, const Point3F *verts, U32 *vertMap, U32 count ); 313 314 /// Same as above except we assume that the passed verts ( Point3F ) are already 315 /// transformed into 'quad space'. If this was done correctly and the points 316 /// are coplanar this means their z components will all be zero. 317 void sortQuadWindingOrder( bool clockwise, const Point3F *verts, U32 *vertMap, U32 count ); 318 319 /// 320 /// WORK IN PROGRESS 321 /// 322 /// Creates an orthonormal basis matrix from one, two, or three unit length 323 /// input vectors. If more than one input vector is provided they must be 324 /// mutually perpendicular. 325 /// 326 /// @param rvec Optional unit length right vector. 327 /// @param fvec Optional unit length forward vector. 328 /// @param uvec Optional unit length up vector. 329 /// @param pos Optional position to initialize the matrix. 330 /// @param outMat The output matrix which must be initialized prior to the call. 331 /// 332 void buildMatrix( const VectorF *rvec, const VectorF *fvec, const VectorF *uvec, const VectorF *pos, MatrixF *outMat ); 333 334 /// 335 bool reduceFrustum( const Frustum& frustum, const RectI& viewport, const RectF& area, Frustum& outFrustum ); 336 337 /// Build the frustum near plane dimensions from the parameters. 338 void makeFrustum( F32 *outLeft, 339 F32 *outRight, 340 F32 *outTop, 341 F32 *outBottom, 342 F32 fovYInRadians, 343 F32 aspectRatio, 344 F32 nearPlane ); 345 346 void makeFovPortFrustum( Frustum *outFrustum, 347 bool isOrtho, 348 F32 nearDist, 349 F32 farDist, 350 const FovPort &inPort, 351 const MatrixF &transform = MatrixF(1) ); 352 353 /// Build a GFX projection matrix from the frustum parameters 354 /// including the optional rotation required by GFX. 355 void makeProjection( MatrixF *outMatrix, 356 F32 fovYInRadians, 357 F32 aspectRatio, 358 F32 nearPlane, 359 F32 farPlane, 360 bool gfxRotate ); 361 362 /// Build a projection matrix from the frustum near plane dimensions 363 /// including the optional rotation required by GFX. 364 void makeProjection( MatrixF *outMatrix, 365 F32 left, 366 F32 right, 367 F32 top, 368 F32 bottom, 369 F32 nearPlane, 370 F32 farPlane, 371 bool gfxRotate ); 372 373 /// Build an orthographic projection matrix from the frustum near 374 /// plane dimensions including the optional rotation required by GFX. 375 void makeOrthoProjection( MatrixF *outMatrix, 376 F32 left, 377 F32 right, 378 F32 top, 379 F32 bottom, 380 F32 nearPlane, 381 F32 farPlane, 382 bool gfxRotate ); 383 384 /// Find the intersection of the line going from @a edgeA to @a edgeB with the triangle 385 /// given by @a faceA, @a faceB, and @a faceC. 386 /// @param edgeA Starting point of edge. 387 /// @param edgeB End point of edge. 388 /// @param faceA First vertex of triangle. 389 /// @param faceB Second vertex of triangle. 390 /// @param faceC Third vertex of triangle. 391 /// @param intersection If there is an intersection, the point of intersection on the triangle's 392 /// face is stored here. 393 /// @param True if there is an intersection, false otherwise. 394 bool edgeFaceIntersect( const Point3F &edgeA, const Point3F &edgeB, 395 const Point3F &faceA, const Point3F &faceB, const Point3F &faceC, const Point3F &faceD, Point3F *intersection ); 396 397 /// Find out whether the given polygon is planar. 398 /// @param vertices Array of vertices of the polygon. 399 /// @param numVertices Number of vertices in @a vertices. 400 /// @return True if the polygon is planar, false otherwise. 401 bool isPlanarPolygon( const Point3F* vertices, U32 numVertices ); 402 403 /// Find out whether the given polygon is convex. 404 /// @param vertices Array of vertices of the polygon. 405 /// @param numVertices Number of vertices in @a vertices. 406 /// @return True if the polygon is convex, false otherwise. 407 bool isConvexPolygon( const Point3F* vertices, U32 numVertices ); 408 409 /// Extrude the given polygon along the given direction. 410 U32 extrudePolygonEdges( const Point3F* vertices, U32 numVertices, const Point3F& direction, PlaneF* outPlanes ); 411 412 /// Extrude the edges of the given polygon away from @a fromPoint by constructing a set of planes 413 /// that each go through @a fromPoint and a pair of vertices. 414 /// 415 /// The resulting planes are in the same order as the vertices and have their normals facing *inwards*, 416 /// i.e. the resulting volume will enclose the polygon's interior space. 417 /// 418 /// @param vertices Vertices of the polygon in CCW or CW order (both are acceptable). 419 /// @param numVertices Number of vertices in @a vertices. 420 /// @param fromPoint 421 /// @param outPlanes Array in which the resulting planes are stored. Must have room for at least as many 422 /// planes are there are edges in the polygon. 423 /// 424 /// @return 425 /// 426 /// @note The input polygon does not necessarily need to be planar but it must be convex. 427 U32 extrudePolygonEdgesFromPoint( const Point3F* vertices, U32 numVertices, 428 const Point3F& fromPoint, 429 PlaneF* outPlanes ); 430 431 //void findFarthestPoint( const Point3F* points, U32 numPoints, const Point3F& fromPoint, ) 432 433 /// Build a convex hull from a cloud of 2D points, first and last hull point are the same. 434 void mBuildHull2D(const Vector<Point2F> inPoints, Vector<Point2F> &hullPoints); 435 436} // namespace MathUtils 437 438#endif // _MATHUTILS_H_ 439