Axisang.h 3.6 KB

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