Matrix3.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Math/Vector3.h"
  5. namespace Urho3D
  6. {
  7. /// 3x3 matrix for rotation and scaling.
  8. class URHO3D_API Matrix3
  9. {
  10. public:
  11. /// Construct an identity matrix.
  12. Matrix3() noexcept :
  13. m00_(1.0f),
  14. m01_(0.0f),
  15. m02_(0.0f),
  16. m10_(0.0f),
  17. m11_(1.0f),
  18. m12_(0.0f),
  19. m20_(0.0f),
  20. m21_(0.0f),
  21. m22_(1.0f)
  22. {
  23. }
  24. /// Copy-construct from another matrix.
  25. Matrix3(const Matrix3& matrix) noexcept = default;
  26. /// Construct from values.
  27. Matrix3(float v00, float v01, float v02,
  28. float v10, float v11, float v12,
  29. float v20, float v21, float v22) noexcept :
  30. m00_(v00),
  31. m01_(v01),
  32. m02_(v02),
  33. m10_(v10),
  34. m11_(v11),
  35. m12_(v12),
  36. m20_(v20),
  37. m21_(v21),
  38. m22_(v22)
  39. {
  40. }
  41. /// Construct from a float array.
  42. explicit Matrix3(const float* data) noexcept :
  43. m00_(data[0]),
  44. m01_(data[1]),
  45. m02_(data[2]),
  46. m10_(data[3]),
  47. m11_(data[4]),
  48. m12_(data[5]),
  49. m20_(data[6]),
  50. m21_(data[7]),
  51. m22_(data[8])
  52. {
  53. }
  54. /// Assign from another matrix.
  55. Matrix3& operator =(const Matrix3& rhs) noexcept = default;
  56. /// Test for equality with another matrix without epsilon.
  57. bool operator ==(const Matrix3& rhs) const
  58. {
  59. const float* leftData = Data();
  60. const float* rightData = rhs.Data();
  61. for (unsigned i = 0; i < 9; ++i)
  62. {
  63. if (leftData[i] != rightData[i])
  64. return false;
  65. }
  66. return true;
  67. }
  68. /// Test for inequality with another matrix without epsilon.
  69. bool operator !=(const Matrix3& rhs) const { return !(*this == rhs); }
  70. /// Multiply a Vector3.
  71. Vector3 operator *(const Vector3& rhs) const
  72. {
  73. return Vector3(
  74. m00_ * rhs.x_ + m01_ * rhs.y_ + m02_ * rhs.z_,
  75. m10_ * rhs.x_ + m11_ * rhs.y_ + m12_ * rhs.z_,
  76. m20_ * rhs.x_ + m21_ * rhs.y_ + m22_ * rhs.z_
  77. );
  78. }
  79. /// Add a matrix.
  80. Matrix3 operator +(const Matrix3& rhs) const
  81. {
  82. return Matrix3(
  83. m00_ + rhs.m00_,
  84. m01_ + rhs.m01_,
  85. m02_ + rhs.m02_,
  86. m10_ + rhs.m10_,
  87. m11_ + rhs.m11_,
  88. m12_ + rhs.m12_,
  89. m20_ + rhs.m20_,
  90. m21_ + rhs.m21_,
  91. m22_ + rhs.m22_
  92. );
  93. }
  94. /// Subtract a matrix.
  95. Matrix3 operator -(const Matrix3& rhs) const
  96. {
  97. return Matrix3(
  98. m00_ - rhs.m00_,
  99. m01_ - rhs.m01_,
  100. m02_ - rhs.m02_,
  101. m10_ - rhs.m10_,
  102. m11_ - rhs.m11_,
  103. m12_ - rhs.m12_,
  104. m20_ - rhs.m20_,
  105. m21_ - rhs.m21_,
  106. m22_ - rhs.m22_
  107. );
  108. }
  109. /// Multiply with a scalar.
  110. Matrix3 operator *(float rhs) const
  111. {
  112. return Matrix3(
  113. m00_ * rhs,
  114. m01_ * rhs,
  115. m02_ * rhs,
  116. m10_ * rhs,
  117. m11_ * rhs,
  118. m12_ * rhs,
  119. m20_ * rhs,
  120. m21_ * rhs,
  121. m22_ * rhs
  122. );
  123. }
  124. /// Multiply a matrix.
  125. Matrix3 operator *(const Matrix3& rhs) const
  126. {
  127. return Matrix3(
  128. m00_ * rhs.m00_ + m01_ * rhs.m10_ + m02_ * rhs.m20_,
  129. m00_ * rhs.m01_ + m01_ * rhs.m11_ + m02_ * rhs.m21_,
  130. m00_ * rhs.m02_ + m01_ * rhs.m12_ + m02_ * rhs.m22_,
  131. m10_ * rhs.m00_ + m11_ * rhs.m10_ + m12_ * rhs.m20_,
  132. m10_ * rhs.m01_ + m11_ * rhs.m11_ + m12_ * rhs.m21_,
  133. m10_ * rhs.m02_ + m11_ * rhs.m12_ + m12_ * rhs.m22_,
  134. m20_ * rhs.m00_ + m21_ * rhs.m10_ + m22_ * rhs.m20_,
  135. m20_ * rhs.m01_ + m21_ * rhs.m11_ + m22_ * rhs.m21_,
  136. m20_ * rhs.m02_ + m21_ * rhs.m12_ + m22_ * rhs.m22_
  137. );
  138. }
  139. /// Set scaling elements.
  140. void SetScale(const Vector3& scale)
  141. {
  142. m00_ = scale.x_;
  143. m11_ = scale.y_;
  144. m22_ = scale.z_;
  145. }
  146. /// Set uniform scaling elements.
  147. void SetScale(float scale)
  148. {
  149. m00_ = scale;
  150. m11_ = scale;
  151. m22_ = scale;
  152. }
  153. /// Return the scaling part.
  154. Vector3 Scale() const
  155. {
  156. return Vector3(
  157. sqrtf(m00_ * m00_ + m10_ * m10_ + m20_ * m20_),
  158. sqrtf(m01_ * m01_ + m11_ * m11_ + m21_ * m21_),
  159. sqrtf(m02_ * m02_ + m12_ * m12_ + m22_ * m22_)
  160. );
  161. }
  162. /// Return the scaling part with the sign. Reference rotation matrix is required to avoid ambiguity.
  163. Vector3 SignedScale(const Matrix3& rotation) const
  164. {
  165. return Vector3(
  166. rotation.m00_ * m00_ + rotation.m10_ * m10_ + rotation.m20_ * m20_,
  167. rotation.m01_ * m01_ + rotation.m11_ * m11_ + rotation.m21_ * m21_,
  168. rotation.m02_ * m02_ + rotation.m12_ * m12_ + rotation.m22_ * m22_
  169. );
  170. }
  171. /// Return transposed.
  172. Matrix3 Transpose() const
  173. {
  174. return Matrix3(
  175. m00_,
  176. m10_,
  177. m20_,
  178. m01_,
  179. m11_,
  180. m21_,
  181. m02_,
  182. m12_,
  183. m22_
  184. );
  185. }
  186. /// Return scaled by a vector.
  187. Matrix3 Scaled(const Vector3& scale) const
  188. {
  189. return Matrix3(
  190. m00_ * scale.x_,
  191. m01_ * scale.y_,
  192. m02_ * scale.z_,
  193. m10_ * scale.x_,
  194. m11_ * scale.y_,
  195. m12_ * scale.z_,
  196. m20_ * scale.x_,
  197. m21_ * scale.y_,
  198. m22_ * scale.z_
  199. );
  200. }
  201. /// Test for equality with another matrix with epsilon.
  202. bool Equals(const Matrix3& rhs) const
  203. {
  204. const float* leftData = Data();
  205. const float* rightData = rhs.Data();
  206. for (unsigned i = 0; i < 9; ++i)
  207. {
  208. if (!Urho3D::Equals(leftData[i], rightData[i]))
  209. return false;
  210. }
  211. return true;
  212. }
  213. /// Return inverse.
  214. Matrix3 Inverse() const;
  215. /// Return float data.
  216. const float* Data() const { return &m00_; }
  217. /// Return matrix element.
  218. float Element(unsigned i, unsigned j) const { return Data()[i * 3 + j]; }
  219. /// Return matrix row.
  220. Vector3 Row(unsigned i) const { return Vector3(Element(i, 0), Element(i, 1), Element(i, 2)); }
  221. /// Return matrix column.
  222. Vector3 Column(unsigned j) const { return Vector3(Element(0, j), Element(1, j), Element(2, j)); }
  223. /// Return whether any element is NaN.
  224. bool IsNaN() const
  225. {
  226. const float* data = Data();
  227. for (unsigned i = 0; i < 9; ++i)
  228. {
  229. if (Urho3D::IsNaN(data[i]))
  230. return true;
  231. }
  232. return false;
  233. }
  234. /// Return whether any element is Inf.
  235. bool IsInf() const
  236. {
  237. const float* data = Data();
  238. for (unsigned i = 0; i < 9; ++i)
  239. {
  240. if (Urho3D::IsInf(data[i]))
  241. return true;
  242. }
  243. return false;
  244. }
  245. /// Return as string.
  246. String ToString() const;
  247. float m00_;
  248. float m01_;
  249. float m02_;
  250. float m10_;
  251. float m11_;
  252. float m12_;
  253. float m20_;
  254. float m21_;
  255. float m22_;
  256. /// Bulk transpose matrices.
  257. static void BulkTranspose(float* dest, const float* src, unsigned count)
  258. {
  259. for (unsigned i = 0; i < count; ++i)
  260. {
  261. dest[0] = src[0];
  262. dest[1] = src[3];
  263. dest[2] = src[6];
  264. dest[3] = src[1];
  265. dest[4] = src[4];
  266. dest[5] = src[7];
  267. dest[6] = src[2];
  268. dest[7] = src[5];
  269. dest[8] = src[8];
  270. dest += 9;
  271. src += 9;
  272. }
  273. }
  274. /// Zero matrix.
  275. static const Matrix3 ZERO;
  276. /// Identity matrix.
  277. static const Matrix3 IDENTITY;
  278. };
  279. /// Multiply a 3x3 matrix with a scalar.
  280. inline Matrix3 operator *(float lhs, const Matrix3& rhs) { return rhs * lhs; }
  281. }