Axisang.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. /// Axis angles. Used in rotations.
  11. template<typename T>
  12. class TAxisang
  13. {
  14. public:
  15. /// @name Constructors
  16. /// @{
  17. TAxisang()
  18. {
  19. }
  20. TAxisang(const TAxisang& b)
  21. : m_ang(b.m_ang)
  22. , m_axis(b.m_axis)
  23. {
  24. }
  25. TAxisang(const T rad, const TVec<T, 3>& axis)
  26. : m_ang(rad)
  27. , m_axis(axis)
  28. {
  29. }
  30. explicit TAxisang(const TQuat<T>& q)
  31. {
  32. m_ang = T(2) * acos<T>(q.w());
  33. T length = sqrt<T>(T(1) - q.w() * q.w());
  34. if(!isZero<T>(length))
  35. {
  36. length = T(1) / length;
  37. m_axis = TVec<T, 3>(q.x() * length, q.y() * length, q.z() * length);
  38. }
  39. else
  40. {
  41. m_axis = TVec<T, 3>(T(0));
  42. }
  43. }
  44. explicit TAxisang(const TMat<T, 3, 3>& m3)
  45. {
  46. if(isZero<T>(m3(0, 1) - m3(1, 0)) && isZero<T>(m3(0, 2) - m3(2, 0)) && isZero<T>(m3(1, 2) - m3(2, 1)))
  47. {
  48. if((absolute<T>(m3(0, 1) + m3(1, 0)) < T(0.1)) && (absolute<T>(m3(0, 2) + m3(2, 0)) < T(0.1))
  49. && (absolute<T>(m3(1, 2) + m3(2, 1)) < T(0.1))
  50. && (absolute<T>(m3(0, 0) + m3(1, 1) + m3(2, 2)) - 3) < T(0.1))
  51. {
  52. m_axis = TVec<T, 3>(T(1), T(0), T(0));
  53. m_ang = T(0);
  54. return;
  55. }
  56. m_ang = PI;
  57. m_axis.x() = (m3(0, 0) + T(1)) / T(2);
  58. if(m_axis.x() > T(0))
  59. {
  60. m_axis.x() = sqrt(m_axis.x());
  61. }
  62. else
  63. {
  64. m_axis.x() = T(0);
  65. }
  66. m_axis.y() = (m3(1, 1) + T(1)) / T(2);
  67. if(m_axis.y() > T(0))
  68. {
  69. m_axis.y() = sqrt(m_axis.y());
  70. }
  71. else
  72. {
  73. m_axis.y() = T(0);
  74. }
  75. m_axis.z() = (m3(2, 2) + T(1)) / T(2);
  76. if(m_axis.z() > T(0))
  77. {
  78. m_axis.z() = sqrt(m_axis.z());
  79. }
  80. else
  81. {
  82. m_axis.z() = T(0);
  83. }
  84. const Bool xZero = isZero<T>(m_axis.x());
  85. const Bool yZero = isZero<T>(m_axis.y());
  86. const Bool zZero = isZero<T>(m_axis.z());
  87. const Bool xyPositive = (m3(0, 1) > T(0));
  88. const Bool xzPositive = (m3(0, 2) > T(0));
  89. const Bool yzPositive = (m3(1, 2) > T(0));
  90. if(xZero && !yZero && !zZero)
  91. {
  92. if(!yzPositive)
  93. {
  94. m_axis.y() = -m_axis.y();
  95. }
  96. }
  97. else if(yZero && !zZero)
  98. {
  99. if(!xzPositive)
  100. {
  101. m_axis.z() = -m_axis.z();
  102. }
  103. }
  104. else if(zZero)
  105. {
  106. if(!xyPositive)
  107. {
  108. m_axis.x() = -m_axis.x();
  109. }
  110. }
  111. return;
  112. }
  113. T s = sqrt((m3(2, 1) - m3(1, 2)) * (m3(2, 1) - m3(1, 2)) + (m3(0, 2) - m3(2, 0)) * (m3(0, 2) - m3(2, 0))
  114. + (m3(1, 0) - m3(0, 1)) * (m3(1, 0) - m3(0, 1)));
  115. if(absolute(s) < T(0.001))
  116. {
  117. s = T(1);
  118. }
  119. m_ang = acos<T>((m3(0, 0) + m3(1, 1) + m3(2, 2) - T(1)) / T(2));
  120. m_axis.x() = (m3(2, 1) - m3(1, 2)) / s;
  121. m_axis.y() = (m3(0, 2) - m3(2, 0)) / s;
  122. m_axis.z() = (m3(1, 0) - m3(0, 1)) / s;
  123. }
  124. /// @}
  125. /// @name Accessors
  126. /// @{
  127. T getAngle() const
  128. {
  129. return m_ang;
  130. }
  131. T& getAngle()
  132. {
  133. return m_ang;
  134. }
  135. void setAngle(const T a)
  136. {
  137. m_ang = a;
  138. }
  139. const TVec<T, 3>& getAxis() const
  140. {
  141. return m_axis;
  142. }
  143. TVec<T, 3>& getAxis()
  144. {
  145. return m_axis;
  146. }
  147. void setAxis(const TVec<T, 3>& a)
  148. {
  149. m_axis = a;
  150. }
  151. /// @}
  152. /// @name Operators with same type
  153. /// @{
  154. TAxisang& operator=(const TAxisang& b)
  155. {
  156. m_ang = b.m_ang;
  157. m_axis = b.m_axis;
  158. return *this;
  159. }
  160. /// @}
  161. /// @name Other
  162. /// @{
  163. ANKI_ENABLE_METHOD(std::is_floating_point<T>::value)
  164. void toString(StringAuto& str) const
  165. {
  166. str.sprintf("%f %f %f | %f", m_axis.x(), m_axis.y(), m_axis.z(), m_ang);
  167. }
  168. /// @}
  169. private:
  170. /// @name Data
  171. /// @{
  172. T m_ang;
  173. TVec<T, 3> m_axis;
  174. /// @}
  175. };
  176. /// F32 Axisang
  177. using Axisang = TAxisang<F32>;
  178. /// F64 Axisang
  179. using DAxisang = TAxisang<F64>;
  180. /// @}
  181. } // end namespace anki