FloatMath.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. #ifndef FLOAT_MATH_LIB_H
  2. #define FLOAT_MATH_LIB_H
  3. #include <float.h>
  4. #include <stdint.h>
  5. namespace FLOAT_MATH
  6. {
  7. enum FM_ClipState
  8. {
  9. FMCS_XMIN = (1<<0),
  10. FMCS_XMAX = (1<<1),
  11. FMCS_YMIN = (1<<2),
  12. FMCS_YMAX = (1<<3),
  13. FMCS_ZMIN = (1<<4),
  14. FMCS_ZMAX = (1<<5),
  15. };
  16. enum FM_Axis
  17. {
  18. FM_XAXIS = (1<<0),
  19. FM_YAXIS = (1<<1),
  20. FM_ZAXIS = (1<<2)
  21. };
  22. enum LineSegmentType
  23. {
  24. LS_START,
  25. LS_MIDDLE,
  26. LS_END
  27. };
  28. const float FM_PI = 3.1415926535897932384626433832795028841971693993751f;
  29. const float FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f);
  30. const float FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI));
  31. //***************** Float versions
  32. //***
  33. //*** vectors are assumed to be 3 floats or 3 doubles representing X, Y, Z
  34. //*** quaternions are assumed to be 4 floats or 4 doubles representing X,Y,Z,W
  35. //*** matrices are assumed to be 16 floats or 16 doubles representing a standard D3D or OpenGL style 4x4 matrix
  36. //*** bounding volumes are expressed as two sets of 3 floats/double representing bmin(x,y,z) and bmax(x,y,z)
  37. //*** Plane equations are assumed to be 4 floats or 4 doubles representing Ax,By,Cz,D
  38. FM_Axis fm_getDominantAxis(const float normal[3]);
  39. FM_Axis fm_getDominantAxis(const double normal[3]);
  40. void fm_decomposeTransform(const float local_transform[16],float trans[3],float rot[4],float scale[3]);
  41. void fm_decomposeTransform(const double local_transform[16],double trans[3],double rot[4],double scale[3]);
  42. void fm_multiplyTransform(const float *pA,const float *pB,float *pM);
  43. void fm_multiplyTransform(const double *pA,const double *pB,double *pM);
  44. void fm_inverseTransform(const float matrix[16],float inverse_matrix[16]);
  45. void fm_inverseTransform(const double matrix[16],double inverse_matrix[16]);
  46. void fm_identity(float matrix[16]); // set 4x4 matrix to identity.
  47. void fm_identity(double matrix[16]); // set 4x4 matrix to identity.
  48. void fm_inverseRT(const float matrix[16], const float pos[3], float t[3]); // inverse rotate translate the point.
  49. void fm_inverseRT(const double matrix[16],const double pos[3],double t[3]); // inverse rotate translate the point.
  50. void fm_transform(const float matrix[16], const float pos[3], float t[3]); // rotate and translate this point.
  51. void fm_transform(const double matrix[16],const double pos[3],double t[3]); // rotate and translate this point.
  52. float fm_getDeterminant(const float matrix[16]);
  53. double fm_getDeterminant(const double matrix[16]);
  54. void fm_getSubMatrix(int32_t ki,int32_t kj,float pDst[16],const float matrix[16]);
  55. void fm_getSubMatrix(int32_t ki,int32_t kj,double pDst[16],const float matrix[16]);
  56. void fm_rotate(const float matrix[16],const float pos[3],float t[3]); // only rotate the point by a 4x4 matrix, don't translate.
  57. void fm_rotate(const double matri[16],const double pos[3],double t[3]); // only rotate the point by a 4x4 matrix, don't translate.
  58. void fm_eulerToMatrix(float ax,float ay,float az,float matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  59. void fm_eulerToMatrix(double ax,double ay,double az,double matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  60. void fm_getAABB(uint32_t vcount,const float *points,uint32_t pstride,float bmin[3],float bmax[3]);
  61. void fm_getAABB(uint32_t vcount,const double *points,uint32_t pstride,double bmin[3],double bmax[3]);
  62. void fm_getAABBCenter(const float bmin[3],const float bmax[3],float center[3]);
  63. void fm_getAABBCenter(const double bmin[3],const double bmax[3],double center[3]);
  64. void fm_transformAABB(const float bmin[3],const float bmax[3],const float matrix[16],float tbmin[3],float tbmax[3]);
  65. void fm_transformAABB(const double bmin[3],const double bmax[3],const double matrix[16],double tbmin[3],double tbmax[3]);
  66. void fm_eulerToQuat(float x,float y,float z,float quat[4]); // convert euler angles to quaternion.
  67. void fm_eulerToQuat(double x,double y,double z,double quat[4]); // convert euler angles to quaternion.
  68. void fm_quatToEuler(const float quat[4],float &ax,float &ay,float &az);
  69. void fm_quatToEuler(const double quat[4],double &ax,double &ay,double &az);
  70. void fm_eulerToQuat(const float euler[3],float quat[4]); // convert euler angles to quaternion. Angles must be radians not degrees!
  71. void fm_eulerToQuat(const double euler[3],double quat[4]); // convert euler angles to quaternion.
  72. void fm_scale(float x,float y,float z,float matrix[16]); // apply scale to the matrix.
  73. void fm_scale(double x,double y,double z,double matrix[16]); // apply scale to the matrix.
  74. void fm_eulerToQuatDX(float x,float y,float z,float quat[4]); // convert euler angles to quaternion using the fucked up DirectX method
  75. void fm_eulerToQuatDX(double x,double y,double z,double quat[4]); // convert euler angles to quaternion using the fucked up DirectX method
  76. void fm_eulerToMatrixDX(float x,float y,float z,float matrix[16]); // convert euler angles to quaternion using the fucked up DirectX method.
  77. void fm_eulerToMatrixDX(double x,double y,double z,double matrix[16]); // convert euler angles to quaternion using the fucked up DirectX method.
  78. void fm_quatToMatrix(const float quat[4],float matrix[16]); // convert quaterinion rotation to matrix, translation set to zero.
  79. void fm_quatToMatrix(const double quat[4],double matrix[16]); // convert quaterinion rotation to matrix, translation set to zero.
  80. void fm_quatRotate(const float quat[4],const float v[3],float r[3]); // rotate a vector directly by a quaternion.
  81. void fm_quatRotate(const double quat[4],const double v[3],double r[3]); // rotate a vector directly by a quaternion.
  82. void fm_getTranslation(const float matrix[16],float t[3]);
  83. void fm_getTranslation(const double matrix[16],double t[3]);
  84. void fm_setTranslation(const float *translation,float matrix[16]);
  85. void fm_setTranslation(const double *translation,double matrix[16]);
  86. void fm_multiplyQuat(const float *qa,const float *qb,float *quat);
  87. void fm_multiplyQuat(const double *qa,const double *qb,double *quat);
  88. void fm_matrixToQuat(const float matrix[16],float quat[4]); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
  89. void fm_matrixToQuat(const double matrix[16],double quat[4]); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
  90. float fm_sphereVolume(float radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
  91. double fm_sphereVolume(double radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
  92. float fm_cylinderVolume(float radius,float h);
  93. double fm_cylinderVolume(double radius,double h);
  94. float fm_capsuleVolume(float radius,float h);
  95. double fm_capsuleVolume(double radius,double h);
  96. float fm_distance(const float p1[3],const float p2[3]);
  97. double fm_distance(const double p1[3],const double p2[3]);
  98. float fm_distanceSquared(const float p1[3],const float p2[3]);
  99. double fm_distanceSquared(const double p1[3],const double p2[3]);
  100. float fm_distanceSquaredXZ(const float p1[3],const float p2[3]);
  101. double fm_distanceSquaredXZ(const double p1[3],const double p2[3]);
  102. float fm_computePlane(const float p1[3],const float p2[3],const float p3[3],float *n); // return D
  103. double fm_computePlane(const double p1[3],const double p2[3],const double p3[3],double *n); // return D
  104. float fm_distToPlane(const float plane[4],const float pos[3]); // computes the distance of this point from the plane.
  105. double fm_distToPlane(const double plane[4],const double pos[3]); // computes the distance of this point from the plane.
  106. float fm_dot(const float p1[3],const float p2[3]);
  107. double fm_dot(const double p1[3],const double p2[3]);
  108. void fm_cross(float cross[3],const float a[3],const float b[3]);
  109. void fm_cross(double cross[3],const double a[3],const double b[3]);
  110. float fm_computeNormalVector(float n[3],const float p1[3],const float p2[3]); // as P2-P1 normalized.
  111. double fm_computeNormalVector(double n[3],const double p1[3],const double p2[3]); // as P2-P1 normalized.
  112. bool fm_computeWindingOrder(const float p1[3],const float p2[3],const float p3[3]); // returns true if the triangle is clockwise.
  113. bool fm_computeWindingOrder(const double p1[3],const double p2[3],const double p3[3]); // returns true if the triangle is clockwise.
  114. float fm_normalize(float n[3]); // normalize this vector and return the distance
  115. double fm_normalize(double n[3]); // normalize this vector and return the distance
  116. float fm_normalizeQuat(float n[4]); // normalize this quat
  117. double fm_normalizeQuat(double n[4]); // normalize this quat
  118. void fm_matrixMultiply(const float A[16],const float B[16],float dest[16]);
  119. void fm_matrixMultiply(const double A[16],const double B[16],double dest[16]);
  120. void fm_composeTransform(const float position[3],const float quat[4],const float scale[3],float matrix[16]);
  121. void fm_composeTransform(const double position[3],const double quat[4],const double scale[3],double matrix[16]);
  122. float fm_computeArea(const float p1[3],const float p2[3],const float p3[3]);
  123. double fm_computeArea(const double p1[3],const double p2[3],const double p3[3]);
  124. void fm_lerp(const float p1[3],const float p2[3],float dest[3],float lerpValue);
  125. void fm_lerp(const double p1[3],const double p2[3],double dest[3],double lerpValue);
  126. bool fm_insideTriangleXZ(const float test[3],const float p1[3],const float p2[3],const float p3[3]);
  127. bool fm_insideTriangleXZ(const double test[3],const double p1[3],const double p2[3],const double p3[3]);
  128. bool fm_insideAABB(const float pos[3],const float bmin[3],const float bmax[3]);
  129. bool fm_insideAABB(const double pos[3],const double bmin[3],const double bmax[3]);
  130. bool fm_insideAABB(const float obmin[3],const float obmax[3],const float tbmin[3],const float tbmax[3]); // test if bounding box tbmin/tmbax is fully inside obmin/obmax
  131. bool fm_insideAABB(const double obmin[3],const double obmax[3],const double tbmin[3],const double tbmax[3]); // test if bounding box tbmin/tmbax is fully inside obmin/obmax
  132. uint32_t fm_clipTestPoint(const float bmin[3],const float bmax[3],const float pos[3]);
  133. uint32_t fm_clipTestPoint(const double bmin[3],const double bmax[3],const double pos[3]);
  134. uint32_t fm_clipTestPointXZ(const float bmin[3],const float bmax[3],const float pos[3]); // only tests X and Z, not Y
  135. uint32_t fm_clipTestPointXZ(const double bmin[3],const double bmax[3],const double pos[3]); // only tests X and Z, not Y
  136. uint32_t fm_clipTestAABB(const float bmin[3],const float bmax[3],const float p1[3],const float p2[3],const float p3[3],uint32_t &andCode);
  137. uint32_t fm_clipTestAABB(const double bmin[3],const double bmax[3],const double p1[3],const double p2[3],const double p3[3],uint32_t &andCode);
  138. bool fm_lineTestAABBXZ(const float p1[3],const float p2[3],const float bmin[3],const float bmax[3],float &time);
  139. bool fm_lineTestAABBXZ(const double p1[3],const double p2[3],const double bmin[3],const double bmax[3],double &time);
  140. bool fm_lineTestAABB(const float p1[3],const float p2[3],const float bmin[3],const float bmax[3],float &time);
  141. bool fm_lineTestAABB(const double p1[3],const double p2[3],const double bmin[3],const double bmax[3],double &time);
  142. void fm_initMinMax(const float p[3],float bmin[3],float bmax[3]);
  143. void fm_initMinMax(const double p[3],double bmin[3],double bmax[3]);
  144. void fm_initMinMax(float bmin[3],float bmax[3]);
  145. void fm_initMinMax(double bmin[3],double bmax[3]);
  146. void fm_minmax(const float p[3],float bmin[3],float bmax[3]); // accumulate to a min-max value
  147. void fm_minmax(const double p[3],double bmin[3],double bmax[3]); // accumulate to a min-max value
  148. // Computes the diagonal length of the bounding box and then inflates the bounding box on all sides
  149. // by the ratio provided.
  150. void fm_inflateMinMax(float bmin[3], float bmax[3], float ratio);
  151. void fm_inflateMinMax(double bmin[3], double bmax[3], double ratio);
  152. float fm_solveX(const float plane[4],float y,float z); // solve for X given this plane equation and the other two components.
  153. double fm_solveX(const double plane[4],double y,double z); // solve for X given this plane equation and the other two components.
  154. float fm_solveY(const float plane[4],float x,float z); // solve for Y given this plane equation and the other two components.
  155. double fm_solveY(const double plane[4],double x,double z); // solve for Y given this plane equation and the other two components.
  156. float fm_solveZ(const float plane[4],float x,float y); // solve for Z given this plane equation and the other two components.
  157. double fm_solveZ(const double plane[4],double x,double y); // solve for Z given this plane equation and the other two components.
  158. bool fm_computeBestFitPlane(uint32_t vcount, // number of input data points
  159. const float *points, // starting address of points array.
  160. uint32_t vstride, // stride between input points.
  161. const float *weights, // *optional point weighting values.
  162. uint32_t wstride, // weight stride for each vertex.
  163. float plane[4], // Best fit plane equation
  164. float center[3]); // Best fit weighted center of input points
  165. bool fm_computeBestFitPlane(uint32_t vcount, // number of input data points
  166. const double *points, // starting address of points array.
  167. uint32_t vstride, // stride between input points.
  168. const double *weights, // *optional point weighting values.
  169. uint32_t wstride, // weight stride for each vertex.
  170. double plane[4],
  171. double center[3]);
  172. // Computes the average center of a set of data points
  173. bool fm_computeCentroid(uint32_t vcount, // number of input data points
  174. const float *points, // starting address of points array.
  175. float *center);
  176. bool fm_computeCentroid(uint32_t vcount, // number of input data points
  177. const double *points, // starting address of points array.
  178. double *center);
  179. // Compute centroid of a triangle mesh; takes area of each triangle into account
  180. // weighted average
  181. bool fm_computeCentroid(uint32_t vcount, // number of input data points
  182. const float *points, // starting address of points array.
  183. uint32_t triangleCount,
  184. const uint32_t *indices,
  185. float *center);
  186. // Compute centroid of a triangle mesh; takes area of each triangle into account
  187. // weighted average
  188. bool fm_computeCentroid(uint32_t vcount, // number of input data points
  189. const double *points, // starting address of points array.
  190. uint32_t triangleCount,
  191. const uint32_t *indices,
  192. double *center);
  193. float fm_computeBestFitAABB(uint32_t vcount,const float *points,uint32_t pstride,float bmin[3],float bmax[3]); // returns the diagonal distance
  194. double fm_computeBestFitAABB(uint32_t vcount,const double *points,uint32_t pstride,double bmin[3],double bmax[3]); // returns the diagonal distance
  195. float fm_computeBestFitSphere(uint32_t vcount,const float *points,uint32_t pstride,float center[3]);
  196. double fm_computeBestFitSphere(uint32_t vcount,const double *points,uint32_t pstride,double center[3]);
  197. bool fm_lineSphereIntersect(const float center[3],float radius,const float p1[3],const float p2[3],float intersect[3]);
  198. bool fm_lineSphereIntersect(const double center[3],double radius,const double p1[3],const double p2[3],double intersect[3]);
  199. bool fm_intersectRayAABB(const float bmin[3],const float bmax[3],const float pos[3],const float dir[3],float intersect[3]);
  200. bool fm_intersectLineSegmentAABB(const float bmin[3],const float bmax[3],const float p1[3],const float p2[3],float intersect[3]);
  201. bool fm_lineIntersectsTriangle(const float rayStart[3],const float rayEnd[3],const float p1[3],const float p2[3],const float p3[3],float sect[3]);
  202. bool fm_lineIntersectsTriangle(const double rayStart[3],const double rayEnd[3],const double p1[3],const double p2[3],const double p3[3],double sect[3]);
  203. bool fm_rayIntersectsTriangle(const float origin[3],const float dir[3],const float v0[3],const float v1[3],const float v2[3],float &t);
  204. bool fm_rayIntersectsTriangle(const double origin[3],const double dir[3],const double v0[3],const double v1[3],const double v2[3],double &t);
  205. bool fm_raySphereIntersect(const float center[3],float radius,const float pos[3],const float dir[3],float distance,float intersect[3]);
  206. bool fm_raySphereIntersect(const double center[3],double radius,const double pos[3],const double dir[3],double distance,double intersect[3]);
  207. void fm_catmullRom(float out_vector[3],const float p1[3],const float p2[3],const float p3[3],const float *p4, const float s);
  208. void fm_catmullRom(double out_vector[3],const double p1[3],const double p2[3],const double p3[3],const double *p4, const double s);
  209. bool fm_intersectAABB(const float bmin1[3],const float bmax1[3],const float bmin2[3],const float bmax2[3]);
  210. bool fm_intersectAABB(const double bmin1[3],const double bmax1[3],const double bmin2[3],const double bmax2[3]);
  211. // computes the rotation quaternion to go from unit-vector v0 to unit-vector v1
  212. void fm_rotationArc(const float v0[3],const float v1[3],float quat[4]);
  213. void fm_rotationArc(const double v0[3],const double v1[3],double quat[4]);
  214. float fm_distancePointLineSegment(const float Point[3],const float LineStart[3],const float LineEnd[3],float intersection[3],LineSegmentType &type,float epsilon);
  215. double fm_distancePointLineSegment(const double Point[3],const double LineStart[3],const double LineEnd[3],double intersection[3],LineSegmentType &type,double epsilon);
  216. bool fm_colinear(const double p1[3],const double p2[3],const double p3[3],double epsilon=0.999); // true if these three points in a row are co-linear
  217. bool fm_colinear(const float p1[3],const float p2[3],const float p3[3],float epsilon=0.999f);
  218. bool fm_colinear(const float a1[3],const float a2[3],const float b1[3],const float b2[3],float epsilon=0.999f); // true if these two line segments are co-linear.
  219. bool fm_colinear(const double a1[3],const double a2[3],const double b1[3],const double b2[3],double epsilon=0.999); // true if these two line segments are co-linear.
  220. enum IntersectResult
  221. {
  222. IR_DONT_INTERSECT,
  223. IR_DO_INTERSECT,
  224. IR_COINCIDENT,
  225. IR_PARALLEL,
  226. };
  227. IntersectResult fm_intersectLineSegments2d(const float a1[3], const float a2[3], const float b1[3], const float b2[3], float intersectionPoint[3]);
  228. IntersectResult fm_intersectLineSegments2d(const double a1[3],const double a2[3],const double b1[3],const double b2[3],double intersectionPoint[3]);
  229. IntersectResult fm_intersectLineSegments2dTime(const float a1[3], const float a2[3], const float b1[3], const float b2[3],float &t1,float &t2);
  230. IntersectResult fm_intersectLineSegments2dTime(const double a1[3],const double a2[3],const double b1[3],const double b2[3],double &t1,double &t2);
  231. // Plane-Triangle splitting
  232. enum PlaneTriResult
  233. {
  234. PTR_ON_PLANE,
  235. PTR_FRONT,
  236. PTR_BACK,
  237. PTR_SPLIT,
  238. };
  239. PlaneTriResult fm_planeTriIntersection(const float plane[4], // the plane equation in Ax+By+Cz+D format
  240. const float *triangle, // the source triangle.
  241. uint32_t tstride, // stride in bytes of the input and output *vertices*
  242. float epsilon, // the co-planer epsilon value.
  243. float *front, // the triangle in front of the
  244. uint32_t &fcount, // number of vertices in the 'front' triangle
  245. float *back, // the triangle in back of the plane
  246. uint32_t &bcount); // the number of vertices in the 'back' triangle.
  247. PlaneTriResult fm_planeTriIntersection(const double plane[4], // the plane equation in Ax+By+Cz+D format
  248. const double *triangle, // the source triangle.
  249. uint32_t tstride, // stride in bytes of the input and output *vertices*
  250. double epsilon, // the co-planer epsilon value.
  251. double *front, // the triangle in front of the
  252. uint32_t &fcount, // number of vertices in the 'front' triangle
  253. double *back, // the triangle in back of the plane
  254. uint32_t &bcount); // the number of vertices in the 'back' triangle.
  255. bool fm_intersectPointPlane(const float p1[3],const float p2[3],float *split,const float plane[4]);
  256. bool fm_intersectPointPlane(const double p1[3],const double p2[3],double *split,const double plane[4]);
  257. PlaneTriResult fm_getSidePlane(const float p[3],const float plane[4],float epsilon);
  258. PlaneTriResult fm_getSidePlane(const double p[3],const double plane[4],double epsilon);
  259. void fm_computeBestFitOBB(uint32_t vcount,const float *points,uint32_t pstride,float *sides,float matrix[16],bool bruteForce=true);
  260. void fm_computeBestFitOBB(uint32_t vcount,const double *points,uint32_t pstride,double *sides,double matrix[16],bool bruteForce=true);
  261. void fm_computeBestFitOBB(uint32_t vcount,const float *points,uint32_t pstride,float *sides,float pos[3],float quat[4],bool bruteForce=true);
  262. void fm_computeBestFitOBB(uint32_t vcount,const double *points,uint32_t pstride,double *sides,double pos[3],double quat[4],bool bruteForce=true);
  263. void fm_computeBestFitABB(uint32_t vcount,const float *points,uint32_t pstride,float *sides,float pos[3]);
  264. void fm_computeBestFitABB(uint32_t vcount,const double *points,uint32_t pstride,double *sides,double pos[3]);
  265. //** Note, if the returned capsule height is less than zero, then you must represent it is a sphere of size radius.
  266. void fm_computeBestFitCapsule(uint32_t vcount,const float *points,uint32_t pstride,float &radius,float &height,float matrix[16],bool bruteForce=true);
  267. void fm_computeBestFitCapsule(uint32_t vcount,const double *points,uint32_t pstride,float &radius,float &height,double matrix[16],bool bruteForce=true);
  268. void fm_planeToMatrix(const float plane[4],float matrix[16]); // convert a plane equation to a 4x4 rotation matrix. Reference vector is 0,1,0
  269. void fm_planeToQuat(const float plane[4],float quat[4],float pos[3]); // convert a plane equation to a quaternion and translation
  270. void fm_planeToMatrix(const double plane[4],double matrix[16]); // convert a plane equation to a 4x4 rotation matrix
  271. void fm_planeToQuat(const double plane[4],double quat[4],double pos[3]); // convert a plane equation to a quaternion and translation
  272. inline void fm_doubleToFloat3(const double p[3],float t[3]) { t[0] = (float) p[0]; t[1] = (float)p[1]; t[2] = (float)p[2]; };
  273. inline void fm_floatToDouble3(const float p[3],double t[3]) { t[0] = (double)p[0]; t[1] = (double)p[1]; t[2] = (double)p[2]; };
  274. void fm_eulerMatrix(float ax,float ay,float az,float matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  275. void fm_eulerMatrix(double ax,double ay,double az,double matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
  276. float fm_computeMeshVolume(const float *vertices,uint32_t tcount,const uint32_t *indices);
  277. double fm_computeMeshVolume(const double *vertices,uint32_t tcount,const uint32_t *indices);
  278. #define FM_DEFAULT_GRANULARITY 0.001f // 1 millimeter is the default granularity
  279. class fm_VertexIndex
  280. {
  281. public:
  282. virtual uint32_t getIndex(const float pos[3],bool &newPos) = 0; // get welded index for this float vector[3]
  283. virtual uint32_t getIndex(const double pos[3],bool &newPos) = 0; // get welded index for this double vector[3]
  284. virtual const float * getVerticesFloat(void) const = 0;
  285. virtual const double * getVerticesDouble(void) const = 0;
  286. virtual const float * getVertexFloat(uint32_t index) const = 0;
  287. virtual const double * getVertexDouble(uint32_t index) const = 0;
  288. virtual uint32_t getVcount(void) const = 0;
  289. virtual bool isDouble(void) const = 0;
  290. virtual bool saveAsObj(const char *fname,uint32_t tcount,uint32_t *indices) = 0;
  291. };
  292. fm_VertexIndex * fm_createVertexIndex(double granularity,bool snapToGrid); // create an indexed vertex system for doubles
  293. fm_VertexIndex * fm_createVertexIndex(float granularity,bool snapToGrid); // create an indexed vertext system for floats
  294. void fm_releaseVertexIndex(fm_VertexIndex *vindex);
  295. class fm_Triangulate
  296. {
  297. public:
  298. virtual const double * triangulate3d(uint32_t pcount,
  299. const double *points,
  300. uint32_t vstride,
  301. uint32_t &tcount,
  302. bool consolidate,
  303. double epsilon) = 0;
  304. virtual const float * triangulate3d(uint32_t pcount,
  305. const float *points,
  306. uint32_t vstride,
  307. uint32_t &tcount,
  308. bool consolidate,
  309. float epsilon) = 0;
  310. };
  311. fm_Triangulate * fm_createTriangulate(void);
  312. void fm_releaseTriangulate(fm_Triangulate *t);
  313. const float * fm_getPoint(const float *points,uint32_t pstride,uint32_t index);
  314. const double * fm_getPoint(const double *points,uint32_t pstride,uint32_t index);
  315. bool fm_insideTriangle(float Ax, float Ay,float Bx, float By,float Cx, float Cy,float Px, float Py);
  316. bool fm_insideTriangle(double Ax, double Ay,double Bx, double By,double Cx, double Cy,double Px, double Py);
  317. float fm_areaPolygon2d(uint32_t pcount,const float *points,uint32_t pstride);
  318. double fm_areaPolygon2d(uint32_t pcount,const double *points,uint32_t pstride);
  319. bool fm_pointInsidePolygon2d(uint32_t pcount,const float *points,uint32_t pstride,const float *point,uint32_t xindex=0,uint32_t yindex=1);
  320. bool fm_pointInsidePolygon2d(uint32_t pcount,const double *points,uint32_t pstride,const double *point,uint32_t xindex=0,uint32_t yindex=1);
  321. uint32_t fm_consolidatePolygon(uint32_t pcount,const float *points,uint32_t pstride,float *dest,float epsilon=0.999999f); // collapses co-linear edges.
  322. uint32_t fm_consolidatePolygon(uint32_t pcount,const double *points,uint32_t pstride,double *dest,double epsilon=0.999999); // collapses co-linear edges.
  323. bool fm_computeSplitPlane(uint32_t vcount,const double *vertices,uint32_t tcount,const uint32_t *indices,double *plane);
  324. bool fm_computeSplitPlane(uint32_t vcount,const float *vertices,uint32_t tcount,const uint32_t *indices,float *plane);
  325. void fm_nearestPointInTriangle(const float *pos,const float *p1,const float *p2,const float *p3,float *nearest);
  326. void fm_nearestPointInTriangle(const double *pos,const double *p1,const double *p2,const double *p3,double *nearest);
  327. float fm_areaTriangle(const float *p1,const float *p2,const float *p3);
  328. double fm_areaTriangle(const double *p1,const double *p2,const double *p3);
  329. void fm_subtract(const float *A,const float *B,float *diff); // compute A-B and store the result in 'diff'
  330. void fm_subtract(const double *A,const double *B,double *diff); // compute A-B and store the result in 'diff'
  331. void fm_multiply(float *A,float scaler);
  332. void fm_multiply(double *A,double scaler);
  333. void fm_add(const float *A,const float *B,float *sum);
  334. void fm_add(const double *A,const double *B,double *sum);
  335. void fm_copy3(const float *source,float *dest);
  336. void fm_copy3(const double *source,double *dest);
  337. // re-indexes an indexed triangle mesh but drops unused vertices. The output_indices can be the same pointer as the input indices.
  338. // the output_vertices can point to the input vertices if you desire. The output_vertices buffer should be at least the same size
  339. // is the input buffer. The routine returns the new vertex count after re-indexing.
  340. uint32_t fm_copyUniqueVertices(uint32_t vcount,const float *input_vertices,float *output_vertices,uint32_t tcount,const uint32_t *input_indices,uint32_t *output_indices);
  341. uint32_t fm_copyUniqueVertices(uint32_t vcount,const double *input_vertices,double *output_vertices,uint32_t tcount,const uint32_t *input_indices,uint32_t *output_indices);
  342. bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const float *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
  343. bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const double *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
  344. bool fm_samePlane(const float p1[4],const float p2[4],float normalEpsilon=0.01f,float dEpsilon=0.001f,bool doubleSided=false); // returns true if these two plane equations are identical within an epsilon
  345. bool fm_samePlane(const double p1[4],const double p2[4],double normalEpsilon=0.01,double dEpsilon=0.001,bool doubleSided=false);
  346. void fm_OBBtoAABB(const float obmin[3],const float obmax[3],const float matrix[16],float abmin[3],float abmax[3]);
  347. // a utility class that will tessellate a mesh.
  348. class fm_Tesselate
  349. {
  350. public:
  351. virtual const uint32_t * tesselate(fm_VertexIndex *vindex,uint32_t tcount,const uint32_t *indices,float longEdge,uint32_t maxDepth,uint32_t &outcount) = 0;
  352. };
  353. fm_Tesselate * fm_createTesselate(void);
  354. void fm_releaseTesselate(fm_Tesselate *t);
  355. void fm_computeMeanNormals(uint32_t vcount, // the number of vertices
  356. const float *vertices, // the base address of the vertex position data.
  357. uint32_t vstride, // the stride between position data.
  358. float *normals, // the base address of the destination for mean vector normals
  359. uint32_t nstride, // the stride between normals
  360. uint32_t tcount, // the number of triangles
  361. const uint32_t *indices); // the triangle indices
  362. void fm_computeMeanNormals(uint32_t vcount, // the number of vertices
  363. const double *vertices, // the base address of the vertex position data.
  364. uint32_t vstride, // the stride between position data.
  365. double *normals, // the base address of the destination for mean vector normals
  366. uint32_t nstride, // the stride between normals
  367. uint32_t tcount, // the number of triangles
  368. const uint32_t *indices); // the triangle indices
  369. bool fm_isValidTriangle(const float *p1,const float *p2,const float *p3,float epsilon=0.00001f);
  370. bool fm_isValidTriangle(const double *p1,const double *p2,const double *p3,double epsilon=0.00001f);
  371. }; // end of namespace
  372. #endif