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
70class FBXSDK_DLL FbxEuler
71{
72public:
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
100private:
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. */
121enum 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
131extern FBXSDK_DLL const FbxDouble FbxIdentityMatrix[4][4];
132extern FBXSDK_DLL const FbxVector4 FbxZeroVector4;
133
134inline float FbxFloor(const float x)
135{
136 return float(floor(x));
137}
138
139inline double FbxFloor(const double x)
140{
141 return floor(x);
142}
143
144inline float FbxCeil(const float x)
145{
146 return float(ceil(x));
147}
148
149inline double FbxCeil(const double x)
150{
151 return ceil(x);
152}
153
154template<class T> inline T FbxSign(const T x)
155{
156 return (x < 0) ? T(-1) : T(1);
157}
158
159template<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
165inline FbxUChar FbxAbs(const FbxUChar x)
166{
167 return x;
168}
169
170inline FbxUShort FbxAbs(const FbxUShort x)
171{
172 return x;
173}
174
175inline 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
187inline FbxULongLong FbxAbs(const FbxULongLong x)
188{
189 return x;
190}
191
192inline FbxFloat FbxAbs(const FbxFloat x)
193{
194 return (FbxFloat)fabs(x);
195}
196
197inline FbxDouble FbxAbs(const FbxDouble x)
198{
199 return fabs(x);
200}
201
202template<class T> inline T FbxAbs(const T x)
203{
204 return (x >= 0) ? x : ((x > FbxMin(x)) ? -x : FbxMax(x));
205}
206
207template<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
212template<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
217inline 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
222inline 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
227inline 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
232inline 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
237inline 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
242inline 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
247inline 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
252inline 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
257inline FbxDouble FbxMod(const FbxFloat x, FbxFloat& i)
258{
259 return modff(x, &i);
260}
261
262inline FbxDouble FbxMod(const FbxDouble x, FbxDouble& i)
263{
264 return modf(x, &i);
265}
266
267inline FbxDouble FbxMod(const FbxFloat x)
268{
269 FbxFloat i;
270 return modff(x, &i);
271}
272
273inline FbxDouble FbxMod(const FbxDouble x)
274{
275 FbxDouble i;
276 return modf(x, &i);
277}
278
279template<class T> inline T FbxReciprocal(const T x)
280{
281 return T(1) / x;
282}
283
284inline double FbxSqrt(const double x)
285{
286 return sqrt(x);
287}
288
289inline float FbxSqrt(const float x)
290{
291 return sqrtf(x);
292}
293
294template<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
314inline float FbxExp(const float x)
315{
316 return expf(x);
317}
318
319inline double FbxExp(const double x)
320{
321 return exp(x);
322}
323
324inline float FbxLog(const float x)
325{
326 return float(log(x));
327}
328
329inline double FbxLog(const double x)
330{
331 return log(x);
332}
333
334template<class T> inline T FbxPow(const T x, const T y)
335{
336 return (T)FbxExp(y * FbxLog((double)x));
337}
338
339template<class T> inline T FbxLog2(const T x)
340{
341 return (T)(FbxLog(x) * FBXSDK_1_DIV_LN2);
342}
343
344inline float FbxSin(const float x)
345{
346 return sinf(x);
347}
348
349inline double FbxSin(const double x)
350{
351 return sin(x);
352}
353
354inline float FbxCos(const float x)
355{
356 return cosf(x);
357}
358
359inline double FbxCos(const double x)
360{
361 return cos(x);
362}
363
364inline float FbxTan(const float x)
365{
366 return tanf(x);
367}
368
369inline double FbxTan(const double x)
370{
371 return tan(x);
372}
373
374// *y = cos(x), sin(x)
375template<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)
381template<class T> inline T FbxSinCosd(const T x, T* y)
382{
383 return FbxSinCos(T(x * FBXSDK_PI_DIV_180), y);
384}
385
386inline float FbxASin(const float x)
387{
388 return asinf(x);
389}
390
391inline double FbxASin(const double x)
392{
393 return asin(x);
394}
395
396template<class T> inline T FbxASind(const T x)
397{
398 return (T)(FbxASin((double)x) * FBXSDK_180_DIV_PI);
399}
400
401inline float FbxACos(const float x)
402{
403 return acosf(x);
404}
405
406inline double FbxACos(const double x)
407{
408 return acos(x);
409}
410
411template<class T> inline T FbxACosd(const T x)
412{
413 return (T)(FbxACos(x) * FBXSDK_180_DIV_PI);
414}
415
416inline float FbxATan(const float x)
417{
418 return atanf(x);
419}
420
421inline double FbxATan(const double x)
422{
423 return atan(x);
424}
425
426template<class T> inline T FbxATand(const T x)
427{
428 return (T)(FbxATan(x) * FBXSDK_180_DIV_PI);
429}
430
431inline float FbxATan(const float y, const float x)
432{
433 return atan2f(y, x);
434}
435
436inline double FbxATan(const double y, const double x)
437{
438 return atan2(y, x);
439}
440
441template<class T> inline T FbxATand(const T y, const T x)
442{
443 return (T)(FbxATan(y, x) * FBXSDK_180_DIV_PI);
444}
445
446template<class T> inline T FbxNorm(const T x, const T y)
447{
448 return FbxSqrt(x * x + y * y);
449}
450
451template<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
456template<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
461template<class T> inline T FbxHypot(const T x, const T y)
462{
463 return FbxSqrt(x * x + y * y);
464}
465
466template<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
471template<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
476inline FbxVector4 FbxRejection(const FbxVector4& a, const FbxVector4& b)
477{
478 return a - b * (a.DotProduct(b) / b.DotProduct(b));
479}
480
481template<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
493template<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
501template<class T> inline T FbxExp(const T x);
502template<class T> inline T FbxLog(const T x);
503template<class T> inline T FbxSin(const T x);
504template<class T> inline T FbxCos(const T x);
505template<class T> inline T FbxASin(const T x);
506template<class T> inline T FbxACos(const T x);
507template<class T> inline T FbxATan(const T x);
508template<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