Euler.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #ifndef ANKI_MATH_EULER_H
  2. #define ANKI_MATH_EULER_H
  3. #include "anki/math/CommonIncludes.h"
  4. namespace anki {
  5. /// @addtogroup Math
  6. /// @{
  7. /// Euler angles. Used for rotations. It cannot describe a rotation
  8. /// accurately though
  9. template<typename T>
  10. class TEuler
  11. {
  12. public:
  13. /// @name Constructors
  14. /// @{
  15. explicit TEuler()
  16. {
  17. x() = y() = z() = 0.0;
  18. }
  19. explicit TEuler(const T x_, const T y_, const T z_)
  20. {
  21. x() = x_;
  22. y() = y_;
  23. z() = z_;
  24. }
  25. TEuler(const TEuler& b)
  26. {
  27. x() = b.x();
  28. y() = b.y();
  29. z() = b.z();
  30. }
  31. explicit TEuler(const TQuat<T>& q)
  32. {
  33. T test = q.x() * q.y() + q.z() * q.w();
  34. if(test > 0.499)
  35. {
  36. y() = 2.0 * atan2<T>(q.x(), q.w());
  37. z() = getPi<T>() / 2.0;
  38. x() = 0.0;
  39. return;
  40. }
  41. if(test < -0.499)
  42. {
  43. y() = -2.0 * atan2<T>(q.x(), q.w());
  44. z() = -getPi<T>() / 2.0;
  45. x() = 0.0;
  46. return;
  47. }
  48. T sqx = q.x() * q.x();
  49. T sqy = q.y() * q.y();
  50. T sqz = q.z() * q.z();
  51. y() = atan2<T>(2.0 * q.y() * q.w() - 2.0 * q.x() * q.z(),
  52. 1.0 - 2.0 * sqy - 2.0 * sqz);
  53. z() = asin<T>(2.0 * test);
  54. x() = atan2<T>(2.0 * q.x() * q.w() - 2.0 * q.y() * q.z(),
  55. 1.0 - 2.0 * sqx - 2.0 * sqz);
  56. }
  57. explicit TEuler(const TMat3<T>& m3)
  58. {
  59. T cx, sx;
  60. T cy, sy;
  61. T cz, sz;
  62. sy = m3(0, 2);
  63. cy = sqrt<T>(1.0 - sy * sy);
  64. // normal case
  65. if (!isZero<T>(cy))
  66. {
  67. T factor = 1.0 / cy;
  68. sx = -m3(1, 2) * factor;
  69. cx = m3(2, 2) * factor;
  70. sz = -m3(0, 1) * factor;
  71. cz = m3(0, 0) * factor;
  72. }
  73. // x and z axes aligned
  74. else
  75. {
  76. sz = 0.0;
  77. cz = 1.0;
  78. sx = m3(2, 1);
  79. cx = m3(1, 1);
  80. }
  81. z() = atan2<T>(sz, cz);
  82. y() = atan2<T>(sy, cy);
  83. x() = atan2<T>(sx, cx);
  84. }
  85. /// @}
  86. /// @name Accessors
  87. /// @{
  88. T& operator [](const U i)
  89. {
  90. return arr[i];
  91. }
  92. T operator [](const U i) const
  93. {
  94. return arr[i];
  95. }
  96. T& x()
  97. {
  98. return vec.x;
  99. }
  100. T x() const
  101. {
  102. return vec.x;
  103. }
  104. T& y()
  105. {
  106. return vec.y;
  107. }
  108. T y() const
  109. {
  110. return vec.y;
  111. }
  112. T& z()
  113. {
  114. return vec.z;
  115. }
  116. T z() const
  117. {
  118. return vec.z;
  119. }
  120. /// @}
  121. /// @name Operators with same type
  122. /// @{
  123. TEuler& operator=(const TEuler& b)
  124. {
  125. x() = b.x();
  126. y() = b.y();
  127. z() = b.z();
  128. return *this;
  129. }
  130. /// @}
  131. /// @name Other
  132. /// @{
  133. std::string toString() const
  134. {
  135. std::string s = std::to_string(x()) + " " + std::to_string(y())
  136. + " " + std::to_string(z());
  137. return s;
  138. }
  139. /// @}
  140. private:
  141. /// @name Data
  142. /// @{
  143. union
  144. {
  145. struct
  146. {
  147. T x, y, z;
  148. } vec;
  149. Array<T, 3> arr;
  150. };
  151. /// @}
  152. };
  153. /// F32 Euler angles
  154. typedef TEuler<F32> Euler;
  155. /// @}
  156. } // end namespace anki
  157. #endif