Transform.h 5.1 KB

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