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 | |