Transform.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright (C) 2009-2022, 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. /// Transformation
  11. template<typename T>
  12. class TTransform
  13. {
  14. public:
  15. /// @name Constructors
  16. /// @{
  17. TTransform()
  18. {
  19. }
  20. TTransform(const TTransform& b)
  21. : m_origin(b.m_origin)
  22. , m_rotation(b.m_rotation)
  23. , m_scale(b.m_scale)
  24. {
  25. checkW();
  26. }
  27. explicit TTransform(const TMat<T, 4, 4>& m4)
  28. {
  29. const TVec<T, 3> s0 = m4.getColumn(0).xyz();
  30. const TVec<T, 3> s1 = m4.getColumn(1).xyz();
  31. const TVec<T, 3> s2 = m4.getColumn(2).xyz();
  32. const TVec<T, 3> scales(s0.getLength(), s1.getLength(), s2.getLength());
  33. [[maybe_unused]] const T E = T(0.001);
  34. ANKI_ASSERT(isZero(scales.x() - scales.y(), E) && isZero(scales.y() - scales.z(), E)
  35. && "Expecting uniform scale");
  36. m_rotation.setColumns(s0 / scales.x(), s1 / scales.x(), s2 / scales.x(), TVec<T, 3>(T(0)));
  37. m_origin = m4.getTranslationPart().xyz0();
  38. m_scale = scales.x();
  39. checkW();
  40. }
  41. TTransform(const TVec<T, 4>& origin, const TMat<T, 3, 4>& rotation, const T scale)
  42. : m_origin(origin)
  43. , m_rotation(rotation)
  44. , m_scale(scale)
  45. {
  46. checkW();
  47. }
  48. explicit TTransform(const TVec<T, 4>& origin)
  49. : m_origin(origin)
  50. , m_rotation(TMat<T, 3, 4>::getIdentity())
  51. , m_scale(T(1))
  52. {
  53. checkW();
  54. }
  55. explicit TTransform(const TMat<T, 3, 4>& rotation)
  56. : m_origin(TVec<T, 4>(T(0)))
  57. , m_rotation(rotation)
  58. , m_scale(T(1))
  59. {
  60. checkW();
  61. }
  62. TTransform(const T scale)
  63. : m_origin(TVec<T, 4>(T(0)))
  64. , m_rotation(TMat<T, 3, 4>::getIdentity())
  65. , m_scale(scale)
  66. {
  67. checkW();
  68. }
  69. /// @}
  70. /// @name Accessors
  71. /// @{
  72. const TVec<T, 4>& getOrigin() const
  73. {
  74. return m_origin;
  75. }
  76. TVec<T, 4>& getOrigin()
  77. {
  78. return m_origin;
  79. }
  80. void setOrigin(const TVec<T, 4>& o)
  81. {
  82. m_origin = o;
  83. checkW();
  84. }
  85. const TMat<T, 3, 4>& getRotation() const
  86. {
  87. return m_rotation;
  88. }
  89. TMat<T, 3, 4>& getRotation()
  90. {
  91. return m_rotation;
  92. }
  93. void setRotation(const TMat<T, 3, 4>& r)
  94. {
  95. m_rotation = r;
  96. }
  97. T getScale() const
  98. {
  99. return m_scale;
  100. }
  101. T& getScale()
  102. {
  103. return m_scale;
  104. }
  105. void setScale(const T s)
  106. {
  107. m_scale = s;
  108. }
  109. /// @}
  110. /// @name Operators with same type
  111. /// @{
  112. TTransform& operator=(const TTransform& b)
  113. {
  114. m_origin = b.m_origin;
  115. m_rotation = b.m_rotation;
  116. m_scale = b.m_scale;
  117. checkW();
  118. return *this;
  119. }
  120. Bool operator==(const TTransform& b) const
  121. {
  122. return m_origin == b.m_origin && m_rotation == b.m_rotation && m_scale == b.m_scale;
  123. }
  124. Bool operator!=(const TTransform& b) const
  125. {
  126. return !operator==(b);
  127. }
  128. /// @}
  129. /// @name Other
  130. /// @{
  131. void setIdentity()
  132. {
  133. (*this) = getIdentity();
  134. }
  135. static TTransform getIdentity()
  136. {
  137. return TTransform(TVec<T, 4>(T(0)), TMat<T, 3, 4>::getIdentity(), T(1));
  138. }
  139. /// @copybrief combineTTransformations
  140. TTransform combineTransformations(const TTransform& b) const
  141. {
  142. checkW();
  143. const TTransform& a = *this;
  144. TTransform out;
  145. out.m_origin = TVec<T, 4>(a.m_rotation * (b.m_origin * a.m_scale), T(0)) + a.m_origin;
  146. out.m_rotation = a.m_rotation.combineTransformations(b.m_rotation);
  147. out.m_scale = a.m_scale * b.m_scale;
  148. return out;
  149. }
  150. /// Get the inverse transformation. Its faster that inverting a Mat4
  151. TTransform getInverse() const
  152. {
  153. checkW();
  154. TTransform o;
  155. o.m_rotation = m_rotation;
  156. o.m_rotation.transposeRotationPart();
  157. o.m_scale = T(1) / m_scale;
  158. o.m_origin = -(o.m_rotation * (o.m_scale * m_origin)).xyz0();
  159. return o;
  160. }
  161. void invert()
  162. {
  163. m_rotation.transposeRotationPart();
  164. m_scale = T(1) / m_scale;
  165. m_origin = -(m_rotation * (m_scale * m_origin));
  166. }
  167. /// Transform a TVec3
  168. TVec<T, 3> transform(const TVec<T, 3>& b) const
  169. {
  170. checkW();
  171. return (m_rotation.getRotationPart() * (b * m_scale)) + m_origin.xyz();
  172. }
  173. /// Transform a TVec4. SIMD optimized
  174. TVec<T, 4> transform(const TVec<T, 4>& b) const
  175. {
  176. checkW();
  177. TVec<T, 4> out = TVec<T, 4>(m_rotation * (b * m_scale), T(0)) + m_origin;
  178. return out;
  179. }
  180. template<U VEC_DIMS>
  181. TTransform& lookAt(const TVec<T, VEC_DIMS>& refPoint, const TVec<T, VEC_DIMS>& up)
  182. {
  183. const TVec<T, 4> j = up.xyz0();
  184. const TVec<T, 4> vdir = (refPoint.xyz0() - m_origin).getNormalized();
  185. const TVec<T, 4> vup = (j - vdir * j.dot(vdir)).getNormalized();
  186. const TVec<T, 4> vside = vdir.cross(vup);
  187. m_rotation.setColumns(vside.xyz(), vup.xyz(), (-vdir).xyz());
  188. return *this;
  189. }
  190. ANKI_ENABLE_METHOD(std::is_floating_point<T>::value) void toString(StringAuto& str) const
  191. {
  192. StringAuto b(str.getAllocator());
  193. m_origin.toString(b);
  194. str.append(b);
  195. str.append("\n");
  196. b.destroy();
  197. m_rotation.toString(b);
  198. str.append(b);
  199. str.append("\n");
  200. b.destroy();
  201. b.sprintf("%f", m_scale);
  202. str.append(b);
  203. }
  204. /// @}
  205. private:
  206. /// @name Data
  207. /// @{
  208. TVec<T, 4> m_origin; ///< The rotation
  209. TMat<T, 3, 4> m_rotation; ///< The translation
  210. T m_scale; ///< The uniform scaling
  211. /// @}
  212. void checkW() const
  213. {
  214. ANKI_ASSERT(m_origin.w() == T(0));
  215. }
  216. };
  217. /// F32 transformation
  218. using Transform = TTransform<F32>;
  219. /// F64 transformation
  220. using DTransform = TTransform<F64>;
  221. /// @}
  222. } // end namespace anki