Transform.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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. // Transformation
  9. template<typename T>
  10. class TTransform
  11. {
  12. public:
  13. // Constructors //
  14. constexpr TTransform()
  15. : m_origin(T(0))
  16. , m_rotation(TMat<T, 3, 4>::getIdentity())
  17. , m_scale(T(1), T(1), T(1), T(0))
  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. check();
  26. }
  27. explicit TTransform(const TMat<T, 4, 4>& m4)
  28. {
  29. m_scale = m4.extractScale().xyz0;
  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. m_rotation.setColumns(s0 / m_scale.x, s1 / m_scale.y, s2 / m_scale.z, TVec<T, 3>(T(0)));
  34. m_origin = m4.getTranslationPart().xyz0;
  35. check();
  36. }
  37. TTransform(const TVec<T, 4>& origin, const TMat<T, 3, 4>& rotation, const TVec<T, 4>& scale)
  38. : m_origin(origin)
  39. , m_rotation(rotation)
  40. , m_scale(scale)
  41. {
  42. check();
  43. }
  44. TTransform(const TVec<T, 3>& origin, const TMat<T, 3, 3>& rotation, const TVec<T, 3>& scale)
  45. : TTransform(origin.xyz0, TMat<T, 3, 4>(TVec<T, 3>(T(0)), rotation), scale.xyz0)
  46. {
  47. check();
  48. }
  49. // Accessors //
  50. [[nodiscard]] const TVec<T, 4>& getOrigin() const
  51. {
  52. return m_origin;
  53. }
  54. void setOrigin(const TVec<T, 4>& o)
  55. {
  56. m_origin = o;
  57. check();
  58. }
  59. void setOrigin(const TVec<T, 3>& o)
  60. {
  61. m_origin = o.xyz0;
  62. }
  63. [[nodiscard]] const TMat<T, 3, 4>& getRotation() const
  64. {
  65. return m_rotation;
  66. }
  67. void setRotation(const TMat<T, 3, 4>& r)
  68. {
  69. m_rotation = r;
  70. }
  71. void setRotation(const TMat<T, 3, 3>& r)
  72. {
  73. m_rotation.setRotationPart(r);
  74. m_rotation.setTranslationPart(TVec<T, 3>(T(0)));
  75. }
  76. [[nodiscard]] const TVec<T, 4>& getScale() const
  77. {
  78. return m_scale;
  79. }
  80. void setScale(const TVec<T, 4>& s)
  81. {
  82. m_scale = s;
  83. check();
  84. }
  85. void setScale(const TVec<T, 3>& s)
  86. {
  87. m_scale = s.xyz0;
  88. check();
  89. }
  90. // Operators with same type //
  91. TTransform& operator=(const TTransform& b)
  92. {
  93. m_origin = b.m_origin;
  94. m_rotation = b.m_rotation;
  95. m_scale = b.m_scale;
  96. check();
  97. return *this;
  98. }
  99. Bool operator==(const TTransform& b) const
  100. {
  101. return m_origin == b.m_origin && m_rotation == b.m_rotation && m_scale == b.m_scale;
  102. }
  103. Bool operator!=(const TTransform& b) const
  104. {
  105. return !operator==(b);
  106. }
  107. // Other //
  108. void setIdentity()
  109. {
  110. (*this) = getIdentity();
  111. }
  112. [[nodiscard]] static TTransform getIdentity()
  113. {
  114. return TTransform();
  115. }
  116. // See combineTTransformations
  117. [[nodiscard]] TTransform combineTransformations(const TTransform& b) const
  118. {
  119. check();
  120. const TTransform& a = *this;
  121. TTransform out;
  122. out.m_origin = TVec<T, 4>(a.m_rotation * (b.m_origin * a.m_scale), T(0)) + a.m_origin;
  123. out.m_rotation = a.m_rotation.combineTransformations(b.m_rotation);
  124. out.m_scale = a.m_scale * b.m_scale;
  125. return out;
  126. }
  127. // Get the inverse transformation. Its faster that inverting a Mat4
  128. [[nodiscard]] TTransform invert() const
  129. {
  130. TTransform o;
  131. o.m_rotation = m_rotation;
  132. o.m_rotation.transposeRotationPart();
  133. o.m_scale = TVec<T, 4>(T(1), T(1), T(1), T(0)) / m_scale.xyz1;
  134. o.m_origin = -(o.m_rotation * (o.m_scale * m_origin)).xyz0;
  135. o.check();
  136. return o;
  137. }
  138. // Transform a TVec3
  139. [[nodiscard]] TVec<T, 3> transform(const TVec<T, 3>& b) const
  140. {
  141. check();
  142. return (m_rotation.getRotationPart() * (b * m_scale.xyz)) + m_origin.xyz;
  143. }
  144. // Transform a TVec4. SIMD optimized
  145. [[nodiscard]] TVec<T, 4> transform(const TVec<T, 4>& b) const
  146. {
  147. check();
  148. TVec<T, 4> out = TVec<T, 4>(m_rotation * (b * m_scale), T(0)) + m_origin;
  149. return out;
  150. }
  151. template<U32 kVecComponentCount>
  152. [[nodiscard]] TTransform lookAt(const TVec<T, kVecComponentCount>& refPoint, const TVec<T, kVecComponentCount>& up) const
  153. {
  154. const TVec<T, 4> j = up.xyz0;
  155. const TVec<T, 4> vdir = (refPoint.xyz0 - m_origin).normalize();
  156. const TVec<T, 4> vup = (j - vdir * j.dot(vdir)).normalize();
  157. const TVec<T, 4> vside = vdir.cross(vup);
  158. TTransform out;
  159. out.m_origin = m_origin;
  160. out.m_scale = m_scale;
  161. out.m_rotation.setColumns(vside.xyz, vup.xyz, (-vdir).xyz);
  162. return out;
  163. }
  164. [[nodiscard]] String toString() const requires(std::is_floating_point<T>::value)
  165. {
  166. String str;
  167. String b = String("origin: ") + m_origin.toString();
  168. str += b;
  169. str += "\nrotation:\n";
  170. b = m_rotation.toString();
  171. str += b;
  172. str += "\n";
  173. b = String().sprintf("scale: %f %f %f", m_scale.x, m_scale.y, m_scale.z);
  174. str += b;
  175. return str;
  176. }
  177. [[nodiscard]] Bool hasUniformScale() const
  178. {
  179. return m_scale.x == m_scale.y && m_scale.x == m_scale.z;
  180. }
  181. private:
  182. TVec<T, 4> m_origin; // The rotation
  183. TMat<T, 3, 4> m_rotation; // The translation
  184. TVec<T, 4> m_scale; // The scaling
  185. void check() const
  186. {
  187. ANKI_ASSERT(m_origin.w == T(0));
  188. using TT = TVec<T, 3>;
  189. [[maybe_unused]] TT t; // Shut up the compiler regarding TT
  190. ANKI_ASSERT(m_scale.w == T(0) && m_scale.xyz > T(0));
  191. }
  192. };
  193. using Transform = TTransform<F32>;
  194. using DTransform = TTransform<F64>;
  195. } // end namespace anki