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