1 | /**************************************************************************************** |
2 | |
3 | Copyright (C) 2015 Autodesk, Inc. |
4 | All rights reserved. |
5 | |
6 | Use of this software is subject to the terms of the Autodesk license agreement |
7 | provided at the time of installation or download, or which otherwise accompanies |
8 | this software in either electronic or hard copy form. |
9 | |
10 | ****************************************************************************************/ |
11 | |
12 | //! \file fbxmath.h |
13 | #ifndef _FBXSDK_CORE_MATH_H_ |
14 | #define _FBXSDK_CORE_MATH_H_ |
15 | |
16 | #include <fbxsdk/fbxsdk_def.h> |
17 | |
18 | #include <fbxsdk/core/math/fbxvector2.h> |
19 | #include <fbxsdk/core/math/fbxvector4.h> |
20 | #include <fbxsdk/core/math/fbxmatrix.h> |
21 | #include <fbxsdk/core/math/fbxaffinematrix.h> |
22 | |
23 | //On Mac OS, cmath will include math.h and undef "isnan" |
24 | #if defined(FBXSDK_ENV_MAC) |
25 | #include <cmath> |
26 | extern "C" int isnan (double); |
27 | #endif |
28 | |
29 | #include <fbxsdk/fbxsdk_nsbegin.h> |
30 | |
31 | #if defined(FBXSDK_ENV_WIN) |
32 | #ifndef isnan |
33 | #define isnan _isnan |
34 | #endif |
35 | #ifndef finite |
36 | #define finite _finite |
37 | #endif |
38 | #endif |
39 | |
40 | //--------------------------------------------------------------------------------------- |
41 | //Common Constants |
42 | #define FBXSDK_PI 3.1415926535897932384626433832795028841971693993751 //!< PI mathematic constant |
43 | #define FBXSDK_PI_DIV_2 1.5707963267948966192313216916397514420985846996875 //!< PI divided by 2 |
44 | #define FBXSDK_PI_DIV_180 0.017453292519943295769236907684886127134428718885417 //!< PI divived by 180 |
45 | #define FBXSDK_180_DIV_PI 57.295779513082320876798154814105170332405472466565 //!< 180 divided by PI |
46 | #define FBXSDK_1_DIV_LN2 1.4426950408889634073599246810018921374266459541530 //!< 1 divided by LogN2 |
47 | |
48 | //--------------------------------------------------------------------------------------- |
49 | //Unit Convertion Ratio |
50 | #define FBXSDK_DEG_TO_RAD FBXSDK_PI_DIV_180 //!< Degree to Radian |
51 | #define FBXSDK_RAD_TO_DEG FBXSDK_180_DIV_PI //!< Radian to Degree |
52 | #define FBXSDK_IN_TO_CM 2.54 //!< Inch to Centimeter |
53 | #define FBXSDK_MM_TO_CM 0.1 //!< Millimeter to Centimeter |
54 | #define FBXSDK_CM_TO_IN 0.393700787 //!< Centimeter to Inch |
55 | #define FBXSDK_IN_TO_MM 25.4 //!< Inch to Millimeter |
56 | #define FBXSDK_MM_TO_IN 0.0393700787 //!< Millimeter to Inch |
57 | #define FBXSDK_FT_TO_M 0.3048 //!< Feet to Meter |
58 | #define FBXSDK_M_TO_FT 3.2808399 //!< Meter to Feet |
59 | #define FBXSDK_YD_TO_FT 3 //!< Yard to Feet |
60 | #define FBXSDK_FT_TO_YD 0.333333333 //!< Feet to Yard |
61 | #define FBXSDK_KM_TO_MILE 0.621371192 //!< Kilometer to Mile |
62 | #define FBXSDK_MILE_TO_KM 1.609344 //!< Mile to Kilometer |
63 | #define FBXSDK_YD_TO_M 0.9144 //!< Yard to Meter |
64 | #define FBXSDK_M_TO_YD 1.0936133 //!< Meter to Yard |
65 | |
66 | //--------------------------------------------------------------------------------------- |
67 | //Euler Definition |
68 | #define FBXSDK_EULER_DEGENERATE FbxEuler::DegenerateThreshold() //!< Euler degenerate threshold can be changed with a call to FbxEuler::SetDegenerateThreshold. |
69 | |
70 | class FBXSDK_DLL FbxEuler |
71 | { |
72 | public: |
73 | enum EAxis {eAxisX=0, eAxisY=1, eAxisZ=2}; |
74 | |
75 | enum EOrder |
76 | { |
77 | eOrderXYZ, |
78 | eOrderXZY, |
79 | eOrderYZX, |
80 | eOrderYXZ, |
81 | eOrderZXY, |
82 | eOrderZYX, |
83 | eOrderSphericXYZ |
84 | }; |
85 | |
86 | static bool IsParityOdd(EOrder pOrder); |
87 | static bool IsRepeat(EOrder pOrder); |
88 | |
89 | static const int AxisTableSize; |
90 | static const int AxisTable[][3]; |
91 | |
92 | // Used to detect Euler gimbal locks when extracting the rotation vector from |
93 | // the FbxAMatrix. This value should only be changed when the user system stores |
94 | // single floating point values into the FbxAMatrix with a very low precision. |
95 | // In this case, the default threshold value would be too small for a proper detection |
96 | // and the extracted values can quickly become off target by a huge amount. |
97 | static void SetDegenerateThreshold(double pThreshold=16.0*FBXSDK_FLOAT_EPSILON); |
98 | static inline double DegenerateThreshold() { return FbxEuler::mDegenerateThreshold; } |
99 | |
100 | private: |
101 | static double mDegenerateThreshold; |
102 | }; |
103 | |
104 | /** Rotation order flags. |
105 | * Each rotate order produces a different end orientation. For example, if the rotation order for an object is set to XYZ, |
106 | * the object first rotates about its X-axis, then its Y-axis, and finally its Z-axis. |
107 | */ |
108 | |
109 | #define EFbxRotationOrder FbxEuler::EOrder |
110 | #define eEulerXYZ FbxEuler::eOrderXYZ |
111 | #define eEulerXZY FbxEuler::eOrderXZY |
112 | #define eEulerYZX FbxEuler::eOrderYZX |
113 | #define eEulerYXZ FbxEuler::eOrderYXZ |
114 | #define eEulerZXY FbxEuler::eOrderZXY |
115 | #define eEulerZYX FbxEuler::eOrderZYX |
116 | #define eSphericXYZ FbxEuler::eOrderSphericXYZ |
117 | |
118 | |
119 | |
120 | /** Quaternion interpolation modes. */ |
121 | enum EFbxQuatInterpMode |
122 | { |
123 | eQuatInterpOff, //!< Do not evaluate using quaternion interpolation. |
124 | eQuatInterpClassic, //!< Legacy quaternion interpolation mode. |
125 | eQuatInterpSlerp, //!< Spherical linear interpolation. |
126 | eQuatInterpCubic, //!< Cubic interpolation. |
127 | eQuatInterpTangentDependent, //!< Mix between Slerp and cubic interpolation, depending on the specified tangents for each key. |
128 | eQuatInterpCount //!< Number of quaternion interpolation modes. Mark the end of this enum. |
129 | }; |
130 | |
131 | extern FBXSDK_DLL const FbxDouble FbxIdentityMatrix[4][4]; |
132 | extern FBXSDK_DLL const FbxVector4 FbxZeroVector4; |
133 | |
134 | inline float FbxFloor(const float x) |
135 | { |
136 | return float(floor(x)); |
137 | } |
138 | |
139 | inline double FbxFloor(const double x) |
140 | { |
141 | return floor(x); |
142 | } |
143 | |
144 | inline float FbxCeil(const float x) |
145 | { |
146 | return float(ceil(x)); |
147 | } |
148 | |
149 | inline double FbxCeil(const double x) |
150 | { |
151 | return ceil(x); |
152 | } |
153 | |
154 | template<class T> inline T FbxSign(const T x) |
155 | { |
156 | return (x < 0) ? T(-1) : T(1); |
157 | } |
158 | |
159 | template<class T> inline T FbxRound(const T x) |
160 | { |
161 | T y = FbxFloor(x); |
162 | return (x - y < T(0.5)) ? y : y + T(1); |
163 | } |
164 | |
165 | inline FbxUChar FbxAbs(const FbxUChar x) |
166 | { |
167 | return x; |
168 | } |
169 | |
170 | inline FbxUShort FbxAbs(const FbxUShort x) |
171 | { |
172 | return x; |
173 | } |
174 | |
175 | inline FbxUInt FbxAbs(const FbxUInt x) |
176 | { |
177 | return x; |
178 | } |
179 | |
180 | #ifndef FBXSDK_SYSTEM_IS_LP64 |
181 | inline FbxULong FbxAbs(const FbxULong x) |
182 | { |
183 | return x; |
184 | } |
185 | #endif |
186 | |
187 | inline FbxULongLong FbxAbs(const FbxULongLong x) |
188 | { |
189 | return x; |
190 | } |
191 | |
192 | inline FbxFloat FbxAbs(const FbxFloat x) |
193 | { |
194 | return (FbxFloat)fabs(x); |
195 | } |
196 | |
197 | inline FbxDouble FbxAbs(const FbxDouble x) |
198 | { |
199 | return fabs(x); |
200 | } |
201 | |
202 | template<class T> inline T FbxAbs(const T x) |
203 | { |
204 | return (x >= 0) ? x : ((x > FbxMin(x)) ? -x : FbxMax(x)); |
205 | } |
206 | |
207 | template<class T> inline T FbxClamp(const T value, const T min, const T max) |
208 | { |
209 | return (value < min) ? min : ((value > max) ? max : value); |
210 | } |
211 | |
212 | template<class T> inline bool FbxEqual(const T x, const T y, const T e=(T)FBXSDK_TOLERANCE) |
213 | { |
214 | return FbxAbs(x - y) <= e; |
215 | } |
216 | |
217 | inline bool FbxEqual(const FbxDouble2& x, const FbxDouble2& y, const double e=FBXSDK_TOLERANCE) |
218 | { |
219 | return ( FbxEqual(x.mData[0], y.mData[0], e) && FbxEqual(x.mData[1], y.mData[1], e) ); |
220 | } |
221 | |
222 | inline bool FbxEqual(const FbxDouble3& x, const FbxDouble3& y, const double e=FBXSDK_TOLERANCE) |
223 | { |
224 | return ( FbxEqual(x.mData[0], y.mData[0], e) && FbxEqual(x.mData[1], y.mData[1], e) && FbxEqual(x.mData[2], y.mData[2], e) ); |
225 | } |
226 | |
227 | inline bool FbxEqual(const FbxDouble4& x, const FbxDouble4& y, const double e=FBXSDK_TOLERANCE) |
228 | { |
229 | return ( FbxEqual(x.mData[0], y.mData[0], e) && FbxEqual(x.mData[1], y.mData[1], e) && FbxEqual(x.mData[2], y.mData[2], e) && FbxEqual(x.mData[3], y.mData[3], e) ); |
230 | } |
231 | |
232 | inline bool FbxEqual(const FbxDouble4x4& x, const FbxDouble4x4& y, const double e=FBXSDK_TOLERANCE) |
233 | { |
234 | return ( FbxEqual(x[0], y[0], e) && FbxEqual(x[1], y[1], e) && FbxEqual(x[2], y[2], e) && FbxEqual(x[3], y[3], e) ); |
235 | } |
236 | |
237 | inline bool FbxEqual(const FbxVector2& x, const FbxVector2& y, const double e=FBXSDK_TOLERANCE) |
238 | { |
239 | return ( FbxEqual(x.mData[0], y.mData[0], e) && FbxEqual(x.mData[1], y.mData[1], e) ); |
240 | } |
241 | |
242 | inline bool FbxEqual(const FbxVector4& x, const FbxVector4& y, const double e=FBXSDK_TOLERANCE) |
243 | { |
244 | return ( FbxEqual(x.mData[0], y.mData[0], e) && FbxEqual(x.mData[1], y.mData[1], e) && FbxEqual(x.mData[2], y.mData[2], e) && FbxEqual(x.mData[3], y.mData[3], e) ); |
245 | } |
246 | |
247 | inline bool FbxEqual(const FbxMatrix& x, const FbxMatrix& y, const double e=FBXSDK_TOLERANCE) |
248 | { |
249 | return ( FbxEqual(x[0], y[0], e) && FbxEqual(x[1], y[1], e) && FbxEqual(x[2], y[2], e) && FbxEqual(x[3], y[3], e) ); |
250 | } |
251 | |
252 | inline bool FbxEqual(const FbxAMatrix& x, const FbxAMatrix& y, const double e=FBXSDK_TOLERANCE) |
253 | { |
254 | return ( FbxEqual(x[0], y[0], e) && FbxEqual(x[1], y[1], e) && FbxEqual(x[2], y[2], e) && FbxEqual(x[3], y[3], e) ); |
255 | } |
256 | |
257 | inline FbxDouble FbxMod(const FbxFloat x, FbxFloat& i) |
258 | { |
259 | return modff(x, &i); |
260 | } |
261 | |
262 | inline FbxDouble FbxMod(const FbxDouble x, FbxDouble& i) |
263 | { |
264 | return modf(x, &i); |
265 | } |
266 | |
267 | inline FbxDouble FbxMod(const FbxFloat x) |
268 | { |
269 | FbxFloat i; |
270 | return modff(x, &i); |
271 | } |
272 | |
273 | inline FbxDouble FbxMod(const FbxDouble x) |
274 | { |
275 | FbxDouble i; |
276 | return modf(x, &i); |
277 | } |
278 | |
279 | template<class T> inline T FbxReciprocal(const T x) |
280 | { |
281 | return T(1) / x; |
282 | } |
283 | |
284 | inline double FbxSqrt(const double x) |
285 | { |
286 | return sqrt(x); |
287 | } |
288 | |
289 | inline float FbxSqrt(const float x) |
290 | { |
291 | return sqrtf(x); |
292 | } |
293 | |
294 | template<class T> inline T FbxSqrt(const T x) |
295 | { |
296 | if( x > 1 ) |
297 | { |
298 | T z, y = x >> 1; |
299 | do |
300 | { |
301 | z = y; |
302 | y = (y + (x / y)) >> 1; |
303 | } |
304 | while(y < z); |
305 | |
306 | return z; |
307 | } |
308 | else |
309 | { |
310 | return x; |
311 | } |
312 | } |
313 | |
314 | inline float FbxExp(const float x) |
315 | { |
316 | return expf(x); |
317 | } |
318 | |
319 | inline double FbxExp(const double x) |
320 | { |
321 | return exp(x); |
322 | } |
323 | |
324 | inline float FbxLog(const float x) |
325 | { |
326 | return float(log(x)); |
327 | } |
328 | |
329 | inline double FbxLog(const double x) |
330 | { |
331 | return log(x); |
332 | } |
333 | |
334 | template<class T> inline T FbxPow(const T x, const T y) |
335 | { |
336 | return (T)FbxExp(y * FbxLog((double)x)); |
337 | } |
338 | |
339 | template<class T> inline T FbxLog2(const T x) |
340 | { |
341 | return (T)(FbxLog(x) * FBXSDK_1_DIV_LN2); |
342 | } |
343 | |
344 | inline float FbxSin(const float x) |
345 | { |
346 | return sinf(x); |
347 | } |
348 | |
349 | inline double FbxSin(const double x) |
350 | { |
351 | return sin(x); |
352 | } |
353 | |
354 | inline float FbxCos(const float x) |
355 | { |
356 | return cosf(x); |
357 | } |
358 | |
359 | inline double FbxCos(const double x) |
360 | { |
361 | return cos(x); |
362 | } |
363 | |
364 | inline float FbxTan(const float x) |
365 | { |
366 | return tanf(x); |
367 | } |
368 | |
369 | inline double FbxTan(const double x) |
370 | { |
371 | return tan(x); |
372 | } |
373 | |
374 | // *y = cos(x), sin(x) |
375 | template<class T> inline T FbxSinCos(const T x, T* y) |
376 | { |
377 | return *y = FbxCos(x), FbxSin(x); |
378 | } |
379 | |
380 | // *y = cos(x * pi/180), sin(x * pi/180) |
381 | template<class T> inline T FbxSinCosd(const T x, T* y) |
382 | { |
383 | return FbxSinCos(T(x * FBXSDK_PI_DIV_180), y); |
384 | } |
385 | |
386 | inline float FbxASin(const float x) |
387 | { |
388 | return asinf(x); |
389 | } |
390 | |
391 | inline double FbxASin(const double x) |
392 | { |
393 | return asin(x); |
394 | } |
395 | |
396 | template<class T> inline T FbxASind(const T x) |
397 | { |
398 | return (T)(FbxASin((double)x) * FBXSDK_180_DIV_PI); |
399 | } |
400 | |
401 | inline float FbxACos(const float x) |
402 | { |
403 | return acosf(x); |
404 | } |
405 | |
406 | inline double FbxACos(const double x) |
407 | { |
408 | return acos(x); |
409 | } |
410 | |
411 | template<class T> inline T FbxACosd(const T x) |
412 | { |
413 | return (T)(FbxACos(x) * FBXSDK_180_DIV_PI); |
414 | } |
415 | |
416 | inline float FbxATan(const float x) |
417 | { |
418 | return atanf(x); |
419 | } |
420 | |
421 | inline double FbxATan(const double x) |
422 | { |
423 | return atan(x); |
424 | } |
425 | |
426 | template<class T> inline T FbxATand(const T x) |
427 | { |
428 | return (T)(FbxATan(x) * FBXSDK_180_DIV_PI); |
429 | } |
430 | |
431 | inline float FbxATan(const float y, const float x) |
432 | { |
433 | return atan2f(y, x); |
434 | } |
435 | |
436 | inline double FbxATan(const double y, const double x) |
437 | { |
438 | return atan2(y, x); |
439 | } |
440 | |
441 | template<class T> inline T FbxATand(const T y, const T x) |
442 | { |
443 | return (T)(FbxATan(y, x) * FBXSDK_180_DIV_PI); |
444 | } |
445 | |
446 | template<class T> inline T FbxNorm(const T x, const T y) |
447 | { |
448 | return FbxSqrt(x * x + y * y); |
449 | } |
450 | |
451 | template<class T> inline T FbxNorm(const T x, const T y, const T z) |
452 | { |
453 | return FbxSqrt(x * x + y * y + z * z); |
454 | } |
455 | |
456 | template<class T> inline T FbxNorm(const T w, const T x, const T y, const T z) |
457 | { |
458 | return FbxSqrt(w * w + x * x + y * y + z * z); |
459 | } |
460 | |
461 | template<class T> inline T FbxHypot(const T x, const T y) |
462 | { |
463 | return FbxSqrt(x * x + y * y); |
464 | } |
465 | |
466 | template<class T> inline T FbxHypot(const T x, const T y, const T z) |
467 | { |
468 | return FbxSqrt(x * x + y * y + z * z); |
469 | } |
470 | |
471 | template<class T> inline T FbxHypot(const T w, const T x, const T y, const T z) |
472 | { |
473 | return FbxSqrt(w * w + x * x + y * y + z * z); |
474 | } |
475 | |
476 | inline FbxVector4 FbxRejection(const FbxVector4& a, const FbxVector4& b) |
477 | { |
478 | return a - b * (a.DotProduct(b) / b.DotProduct(b)); |
479 | } |
480 | |
481 | template<class T> inline int FbxBitCount(const T x) |
482 | { |
483 | int n = 0; |
484 | T c = x; |
485 | while( c ) |
486 | { |
487 | n += int(c & 1); |
488 | c = (c >> 1); |
489 | } |
490 | return n; |
491 | } |
492 | |
493 | template<class T> inline void FbxFixInfinite(T& x) |
494 | { |
495 | if( x != x || x > FbxMax(x) || x < -FbxMax(x) ) |
496 | { |
497 | x = T(0); |
498 | } |
499 | } |
500 | |
501 | template<class T> inline T FbxExp(const T x); |
502 | template<class T> inline T FbxLog(const T x); |
503 | template<class T> inline T FbxSin(const T x); |
504 | template<class T> inline T FbxCos(const T x); |
505 | template<class T> inline T FbxASin(const T x); |
506 | template<class T> inline T FbxACos(const T x); |
507 | template<class T> inline T FbxATan(const T x); |
508 | template<class T> inline T FbxATan(const T y, const T x); |
509 | |
510 | #include <fbxsdk/fbxsdk_nsend.h> |
511 | |
512 | #endif /* _FBXSDK_CORE_MATH_H_ */ |
513 | |