Transform.h 5.1 KB

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