Axisang.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Copyright (C) 2009-present, 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)) && (absolute<T>(m3(0, 0) + m3(1, 1) + m3(2, 2)) - 3) < T(0.1))
  50. {
  51. m_axis = TVec<T, 3>(T(1), T(0), T(0));
  52. m_ang = T(0);
  53. return;
  54. }
  55. m_ang = kPi;
  56. m_axis.x = (m3(0, 0) + T(1)) / T(2);
  57. if(m_axis.x > T(0))
  58. {
  59. m_axis.x = sqrt(m_axis.x);
  60. }
  61. else
  62. {
  63. m_axis.x = T(0);
  64. }
  65. m_axis.y = (m3(1, 1) + T(1)) / T(2);
  66. if(m_axis.y > T(0))
  67. {
  68. m_axis.y = sqrt(m_axis.y);
  69. }
  70. else
  71. {
  72. m_axis.y = T(0);
  73. }
  74. m_axis.z = (m3(2, 2) + T(1)) / T(2);
  75. if(m_axis.z > T(0))
  76. {
  77. m_axis.z = sqrt(m_axis.z);
  78. }
  79. else
  80. {
  81. m_axis.z = T(0);
  82. }
  83. const Bool xZero = isZero<T>(m_axis.x);
  84. const Bool yZero = isZero<T>(m_axis.y);
  85. const Bool zZero = isZero<T>(m_axis.z);
  86. const Bool xyPositive = (m3(0, 1) > T(0));
  87. const Bool xzPositive = (m3(0, 2) > T(0));
  88. const Bool yzPositive = (m3(1, 2) > T(0));
  89. if(xZero && !yZero && !zZero)
  90. {
  91. if(!yzPositive)
  92. {
  93. m_axis.y = -m_axis.y;
  94. }
  95. }
  96. else if(yZero && !zZero)
  97. {
  98. if(!xzPositive)
  99. {
  100. m_axis.z = -m_axis.z;
  101. }
  102. }
  103. else if(zZero)
  104. {
  105. if(!xyPositive)
  106. {
  107. m_axis.x = -m_axis.x;
  108. }
  109. }
  110. return;
  111. }
  112. 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))
  113. + (m3(1, 0) - m3(0, 1)) * (m3(1, 0) - m3(0, 1)));
  114. if(absolute(s) < T(0.001))
  115. {
  116. s = T(1);
  117. }
  118. m_ang = acos<T>((m3(0, 0) + m3(1, 1) + m3(2, 2) - T(1)) / T(2));
  119. m_axis.x = (m3(2, 1) - m3(1, 2)) / s;
  120. m_axis.y = (m3(0, 2) - m3(2, 0)) / s;
  121. m_axis.z = (m3(1, 0) - m3(0, 1)) / s;
  122. }
  123. /// @}
  124. /// @name Accessors
  125. /// @{
  126. T getAngle() const
  127. {
  128. return m_ang;
  129. }
  130. T& getAngle()
  131. {
  132. return m_ang;
  133. }
  134. void setAngle(const T a)
  135. {
  136. m_ang = a;
  137. }
  138. const TVec<T, 3>& getAxis() const
  139. {
  140. return m_axis;
  141. }
  142. TVec<T, 3>& getAxis()
  143. {
  144. return m_axis;
  145. }
  146. void setAxis(const TVec<T, 3>& a)
  147. {
  148. m_axis = a;
  149. }
  150. /// @}
  151. /// @name Operators with same type
  152. /// @{
  153. TAxisang& operator=(const TAxisang& b)
  154. {
  155. m_ang = b.m_ang;
  156. m_axis = b.m_axis;
  157. return *this;
  158. }
  159. /// @}
  160. /// @name Other
  161. /// @{
  162. String toString() const requires(std::is_floating_point<T>::value)
  163. {
  164. return String().sprintf("%f %f %f | %f", m_axis.x, m_axis.y, m_axis.z, m_ang);
  165. }
  166. /// @}
  167. private:
  168. /// @name Data
  169. /// @{
  170. T m_ang;
  171. TVec<T, 3> m_axis;
  172. /// @}
  173. };
  174. /// F32 Axisang
  175. using Axisang = TAxisang<F32>;
  176. /// F64 Axisang
  177. using DAxisang = TAxisang<F64>;
  178. /// @}
  179. } // end namespace anki