Euler.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Math/Common.h>
  7. namespace anki {
  8. /// @addtogroup math
  9. /// @{
  10. /// Euler angles. Used for rotations. It cannot describe a rotation accurately though.
  11. /// The 'x' denotes a rotation around x axis, 'y' around y axis and 'z' around z axis.
  12. template<typename T>
  13. class TEuler
  14. {
  15. public:
  16. /// @name Constructors
  17. /// @{
  18. TEuler()
  19. {
  20. }
  21. TEuler(const T x_, const T y_, const T z_)
  22. {
  23. x() = x_;
  24. y() = y_;
  25. z() = z_;
  26. }
  27. TEuler(const TEuler& b)
  28. {
  29. x() = b.x();
  30. y() = b.y();
  31. z() = b.z();
  32. }
  33. explicit TEuler(const TQuat<T>& q)
  34. {
  35. const T test = q.x() * q.y() + q.z() * q.w();
  36. if(test > T(0.499))
  37. {
  38. y() = T(2) * atan2<T>(q.x(), q.w());
  39. z() = PI / T(2);
  40. x() = T(0);
  41. }
  42. else if(test < T(-0.499))
  43. {
  44. y() = -T(2) * atan2<T>(q.x(), q.w());
  45. z() = -PI / T(2);
  46. x() = T(0);
  47. }
  48. else
  49. {
  50. const T sqx = q.x() * q.x();
  51. const T sqy = q.y() * q.y();
  52. const T sqz = q.z() * q.z();
  53. y() = atan2<T>(T(2) * q.y() * q.w() - T(2) * q.x() * q.z(), T(1) - T(2) * sqy - T(2) * sqz);
  54. z() = asin<T>(T(2) * test);
  55. x() = atan2<T>(T(2) * q.x() * q.w() - T(2) * q.y() * q.z(), T(1) - T(2) * sqx - T(2) * sqz);
  56. }
  57. }
  58. explicit TEuler(const TMat<T, 3, 3>& m3)
  59. {
  60. if(m3(1, 0) > T(0.998))
  61. {
  62. // Singularity at north pole
  63. y() = atan2(m3(0, 2), m3(2, 2));
  64. z() = PI / T(2);
  65. x() = T(0);
  66. }
  67. else if(m3(1, 0) < T(-0.998))
  68. {
  69. // Singularity at south pole
  70. y() = atan2(m3(0, 2), m3(2, 2));
  71. z() = -PI / T(2);
  72. x() = T(0);
  73. }
  74. else
  75. {
  76. y() = atan2(-m3(2, 0), m3(0, 0));
  77. z() = asin(m3(1, 0));
  78. x() = atan2(-m3(1, 2), m3(1, 1));
  79. }
  80. }
  81. /// @}
  82. /// @name Accessors
  83. /// @{
  84. T& operator[](const U i)
  85. {
  86. return m_arr[i];
  87. }
  88. T operator[](const U i) const
  89. {
  90. return m_arr[i];
  91. }
  92. T& x()
  93. {
  94. return m_vec.m_x;
  95. }
  96. T x() const
  97. {
  98. return m_vec.m_x;
  99. }
  100. T& y()
  101. {
  102. return m_vec.m_y;
  103. }
  104. T y() const
  105. {
  106. return m_vec.m_y;
  107. }
  108. T& z()
  109. {
  110. return m_vec.m_z;
  111. }
  112. T z() const
  113. {
  114. return m_vec.m_z;
  115. }
  116. /// @}
  117. /// @name Operators with same type
  118. /// @{
  119. TEuler& operator=(const TEuler& b)
  120. {
  121. x() = b.x();
  122. y() = b.y();
  123. z() = b.z();
  124. return *this;
  125. }
  126. /// @}
  127. /// @name Other
  128. /// @{
  129. ANKI_ENABLE_METHOD(std::is_floating_point<T>::value)
  130. void toString(StringAuto& str) const
  131. {
  132. str.sprintf("%f %f %f", m_vec.m_x, m_vec.m_y, m_vec.m_z);
  133. }
  134. /// @}
  135. private:
  136. /// @name Data
  137. /// @{
  138. struct Vec
  139. {
  140. T m_x, m_y, m_z;
  141. };
  142. union
  143. {
  144. Vec m_vec;
  145. Array<T, 3> m_arr;
  146. };
  147. /// @}
  148. };
  149. /// F32 Euler angles
  150. using Euler = TEuler<F32>;
  151. /// F64 Euler angles
  152. using DEuler = TEuler<F64>;
  153. /// @}
  154. } // end namespace anki