Euler.h 2.7 KB

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