NvFloatMath.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. #ifndef NV_FLOAT_MATH_H
  2. #define NV_FLOAT_MATH_H
  3. #include "NvUserMemAlloc.h"
  4. // a set of routines that let you do common 3d math
  5. // operations without any vector, matrix, or quaternion
  6. // classes or templates.
  7. //
  8. // a vector (or point) is a 'NxF32 *' to 3 floating point numbers.
  9. // a matrix is a 'NxF32 *' to an array of 16 floating point numbers representing a 4x4 transformation matrix compatible with D3D or OGL
  10. // a quaternion is a 'NxF32 *' to 4 floats representing a quaternion x,y,z,w
  11. //
  12. //
  13. /*!
  14. **
  15. ** Copyright (c) 2009 by John W. Ratcliff mailto:[email protected]
  16. **
  17. ** Portions of this source has been released with the PhysXViewer application, as well as
  18. ** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
  19. **
  20. ** If you find this code useful or you are feeling particularily generous I would
  21. ** ask that you please go to http://www.amillionpixels.us and make a donation
  22. ** to Troy DeMolay.
  23. **
  24. ** DeMolay is a youth group for young men between the ages of 12 and 21.
  25. ** It teaches strong moral principles, as well as leadership skills and
  26. ** public speaking. The donations page uses the 'pay for pixels' paradigm
  27. ** where, in this case, a pixel is only a single penny. Donations can be
  28. ** made for as small as $4 or as high as a $100 block. Each person who donates
  29. ** will get a link to their own site as well as acknowledgement on the
  30. ** donations blog located here http://www.amillionpixels.blogspot.com/
  31. **
  32. ** If you wish to contact me you can use the following methods:
  33. **
  34. ** Skype ID: jratcliff63367
  35. ** Yahoo: jratcliff63367
  36. ** AOL: jratcliff1961
  37. ** email: [email protected]
  38. **
  39. **
  40. ** The MIT license:
  41. **
  42. ** Permission is hereby granted, free of charge, to any person obtaining a copy
  43. ** of this software and associated documentation files (the "Software"), to deal
  44. ** in the Software without restriction, including without limitation the rights
  45. ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  46. ** copies of the Software, and to permit persons to whom the Software is furnished
  47. ** to do so, subject to the following conditions:
  48. **
  49. ** The above copyright notice and this permission notice shall be included in all
  50. ** copies or substantial portions of the Software.
  51. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  52. ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  53. ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  54. ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  55. ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  56. ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  57. */
  58. #include <float.h>
  59. namespace CONVEX_DECOMPOSITION
  60. {
  61. enum FM_ClipState
  62. {
  63. FMCS_XMIN = (1<<0),
  64. FMCS_XMAX = (1<<1),
  65. FMCS_YMIN = (1<<2),
  66. FMCS_YMAX = (1<<3),
  67. FMCS_ZMIN = (1<<4),
  68. FMCS_ZMAX = (1<<5),
  69. };
  70. enum FM_Axis
  71. {
  72. FM_XAXIS = (1<<0),
  73. FM_YAXIS = (1<<1),
  74. FM_ZAXIS = (1<<2)
  75. };
  76. enum LineSegmentType
  77. {
  78. LS_START,
  79. LS_MIDDLE,
  80. LS_END
  81. };
  82. const NxF32 FM_PI = 3.1415926535897932384626433832795028841971693993751f;
  83. const NxF32 FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f);
  84. const NxF32 FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI));
  85. //***************** Float versions
  86. //***
  87. //*** vectors are assumed to be 3 floats or 3 doubles representing X, Y, Z
  88. //*** quaternions are assumed to be 4 floats or 4 doubles representing X,Y,Z,W
  89. //*** matrices are assumed to be 16 floats or 16 doubles representing a standard D3D or OpenGL style 4x4 matrix
  90. //*** bounding volumes are expressed as two sets of 3 floats/NxF64 representing bmin(x,y,z) and bmax(x,y,z)
  91. //*** Plane equations are assumed to be 4 floats or 4 doubles representing Ax,By,Cz,D
  92. FM_Axis fm_getDominantAxis(const NxF32 normal[3]);
  93. FM_Axis fm_getDominantAxis(const NxF64 normal[3]);
  94. void fm_decomposeTransform(const NxF32 local_transform[16],NxF32 trans[3],NxF32 rot[4],NxF32 scale[3]);
  95. void fm_decomposeTransform(const NxF64 local_transform[16],NxF64 trans[3],NxF64 rot[4],NxF64 scale[3]);
  96. void fm_multiplyTransform(const NxF32 *pA,const NxF32 *pB,NxF32 *pM);
  97. void fm_multiplyTransform(const NxF64 *pA,const NxF64 *pB,NxF64 *pM);
  98. void fm_inverseTransform(const NxF32 matrix[16],NxF32 inverse_matrix[16]);
  99. void fm_inverseTransform(const NxF64 matrix[16],NxF64 inverse_matrix[16]);
  100. void fm_identity(NxF32 matrix[16]); // set 4x4 matrix to identity.
  101. void fm_identity(NxF64 matrix[16]); // set 4x4 matrix to identity.
  102. void fm_inverseRT(const NxF32 matrix[16], const NxF32 pos[3], NxF32 t[3]); // inverse rotate translate the point.
  103. void fm_inverseRT(const NxF64 matrix[16],const NxF64 pos[3],NxF64 t[3]); // inverse rotate translate the point.
  104. void fm_transform(const NxF32 matrix[16], const NxF32 pos[3], NxF32 t[3]); // rotate and translate this point.
  105. void fm_transform(const NxF64 matrix[16],const NxF64 pos[3],NxF64 t[3]); // rotate and translate this point.
  106. NxF32 fm_getDeterminant(const NxF32 matrix[16]);
  107. NxF64 fm_getDeterminant(const NxF64 matrix[16]);
  108. void fm_getSubMatrix(NxI32 ki,NxI32 kj,NxF32 pDst[16],const NxF32 matrix[16]);
  109. void fm_getSubMatrix(NxI32 ki,NxI32 kj,NxF64 pDst[16],const NxF32 matrix[16]);
  110. void fm_rotate(const NxF32 matrix[16],const NxF32 pos[3],NxF32 t[3]); // only rotate the point by a 4x4 matrix, don't translate.
  111. void fm_rotate(const NxF64 matri[16],const NxF64 pos[3],NxF64 t[3]); // only rotate the point by a 4x4 matrix, don't translate.
  112. void fm_eulerToMatrix(NxF32 ax,NxF32 ay,NxF32 az,NxF32 matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  113. void fm_eulerToMatrix(NxF64 ax,NxF64 ay,NxF64 az,NxF64 matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  114. void fm_getAABB(NxU32 vcount,const NxF32 *points,NxU32 pstride,NxF32 bmin[3],NxF32 bmax[3]);
  115. void fm_getAABB(NxU32 vcount,const NxF64 *points,NxU32 pstride,NxF64 bmin[3],NxF64 bmax[3]);
  116. void fm_getAABBCenter(const NxF32 bmin[3],const NxF32 bmax[3],NxF32 center[3]);
  117. void fm_getAABBCenter(const NxF64 bmin[3],const NxF64 bmax[3],NxF64 center[3]);
  118. void fm_eulerToQuat(NxF32 x,NxF32 y,NxF32 z,NxF32 quat[4]); // convert euler angles to quaternion.
  119. void fm_eulerToQuat(NxF64 x,NxF64 y,NxF64 z,NxF64 quat[4]); // convert euler angles to quaternion.
  120. void fm_quatToEuler(const NxF32 quat[4],NxF32 &ax,NxF32 &ay,NxF32 &az);
  121. void fm_quatToEuler(const NxF64 quat[4],NxF64 &ax,NxF64 &ay,NxF64 &az);
  122. void fm_eulerToQuat(const NxF32 euler[3],NxF32 quat[4]); // convert euler angles to quaternion. Angles must be radians not degrees!
  123. void fm_eulerToQuat(const NxF64 euler[3],NxF64 quat[4]); // convert euler angles to quaternion.
  124. void fm_scale(NxF32 x,NxF32 y,NxF32 z,NxF32 matrix[16]); // apply scale to the matrix.
  125. void fm_scale(NxF64 x,NxF64 y,NxF64 z,NxF64 matrix[16]); // apply scale to the matrix.
  126. void fm_eulerToQuatDX(NxF32 x,NxF32 y,NxF32 z,NxF32 quat[4]); // convert euler angles to quaternion using the fucked up DirectX method
  127. void fm_eulerToQuatDX(NxF64 x,NxF64 y,NxF64 z,NxF64 quat[4]); // convert euler angles to quaternion using the fucked up DirectX method
  128. void fm_eulerToMatrixDX(NxF32 x,NxF32 y,NxF32 z,NxF32 matrix[16]); // convert euler angles to quaternion using the fucked up DirectX method.
  129. void fm_eulerToMatrixDX(NxF64 x,NxF64 y,NxF64 z,NxF64 matrix[16]); // convert euler angles to quaternion using the fucked up DirectX method.
  130. void fm_quatToMatrix(const NxF32 quat[4],NxF32 matrix[16]); // convert quaterinion rotation to matrix, translation set to zero.
  131. void fm_quatToMatrix(const NxF64 quat[4],NxF64 matrix[16]); // convert quaterinion rotation to matrix, translation set to zero.
  132. void fm_quatRotate(const NxF32 quat[4],const NxF32 v[3],NxF32 r[3]); // rotate a vector directly by a quaternion.
  133. void fm_quatRotate(const NxF64 quat[4],const NxF64 v[3],NxF64 r[3]); // rotate a vector directly by a quaternion.
  134. void fm_getTranslation(const NxF32 matrix[16],NxF32 t[3]);
  135. void fm_getTranslation(const NxF64 matrix[16],NxF64 t[3]);
  136. void fm_setTranslation(const NxF32 *translation,NxF32 matrix[16]);
  137. void fm_setTranslation(const NxF64 *translation,NxF64 matrix[16]);
  138. void fm_multiplyQuat(const NxF32 *qa,const NxF32 *qb,NxF32 *quat);
  139. void fm_multiplyQuat(const NxF64 *qa,const NxF64 *qb,NxF64 *quat);
  140. void fm_matrixToQuat(const NxF32 matrix[16],NxF32 quat[4]); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
  141. void fm_matrixToQuat(const NxF64 matrix[16],NxF64 quat[4]); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
  142. NxF32 fm_sphereVolume(NxF32 radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
  143. NxF64 fm_sphereVolume(NxF64 radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
  144. NxF32 fm_cylinderVolume(NxF32 radius,NxF32 h);
  145. NxF64 fm_cylinderVolume(NxF64 radius,NxF64 h);
  146. NxF32 fm_capsuleVolume(NxF32 radius,NxF32 h);
  147. NxF64 fm_capsuleVolume(NxF64 radius,NxF64 h);
  148. NxF32 fm_distance(const NxF32 p1[3],const NxF32 p2[3]);
  149. NxF64 fm_distance(const NxF64 p1[3],const NxF64 p2[3]);
  150. NxF32 fm_distanceSquared(const NxF32 p1[3],const NxF32 p2[3]);
  151. NxF64 fm_distanceSquared(const NxF64 p1[3],const NxF64 p2[3]);
  152. NxF32 fm_distanceSquaredXZ(const NxF32 p1[3],const NxF32 p2[3]);
  153. NxF64 fm_distanceSquaredXZ(const NxF64 p1[3],const NxF64 p2[3]);
  154. NxF32 fm_computePlane(const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3],NxF32 *n); // return D
  155. NxF64 fm_computePlane(const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3],NxF64 *n); // return D
  156. NxF32 fm_distToPlane(const NxF32 plane[4],const NxF32 pos[3]); // computes the distance of this point from the plane.
  157. NxF64 fm_distToPlane(const NxF64 plane[4],const NxF64 pos[3]); // computes the distance of this point from the plane.
  158. NxF32 fm_dot(const NxF32 p1[3],const NxF32 p2[3]);
  159. NxF64 fm_dot(const NxF64 p1[3],const NxF64 p2[3]);
  160. void fm_cross(NxF32 cross[3],const NxF32 a[3],const NxF32 b[3]);
  161. void fm_cross(NxF64 cross[3],const NxF64 a[3],const NxF64 b[3]);
  162. void fm_computeNormalVector(NxF32 n[3],const NxF32 p1[3],const NxF32 p2[3]); // as P2-P1 normalized.
  163. void fm_computeNormalVector(NxF64 n[3],const NxF64 p1[3],const NxF64 p2[3]); // as P2-P1 normalized.
  164. bool fm_computeWindingOrder(const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3]); // returns true if the triangle is clockwise.
  165. bool fm_computeWindingOrder(const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3]); // returns true if the triangle is clockwise.
  166. NxF32 fm_normalize(NxF32 n[3]); // normalize this vector and return the distance
  167. NxF64 fm_normalize(NxF64 n[3]); // normalize this vector and return the distance
  168. void fm_matrixMultiply(const NxF32 A[16],const NxF32 B[16],NxF32 dest[16]);
  169. void fm_matrixMultiply(const NxF64 A[16],const NxF64 B[16],NxF64 dest[16]);
  170. void fm_composeTransform(const NxF32 position[3],const NxF32 quat[4],const NxF32 scale[3],NxF32 matrix[16]);
  171. void fm_composeTransform(const NxF64 position[3],const NxF64 quat[4],const NxF64 scale[3],NxF64 matrix[16]);
  172. NxF32 fm_computeArea(const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3]);
  173. NxF64 fm_computeArea(const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3]);
  174. void fm_lerp(const NxF32 p1[3],const NxF32 p2[3],NxF32 dest[3],NxF32 lerpValue);
  175. void fm_lerp(const NxF64 p1[3],const NxF64 p2[3],NxF64 dest[3],NxF64 lerpValue);
  176. bool fm_insideTriangleXZ(const NxF32 test[3],const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3]);
  177. bool fm_insideTriangleXZ(const NxF64 test[3],const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3]);
  178. bool fm_insideAABB(const NxF32 pos[3],const NxF32 bmin[3],const NxF32 bmax[3]);
  179. bool fm_insideAABB(const NxF64 pos[3],const NxF64 bmin[3],const NxF64 bmax[3]);
  180. bool fm_insideAABB(const NxF32 obmin[3],const NxF32 obmax[3],const NxF32 tbmin[3],const NxF32 tbmax[3]); // test if bounding box tbmin/tmbax is fully inside obmin/obmax
  181. bool fm_insideAABB(const NxF64 obmin[3],const NxF64 obmax[3],const NxF64 tbmin[3],const NxF64 tbmax[3]); // test if bounding box tbmin/tmbax is fully inside obmin/obmax
  182. NxU32 fm_clipTestPoint(const NxF32 bmin[3],const NxF32 bmax[3],const NxF32 pos[3]);
  183. NxU32 fm_clipTestPoint(const NxF64 bmin[3],const NxF64 bmax[3],const NxF64 pos[3]);
  184. NxU32 fm_clipTestPointXZ(const NxF32 bmin[3],const NxF32 bmax[3],const NxF32 pos[3]); // only tests X and Z, not Y
  185. NxU32 fm_clipTestPointXZ(const NxF64 bmin[3],const NxF64 bmax[3],const NxF64 pos[3]); // only tests X and Z, not Y
  186. NxU32 fm_clipTestAABB(const NxF32 bmin[3],const NxF32 bmax[3],const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3],NxU32 &andCode);
  187. NxU32 fm_clipTestAABB(const NxF64 bmin[3],const NxF64 bmax[3],const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3],NxU32 &andCode);
  188. bool fm_lineTestAABBXZ(const NxF32 p1[3],const NxF32 p2[3],const NxF32 bmin[3],const NxF32 bmax[3],NxF32 &time);
  189. bool fm_lineTestAABBXZ(const NxF64 p1[3],const NxF64 p2[3],const NxF64 bmin[3],const NxF64 bmax[3],NxF64 &time);
  190. bool fm_lineTestAABB(const NxF32 p1[3],const NxF32 p2[3],const NxF32 bmin[3],const NxF32 bmax[3],NxF32 &time);
  191. bool fm_lineTestAABB(const NxF64 p1[3],const NxF64 p2[3],const NxF64 bmin[3],const NxF64 bmax[3],NxF64 &time);
  192. void fm_initMinMax(const NxF32 p[3],NxF32 bmin[3],NxF32 bmax[3]);
  193. void fm_initMinMax(const NxF64 p[3],NxF64 bmin[3],NxF64 bmax[3]);
  194. void fm_initMinMax(NxF32 bmin[3],NxF32 bmax[3]);
  195. void fm_initMinMax(NxF64 bmin[3],NxF64 bmax[3]);
  196. void fm_minmax(const NxF32 p[3],NxF32 bmin[3],NxF32 bmax[3]); // accmulate to a min-max value
  197. void fm_minmax(const NxF64 p[3],NxF64 bmin[3],NxF64 bmax[3]); // accmulate to a min-max value
  198. NxF32 fm_solveX(const NxF32 plane[4],NxF32 y,NxF32 z); // solve for X given this plane equation and the other two components.
  199. NxF64 fm_solveX(const NxF64 plane[4],NxF64 y,NxF64 z); // solve for X given this plane equation and the other two components.
  200. NxF32 fm_solveY(const NxF32 plane[4],NxF32 x,NxF32 z); // solve for Y given this plane equation and the other two components.
  201. NxF64 fm_solveY(const NxF64 plane[4],NxF64 x,NxF64 z); // solve for Y given this plane equation and the other two components.
  202. NxF32 fm_solveZ(const NxF32 plane[4],NxF32 x,NxF32 y); // solve for Z given this plane equation and the other two components.
  203. NxF64 fm_solveZ(const NxF64 plane[4],NxF64 x,NxF64 y); // solve for Z given this plane equation and the other two components.
  204. bool fm_computeBestFitPlane(NxU32 vcount, // number of input data points
  205. const NxF32 *points, // starting address of points array.
  206. NxU32 vstride, // stride between input points.
  207. const NxF32 *weights, // *optional point weighting values.
  208. NxU32 wstride, // weight stride for each vertex.
  209. NxF32 plane[4]);
  210. bool fm_computeBestFitPlane(NxU32 vcount, // number of input data points
  211. const NxF64 *points, // starting address of points array.
  212. NxU32 vstride, // stride between input points.
  213. const NxF64 *weights, // *optional point weighting values.
  214. NxU32 wstride, // weight stride for each vertex.
  215. NxF64 plane[4]);
  216. NxF32 fm_computeBestFitAABB(NxU32 vcount,const NxF32 *points,NxU32 pstride,NxF32 bmin[3],NxF32 bmax[3]); // returns the diagonal distance
  217. NxF64 fm_computeBestFitAABB(NxU32 vcount,const NxF64 *points,NxU32 pstride,NxF64 bmin[3],NxF64 bmax[3]); // returns the diagonal distance
  218. NxF32 fm_computeBestFitSphere(NxU32 vcount,const NxF32 *points,NxU32 pstride,NxF32 center[3]);
  219. NxF64 fm_computeBestFitSphere(NxU32 vcount,const NxF64 *points,NxU32 pstride,NxF64 center[3]);
  220. bool fm_lineSphereIntersect(const NxF32 center[3],NxF32 radius,const NxF32 p1[3],const NxF32 p2[3],NxF32 intersect[3]);
  221. bool fm_lineSphereIntersect(const NxF64 center[3],NxF64 radius,const NxF64 p1[3],const NxF64 p2[3],NxF64 intersect[3]);
  222. bool fm_intersectRayAABB(const NxF32 bmin[3],const NxF32 bmax[3],const NxF32 pos[3],const NxF32 dir[3],NxF32 intersect[3]);
  223. bool fm_intersectLineSegmentAABB(const NxF32 bmin[3],const NxF32 bmax[3],const NxF32 p1[3],const NxF32 p2[3],NxF32 intersect[3]);
  224. bool fm_lineIntersectsTriangle(const NxF32 rayStart[3],const NxF32 rayEnd[3],const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3],NxF32 sect[3]);
  225. bool fm_lineIntersectsTriangle(const NxF64 rayStart[3],const NxF64 rayEnd[3],const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3],NxF64 sect[3]);
  226. bool fm_rayIntersectsTriangle(const NxF32 origin[3],const NxF32 dir[3],const NxF32 v0[3],const NxF32 v1[3],const NxF32 v2[3],NxF32 &t);
  227. bool fm_rayIntersectsTriangle(const NxF64 origin[3],const NxF64 dir[3],const NxF64 v0[3],const NxF64 v1[3],const NxF64 v2[3],NxF64 &t);
  228. bool fm_raySphereIntersect(const NxF32 center[3],NxF32 radius,const NxF32 pos[3],const NxF32 dir[3],NxF32 distance,NxF32 intersect[3]);
  229. bool fm_raySphereIntersect(const NxF64 center[3],NxF64 radius,const NxF64 pos[3],const NxF64 dir[3],NxF64 distance,NxF64 intersect[3]);
  230. void fm_catmullRom(NxF32 out_vector[3],const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3],const NxF32 *p4, const NxF32 s);
  231. void fm_catmullRom(NxF64 out_vector[3],const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3],const NxF64 *p4, const NxF64 s);
  232. bool fm_intersectAABB(const NxF32 bmin1[3],const NxF32 bmax1[3],const NxF32 bmin2[3],const NxF32 bmax2[3]);
  233. bool fm_intersectAABB(const NxF64 bmin1[3],const NxF64 bmax1[3],const NxF64 bmin2[3],const NxF64 bmax2[3]);
  234. // computes the rotation quaternion to go from unit-vector v0 to unit-vector v1
  235. void fm_rotationArc(const NxF32 v0[3],const NxF32 v1[3],NxF32 quat[4]);
  236. void fm_rotationArc(const NxF64 v0[3],const NxF64 v1[3],NxF64 quat[4]);
  237. NxF32 fm_distancePointLineSegment(const NxF32 Point[3],const NxF32 LineStart[3],const NxF32 LineEnd[3],NxF32 intersection[3],LineSegmentType &type,NxF32 epsilon);
  238. NxF64 fm_distancePointLineSegment(const NxF64 Point[3],const NxF64 LineStart[3],const NxF64 LineEnd[3],NxF64 intersection[3],LineSegmentType &type,NxF64 epsilon);
  239. bool fm_colinear(const NxF64 p1[3],const NxF64 p2[3],const NxF64 p3[3],NxF64 epsilon=0.999); // true if these three points in a row are co-linear
  240. bool fm_colinear(const NxF32 p1[3],const NxF32 p2[3],const NxF32 p3[3],NxF32 epsilon=0.999f);
  241. bool fm_colinear(const NxF32 a1[3],const NxF32 a2[3],const NxF32 b1[3],const NxF32 b2[3],NxF32 epsilon=0.999f); // true if these two line segments are co-linear.
  242. bool fm_colinear(const NxF64 a1[3],const NxF64 a2[3],const NxF64 b1[3],const NxF64 b2[3],NxF64 epsilon=0.999); // true if these two line segments are co-linear.
  243. enum IntersectResult
  244. {
  245. IR_DONT_INTERSECT,
  246. IR_DO_INTERSECT,
  247. IR_COINCIDENT,
  248. IR_PARALLEL,
  249. };
  250. IntersectResult fm_intersectLineSegments2d(const NxF32 a1[3], const NxF32 a2[3], const NxF32 b1[3], const NxF32 b2[3], NxF32 intersectionPoint[3]);
  251. IntersectResult fm_intersectLineSegments2d(const NxF64 a1[3],const NxF64 a2[3],const NxF64 b1[3],const NxF64 b2[3],NxF64 intersectionPoint[3]);
  252. IntersectResult fm_intersectLineSegments2dTime(const NxF32 a1[3], const NxF32 a2[3], const NxF32 b1[3], const NxF32 b2[3],NxF32 &t1,NxF32 &t2);
  253. IntersectResult fm_intersectLineSegments2dTime(const NxF64 a1[3],const NxF64 a2[3],const NxF64 b1[3],const NxF64 b2[3],NxF64 &t1,NxF64 &t2);
  254. // Plane-Triangle splitting
  255. enum PlaneTriResult
  256. {
  257. PTR_ON_PLANE,
  258. PTR_FRONT,
  259. PTR_BACK,
  260. PTR_SPLIT,
  261. };
  262. PlaneTriResult fm_planeTriIntersection(const NxF32 plane[4], // the plane equation in Ax+By+Cz+D format
  263. const NxF32 *triangle, // the source triangle.
  264. NxU32 tstride, // stride in bytes of the input and output *vertices*
  265. NxF32 epsilon, // the co-planer epsilon value.
  266. NxF32 *front, // the triangle in front of the
  267. NxU32 &fcount, // number of vertices in the 'front' triangle
  268. NxF32 *back, // the triangle in back of the plane
  269. NxU32 &bcount); // the number of vertices in the 'back' triangle.
  270. PlaneTriResult fm_planeTriIntersection(const NxF64 plane[4], // the plane equation in Ax+By+Cz+D format
  271. const NxF64 *triangle, // the source triangle.
  272. NxU32 tstride, // stride in bytes of the input and output *vertices*
  273. NxF64 epsilon, // the co-planer epsilon value.
  274. NxF64 *front, // the triangle in front of the
  275. NxU32 &fcount, // number of vertices in the 'front' triangle
  276. NxF64 *back, // the triangle in back of the plane
  277. NxU32 &bcount); // the number of vertices in the 'back' triangle.
  278. void fm_intersectPointPlane(const NxF32 p1[3],const NxF32 p2[3],NxF32 *split,const NxF32 plane[4]);
  279. void fm_intersectPointPlane(const NxF64 p1[3],const NxF64 p2[3],NxF64 *split,const NxF64 plane[4]);
  280. PlaneTriResult fm_getSidePlane(const NxF32 p[3],const NxF32 plane[4],NxF32 epsilon);
  281. PlaneTriResult fm_getSidePlane(const NxF64 p[3],const NxF64 plane[4],NxF64 epsilon);
  282. void fm_computeBestFitOBB(NxU32 vcount,const NxF32 *points,NxU32 pstride,NxF32 *sides,NxF32 matrix[16],bool bruteForce=true);
  283. void fm_computeBestFitOBB(NxU32 vcount,const NxF64 *points,NxU32 pstride,NxF64 *sides,NxF64 matrix[16],bool bruteForce=true);
  284. void fm_computeBestFitOBB(NxU32 vcount,const NxF32 *points,NxU32 pstride,NxF32 *sides,NxF32 pos[3],NxF32 quat[4],bool bruteForce=true);
  285. void fm_computeBestFitOBB(NxU32 vcount,const NxF64 *points,NxU32 pstride,NxF64 *sides,NxF64 pos[3],NxF64 quat[4],bool bruteForce=true);
  286. void fm_computeBestFitABB(NxU32 vcount,const NxF32 *points,NxU32 pstride,NxF32 *sides,NxF32 pos[3]);
  287. void fm_computeBestFitABB(NxU32 vcount,const NxF64 *points,NxU32 pstride,NxF64 *sides,NxF64 pos[3]);
  288. //** Note, if the returned capsule height is less than zero, then you must represent it is a sphere of size radius.
  289. void fm_computeBestFitCapsule(NxU32 vcount,const NxF32 *points,NxU32 pstride,NxF32 &radius,NxF32 &height,NxF32 matrix[16],bool bruteForce=true);
  290. void fm_computeBestFitCapsule(NxU32 vcount,const NxF64 *points,NxU32 pstride,NxF32 &radius,NxF32 &height,NxF64 matrix[16],bool bruteForce=true);
  291. void fm_planeToMatrix(const NxF32 plane[4],NxF32 matrix[16]); // convert a plane equation to a 4x4 rotation matrix. Reference vector is 0,1,0
  292. void fm_planeToQuat(const NxF32 plane[4],NxF32 quat[4],NxF32 pos[3]); // convert a plane equation to a quaternion and translation
  293. void fm_planeToMatrix(const NxF64 plane[4],NxF64 matrix[16]); // convert a plane equation to a 4x4 rotation matrix
  294. void fm_planeToQuat(const NxF64 plane[4],NxF64 quat[4],NxF64 pos[3]); // convert a plane equation to a quaternion and translation
  295. inline void fm_doubleToFloat3(const NxF64 p[3],NxF32 t[3]) { t[0] = (NxF32) p[0]; t[1] = (NxF32)p[1]; t[2] = (NxF32)p[2]; };
  296. inline void fm_floatToDouble3(const NxF32 p[3],NxF64 t[3]) { t[0] = (NxF64)p[0]; t[1] = (NxF64)p[1]; t[2] = (NxF64)p[2]; };
  297. void fm_eulerMatrix(NxF32 ax,NxF32 ay,NxF32 az,NxF32 matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  298. void fm_eulerMatrix(NxF64 ax,NxF64 ay,NxF64 az,NxF64 matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  299. NxF32 fm_computeMeshVolume(const NxF32 *vertices,NxU32 tcount,const NxU32 *indices);
  300. NxF64 fm_computeMeshVolume(const NxF64 *vertices,NxU32 tcount,const NxU32 *indices);
  301. #define FM_DEFAULT_GRANULARITY 0.001f // 1 millimeter is the default granularity
  302. class fm_VertexIndex
  303. {
  304. public:
  305. virtual NxU32 getIndex(const NxF32 pos[3],bool &newPos) = 0; // get welded index for this NxF32 vector[3]
  306. virtual NxU32 getIndex(const NxF64 pos[3],bool &newPos) = 0; // get welded index for this NxF64 vector[3]
  307. virtual const NxF32 * getVerticesFloat(void) const = 0;
  308. virtual const NxF64 * getVerticesDouble(void) const = 0;
  309. virtual const NxF32 * getVertexFloat(NxU32 index) const = 0;
  310. virtual const NxF64 * getVertexDouble(NxU32 index) const = 0;
  311. virtual NxU32 getVcount(void) const = 0;
  312. virtual bool isDouble(void) const = 0;
  313. virtual bool saveAsObj(const char *fname,NxU32 tcount,NxU32 *indices) = 0;
  314. };
  315. fm_VertexIndex * fm_createVertexIndex(NxF64 granularity,bool snapToGrid); // create an indexed vertex system for doubles
  316. fm_VertexIndex * fm_createVertexIndex(NxF32 granularity,bool snapToGrid); // create an indexed vertext system for floats
  317. void fm_releaseVertexIndex(fm_VertexIndex *vindex);
  318. #if 0 // currently disabled
  319. class fm_LineSegment
  320. {
  321. public:
  322. fm_LineSegment(void)
  323. {
  324. mE1 = mE2 = 0;
  325. }
  326. fm_LineSegment(NxU32 e1,NxU32 e2)
  327. {
  328. mE1 = e1;
  329. mE2 = e2;
  330. }
  331. NxU32 mE1;
  332. NxU32 mE2;
  333. };
  334. // LineSweep *only* supports doublees. As a geometric operation it needs as much precision as possible.
  335. class fm_LineSweep
  336. {
  337. public:
  338. virtual fm_LineSegment * performLineSweep(const fm_LineSegment *segments,
  339. NxU32 icount,
  340. const NxF64 *planeEquation,
  341. fm_VertexIndex *pool,
  342. NxU32 &scount) = 0;
  343. };
  344. fm_LineSweep * fm_createLineSweep(void);
  345. void fm_releaseLineSweep(fm_LineSweep *sweep);
  346. #endif
  347. class fm_Triangulate
  348. {
  349. public:
  350. virtual const NxF64 * triangulate3d(NxU32 pcount,
  351. const NxF64 *points,
  352. NxU32 vstride,
  353. NxU32 &tcount,
  354. bool consolidate,
  355. NxF64 epsilon) = 0;
  356. virtual const NxF32 * triangulate3d(NxU32 pcount,
  357. const NxF32 *points,
  358. NxU32 vstride,
  359. NxU32 &tcount,
  360. bool consolidate,
  361. NxF32 epsilon) = 0;
  362. };
  363. fm_Triangulate * fm_createTriangulate(void);
  364. void fm_releaseTriangulate(fm_Triangulate *t);
  365. const NxF32 * fm_getPoint(const NxF32 *points,NxU32 pstride,NxU32 index);
  366. const NxF64 * fm_getPoint(const NxF64 *points,NxU32 pstride,NxU32 index);
  367. bool fm_insideTriangle(NxF32 Ax, NxF32 Ay,NxF32 Bx, NxF32 By,NxF32 Cx, NxF32 Cy,NxF32 Px, NxF32 Py);
  368. bool fm_insideTriangle(NxF64 Ax, NxF64 Ay,NxF64 Bx, NxF64 By,NxF64 Cx, NxF64 Cy,NxF64 Px, NxF64 Py);
  369. NxF32 fm_areaPolygon2d(NxU32 pcount,const NxF32 *points,NxU32 pstride);
  370. NxF64 fm_areaPolygon2d(NxU32 pcount,const NxF64 *points,NxU32 pstride);
  371. bool fm_pointInsidePolygon2d(NxU32 pcount,const NxF32 *points,NxU32 pstride,const NxF32 *point,NxU32 xindex=0,NxU32 yindex=1);
  372. bool fm_pointInsidePolygon2d(NxU32 pcount,const NxF64 *points,NxU32 pstride,const NxF64 *point,NxU32 xindex=0,NxU32 yindex=1);
  373. NxU32 fm_consolidatePolygon(NxU32 pcount,const NxF32 *points,NxU32 pstride,NxF32 *dest,NxF32 epsilon=0.999999f); // collapses co-linear edges.
  374. NxU32 fm_consolidatePolygon(NxU32 pcount,const NxF64 *points,NxU32 pstride,NxF64 *dest,NxF64 epsilon=0.999999); // collapses co-linear edges.
  375. bool fm_computeSplitPlane(NxU32 vcount,const NxF64 *vertices,NxU32 tcount,const NxU32 *indices,NxF64 *plane);
  376. bool fm_computeSplitPlane(NxU32 vcount,const NxF32 *vertices,NxU32 tcount,const NxU32 *indices,NxF32 *plane);
  377. void fm_nearestPointInTriangle(const NxF32 *pos,const NxF32 *p1,const NxF32 *p2,const NxF32 *p3,NxF32 *nearest);
  378. void fm_nearestPointInTriangle(const NxF64 *pos,const NxF64 *p1,const NxF64 *p2,const NxF64 *p3,NxF64 *nearest);
  379. NxF32 fm_areaTriangle(const NxF32 *p1,const NxF32 *p2,const NxF32 *p3);
  380. NxF64 fm_areaTriangle(const NxF64 *p1,const NxF64 *p2,const NxF64 *p3);
  381. void fm_subtract(const NxF32 *A,const NxF32 *B,NxF32 *diff); // compute A-B and store the result in 'diff'
  382. void fm_subtract(const NxF64 *A,const NxF64 *B,NxF64 *diff); // compute A-B and store the result in 'diff'
  383. void fm_multiply(NxF32 *A,NxF32 scaler);
  384. void fm_multiply(NxF64 *A,NxF64 scaler);
  385. void fm_add(const NxF32 *A,const NxF32 *B,NxF32 *sum);
  386. void fm_add(const NxF64 *A,const NxF64 *B,NxF64 *sum);
  387. void fm_copy3(const NxF32 *source,NxF32 *dest);
  388. void fm_copy3(const NxF64 *source,NxF64 *dest);
  389. // re-indexes an indexed triangle mesh but drops unused vertices. The output_indices can be the same pointer as the input indices.
  390. // the output_vertices can point to the input vertices if you desire. The output_vertices buffer should be at least the same size
  391. // is the input buffer. The routine returns the new vertex count after re-indexing.
  392. NxU32 fm_copyUniqueVertices(NxU32 vcount,const NxF32 *input_vertices,NxF32 *output_vertices,NxU32 tcount,const NxU32 *input_indices,NxU32 *output_indices);
  393. NxU32 fm_copyUniqueVertices(NxU32 vcount,const NxF64 *input_vertices,NxF64 *output_vertices,NxU32 tcount,const NxU32 *input_indices,NxU32 *output_indices);
  394. bool fm_isMeshCoplanar(NxU32 tcount,const NxU32 *indices,const NxF32 *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
  395. bool fm_isMeshCoplanar(NxU32 tcount,const NxU32 *indices,const NxF64 *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
  396. bool fm_samePlane(const NxF32 p1[4],const NxF32 p2[4],NxF32 normalEpsilon=0.01f,NxF32 dEpsilon=0.001f,bool doubleSided=false); // returns true if these two plane equations are identical within an epsilon
  397. bool fm_samePlane(const NxF64 p1[4],const NxF64 p2[4],NxF64 normalEpsilon=0.01,NxF64 dEpsilon=0.001,bool doubleSided=false);
  398. void fm_OBBtoAABB(const NxF32 obmin[3],const NxF32 obmax[3],const NxF32 matrix[16],NxF32 abmin[3],NxF32 abmax[3]);
  399. // a utility class that will tesseleate a mesh.
  400. class fm_Tesselate
  401. {
  402. public:
  403. virtual const NxU32 * tesselate(fm_VertexIndex *vindex,NxU32 tcount,const NxU32 *indices,NxF32 longEdge,NxU32 maxDepth,NxU32 &outcount) = 0;
  404. };
  405. fm_Tesselate * fm_createTesselate(void);
  406. void fm_releaseTesselate(fm_Tesselate *t);
  407. void fm_computeMeanNormals(NxU32 vcount, // the number of vertices
  408. const NxF32 *vertices, // the base address of the vertex position data.
  409. NxU32 vstride, // the stride between position data.
  410. NxF32 *normals, // the base address of the destination for mean vector normals
  411. NxU32 nstride, // the stride between normals
  412. NxU32 tcount, // the number of triangles
  413. const NxU32 *indices); // the triangle indices
  414. void fm_computeMeanNormals(NxU32 vcount, // the number of vertices
  415. const NxF64 *vertices, // the base address of the vertex position data.
  416. NxU32 vstride, // the stride between position data.
  417. NxF64 *normals, // the base address of the destination for mean vector normals
  418. NxU32 nstride, // the stride between normals
  419. NxU32 tcount, // the number of triangles
  420. const NxU32 *indices); // the triangle indices
  421. bool fm_isValidTriangle(const NxF32 *p1,const NxF32 *p2,const NxF32 *p3,NxF32 epsilon=0.00001f);
  422. bool fm_isValidTriangle(const NxF64 *p1,const NxF64 *p2,const NxF64 *p3,NxF64 epsilon=0.00001f);
  423. }; // end of namespace
  424. #endif