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