Matrix3.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include "../Math/Vector3.h"
  24. namespace Atomic
  25. {
  26. /// 3x3 matrix for rotation and scaling.
  27. class ATOMIC_API Matrix3
  28. {
  29. public:
  30. /// Construct an identity matrix.
  31. Matrix3() :
  32. m00_(1.0f),
  33. m01_(0.0f),
  34. m02_(0.0f),
  35. m10_(0.0f),
  36. m11_(1.0f),
  37. m12_(0.0f),
  38. m20_(0.0f),
  39. m21_(0.0f),
  40. m22_(1.0f)
  41. {
  42. }
  43. /// Copy-construct from another matrix.
  44. Matrix3(const Matrix3& matrix) :
  45. m00_(matrix.m00_),
  46. m01_(matrix.m01_),
  47. m02_(matrix.m02_),
  48. m10_(matrix.m10_),
  49. m11_(matrix.m11_),
  50. m12_(matrix.m12_),
  51. m20_(matrix.m20_),
  52. m21_(matrix.m21_),
  53. m22_(matrix.m22_)
  54. {
  55. }
  56. /// Construct from values.
  57. Matrix3(float v00, float v01, float v02,
  58. float v10, float v11, float v12,
  59. float v20, float v21, float v22) :
  60. m00_(v00),
  61. m01_(v01),
  62. m02_(v02),
  63. m10_(v10),
  64. m11_(v11),
  65. m12_(v12),
  66. m20_(v20),
  67. m21_(v21),
  68. m22_(v22)
  69. {
  70. }
  71. /// Construct from a float array.
  72. explicit Matrix3(const float* data) :
  73. m00_(data[0]),
  74. m01_(data[1]),
  75. m02_(data[2]),
  76. m10_(data[3]),
  77. m11_(data[4]),
  78. m12_(data[5]),
  79. m20_(data[6]),
  80. m21_(data[7]),
  81. m22_(data[8])
  82. {
  83. }
  84. /// Assign from another matrix.
  85. Matrix3& operator =(const Matrix3& rhs)
  86. {
  87. m00_ = rhs.m00_;
  88. m01_ = rhs.m01_;
  89. m02_ = rhs.m02_;
  90. m10_ = rhs.m10_;
  91. m11_ = rhs.m11_;
  92. m12_ = rhs.m12_;
  93. m20_ = rhs.m20_;
  94. m21_ = rhs.m21_;
  95. m22_ = rhs.m22_;
  96. return *this;
  97. }
  98. /// Test for equality with another matrix without epsilon.
  99. bool operator ==(const Matrix3& rhs) const
  100. {
  101. const float* leftData = Data();
  102. const float* rightData = rhs.Data();
  103. for (unsigned i = 0; i < 9; ++i)
  104. {
  105. if (leftData[i] != rightData[i])
  106. return false;
  107. }
  108. return true;
  109. }
  110. /// Test for inequality with another matrix without epsilon.
  111. bool operator !=(const Matrix3& rhs) const { return !(*this == rhs); }
  112. /// Multiply a Vector3.
  113. Vector3 operator *(const Vector3& rhs) const
  114. {
  115. return Vector3(
  116. m00_ * rhs.x_ + m01_ * rhs.y_ + m02_ * rhs.z_,
  117. m10_ * rhs.x_ + m11_ * rhs.y_ + m12_ * rhs.z_,
  118. m20_ * rhs.x_ + m21_ * rhs.y_ + m22_ * rhs.z_
  119. );
  120. }
  121. /// Add a matrix.
  122. Matrix3 operator +(const Matrix3& rhs) const
  123. {
  124. return Matrix3(
  125. m00_ + rhs.m00_,
  126. m01_ + rhs.m01_,
  127. m02_ + rhs.m02_,
  128. m10_ + rhs.m10_,
  129. m11_ + rhs.m11_,
  130. m12_ + rhs.m12_,
  131. m20_ + rhs.m20_,
  132. m21_ + rhs.m21_,
  133. m22_ + rhs.m22_
  134. );
  135. }
  136. /// Subtract a matrix.
  137. Matrix3 operator -(const Matrix3& rhs) const
  138. {
  139. return Matrix3(
  140. m00_ - rhs.m00_,
  141. m01_ - rhs.m01_,
  142. m02_ - rhs.m02_,
  143. m10_ - rhs.m10_,
  144. m11_ - rhs.m11_,
  145. m12_ - rhs.m12_,
  146. m20_ - rhs.m20_,
  147. m21_ - rhs.m21_,
  148. m22_ - rhs.m22_
  149. );
  150. }
  151. /// Multiply with a scalar.
  152. Matrix3 operator *(float rhs) const
  153. {
  154. return Matrix3(
  155. m00_ * rhs,
  156. m01_ * rhs,
  157. m02_ * rhs,
  158. m10_ * rhs,
  159. m11_ * rhs,
  160. m12_ * rhs,
  161. m20_ * rhs,
  162. m21_ * rhs,
  163. m22_ * rhs
  164. );
  165. }
  166. /// Multiply a matrix.
  167. Matrix3 operator *(const Matrix3& rhs) const
  168. {
  169. return Matrix3(
  170. m00_ * rhs.m00_ + m01_ * rhs.m10_ + m02_ * rhs.m20_,
  171. m00_ * rhs.m01_ + m01_ * rhs.m11_ + m02_ * rhs.m21_,
  172. m00_ * rhs.m02_ + m01_ * rhs.m12_ + m02_ * rhs.m22_,
  173. m10_ * rhs.m00_ + m11_ * rhs.m10_ + m12_ * rhs.m20_,
  174. m10_ * rhs.m01_ + m11_ * rhs.m11_ + m12_ * rhs.m21_,
  175. m10_ * rhs.m02_ + m11_ * rhs.m12_ + m12_ * rhs.m22_,
  176. m20_ * rhs.m00_ + m21_ * rhs.m10_ + m22_ * rhs.m20_,
  177. m20_ * rhs.m01_ + m21_ * rhs.m11_ + m22_ * rhs.m21_,
  178. m20_ * rhs.m02_ + m21_ * rhs.m12_ + m22_ * rhs.m22_
  179. );
  180. }
  181. /// Set scaling elements.
  182. void SetScale(const Vector3& scale)
  183. {
  184. m00_ = scale.x_;
  185. m11_ = scale.y_;
  186. m22_ = scale.z_;
  187. }
  188. /// Set uniform scaling elements.
  189. void SetScale(float scale)
  190. {
  191. m00_ = scale;
  192. m11_ = scale;
  193. m22_ = scale;
  194. }
  195. /// Return the scaling part.
  196. Vector3 Scale() const
  197. {
  198. return Vector3(
  199. sqrtf(m00_ * m00_ + m10_ * m10_ + m20_ * m20_),
  200. sqrtf(m01_ * m01_ + m11_ * m11_ + m21_ * m21_),
  201. sqrtf(m02_ * m02_ + m12_ * m12_ + m22_ * m22_)
  202. );
  203. }
  204. /// Return the scaling part with the sign. Reference rotation matrix is required to avoid ambiguity.
  205. Vector3 SignedScale(const Matrix3& rotation) const
  206. {
  207. return Vector3(
  208. rotation.m00_ * m00_ + rotation.m10_ * m10_ + rotation.m20_ * m20_,
  209. rotation.m01_ * m01_ + rotation.m11_ * m11_ + rotation.m21_ * m21_,
  210. rotation.m02_ * m02_ + rotation.m12_ * m12_ + rotation.m22_ * m22_
  211. );
  212. }
  213. /// Return transposed.
  214. Matrix3 Transpose() const
  215. {
  216. return Matrix3(
  217. m00_,
  218. m10_,
  219. m20_,
  220. m01_,
  221. m11_,
  222. m21_,
  223. m02_,
  224. m12_,
  225. m22_
  226. );
  227. }
  228. /// Return scaled by a vector.
  229. Matrix3 Scaled(const Vector3& scale) const
  230. {
  231. return Matrix3(
  232. m00_ * scale.x_,
  233. m01_ * scale.y_,
  234. m02_ * scale.z_,
  235. m10_ * scale.x_,
  236. m11_ * scale.y_,
  237. m12_ * scale.z_,
  238. m20_ * scale.x_,
  239. m21_ * scale.y_,
  240. m22_ * scale.z_
  241. );
  242. }
  243. /// Test for equality with another matrix with epsilon.
  244. bool Equals(const Matrix3& rhs) const
  245. {
  246. const float* leftData = Data();
  247. const float* rightData = rhs.Data();
  248. for (unsigned i = 0; i < 9; ++i)
  249. {
  250. if (!Atomic::Equals(leftData[i], rightData[i]))
  251. return false;
  252. }
  253. return true;
  254. }
  255. /// Return inverse.
  256. Matrix3 Inverse() const;
  257. /// Return float data.
  258. const float* Data() const { return &m00_; }
  259. /// Return matrix element.
  260. float Element(unsigned i, unsigned j) const { return Data()[i * 3 + j]; }
  261. /// Return matrix row.
  262. Vector3 Row(unsigned i) const { return Vector3(Element(i, 0), Element(i, 1), Element(i, 2)); }
  263. /// Return matrix column.
  264. Vector3 Column(unsigned j) const { return Vector3(Element(0, j), Element(1, j), Element(2, j)); }
  265. /// Return as string.
  266. String ToString() const;
  267. float m00_;
  268. float m01_;
  269. float m02_;
  270. float m10_;
  271. float m11_;
  272. float m12_;
  273. float m20_;
  274. float m21_;
  275. float m22_;
  276. /// Bulk transpose matrices.
  277. static void BulkTranspose(float* dest, const float* src, unsigned count)
  278. {
  279. for (unsigned i = 0; i < count; ++i)
  280. {
  281. dest[0] = src[0];
  282. dest[1] = src[3];
  283. dest[2] = src[6];
  284. dest[3] = src[1];
  285. dest[4] = src[4];
  286. dest[5] = src[7];
  287. dest[6] = src[2];
  288. dest[7] = src[5];
  289. dest[8] = src[8];
  290. dest += 9;
  291. src += 9;
  292. }
  293. }
  294. /// Zero matrix.
  295. static const Matrix3 ZERO;
  296. /// Identity matrix.
  297. static const Matrix3 IDENTITY;
  298. };
  299. /// Multiply a 3x3 matrix with a scalar.
  300. inline Matrix3 operator *(float lhs, const Matrix3& rhs) { return rhs * lhs; }
  301. }