Matrix.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // Copyright 2019 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "Common/Matrix.h"
  4. #include <algorithm>
  5. #include <cmath>
  6. #include "Common/MathUtil.h"
  7. namespace
  8. {
  9. // Multiply a NxM matrix by a MxP matrix.
  10. template <int N, int M, int P, typename T>
  11. auto MatrixMultiply(const std::array<T, N * M>& a, const std::array<T, M * P>& b)
  12. -> std::array<T, N * P>
  13. {
  14. std::array<T, N * P> result;
  15. for (int n = 0; n != N; ++n)
  16. {
  17. for (int p = 0; p != P; ++p)
  18. {
  19. T temp = {};
  20. for (int m = 0; m != M; ++m)
  21. {
  22. temp += a[n * M + m] * b[m * P + p];
  23. }
  24. result[n * P + p] = temp;
  25. }
  26. }
  27. return result;
  28. }
  29. } // namespace
  30. namespace Common
  31. {
  32. Quaternion Quaternion::Identity()
  33. {
  34. return Quaternion(1, 0, 0, 0);
  35. }
  36. Quaternion Quaternion::RotateX(float rad)
  37. {
  38. return Rotate(rad, Vec3(1, 0, 0));
  39. }
  40. Quaternion Quaternion::RotateY(float rad)
  41. {
  42. return Rotate(rad, Vec3(0, 1, 0));
  43. }
  44. Quaternion Quaternion::RotateZ(float rad)
  45. {
  46. return Rotate(rad, Vec3(0, 0, 1));
  47. }
  48. Quaternion Quaternion::RotateXYZ(const Vec3& rads)
  49. {
  50. const auto length = rads.Length();
  51. return length ? Common::Quaternion::Rotate(length, rads / length) :
  52. Common::Quaternion::Identity();
  53. }
  54. Quaternion Quaternion::Rotate(float rad, const Vec3& axis)
  55. {
  56. const auto sin_angle_2 = std::sin(rad / 2);
  57. return Quaternion(std::cos(rad / 2), axis.x * sin_angle_2, axis.y * sin_angle_2,
  58. axis.z * sin_angle_2);
  59. }
  60. Quaternion::Quaternion(float w, float x, float y, float z) : data(x, y, z, w)
  61. {
  62. }
  63. float Quaternion::Norm() const
  64. {
  65. return std::sqrt(data.Dot(data));
  66. }
  67. Quaternion Quaternion::Normalized() const
  68. {
  69. Quaternion result(*this);
  70. result.data /= Norm();
  71. return result;
  72. }
  73. Quaternion Quaternion::Conjugate() const
  74. {
  75. return Quaternion(data.w, -1 * data.x, -1 * data.y, -1 * data.z);
  76. }
  77. Quaternion Quaternion::Inverted() const
  78. {
  79. return Normalized().Conjugate();
  80. }
  81. Quaternion& Quaternion::operator*=(const Quaternion& rhs)
  82. {
  83. auto& a = data;
  84. auto& b = rhs.data;
  85. data = Vec4{a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
  86. a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
  87. a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
  88. // W
  89. a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z};
  90. return *this;
  91. }
  92. Quaternion operator*(Quaternion lhs, const Quaternion& rhs)
  93. {
  94. return lhs *= rhs;
  95. }
  96. Vec3 operator*(const Quaternion& lhs, const Vec3& rhs)
  97. {
  98. const auto result = lhs * Quaternion(0, rhs.x, rhs.y, rhs.z) * lhs.Conjugate();
  99. return Vec3(result.data.x, result.data.y, result.data.z);
  100. }
  101. Vec3 FromQuaternionToEuler(const Quaternion& q)
  102. {
  103. Vec3 result;
  104. const float qx = q.data.x;
  105. const float qy = q.data.y;
  106. const float qz = q.data.z;
  107. const float qw = q.data.w;
  108. const float sinr_cosp = 2 * (qw * qx + qy * qz);
  109. const float cosr_cosp = 1 - 2 * (qx * qx + qy * qy);
  110. result.x = std::atan2(sinr_cosp, cosr_cosp);
  111. const float sinp = 2 * (qw * qy - qz * qx);
  112. if (std::abs(sinp) >= 1)
  113. result.y = std::copysign(MathUtil::PI / 2, sinp); // use 90 degrees if out of range
  114. else
  115. result.y = std::asin(sinp);
  116. const float siny_cosp = 2 * (qw * qz + qx * qy);
  117. const float cosy_cosp = 1 - 2 * (qy * qy + qz * qz);
  118. result.z = std::atan2(siny_cosp, cosy_cosp);
  119. return result;
  120. }
  121. Matrix33 Matrix33::Identity()
  122. {
  123. Matrix33 mtx = {};
  124. mtx.data[0] = 1.0f;
  125. mtx.data[4] = 1.0f;
  126. mtx.data[8] = 1.0f;
  127. return mtx;
  128. }
  129. Matrix33 Matrix33::FromQuaternion(const Quaternion& q)
  130. {
  131. const auto qx = q.data.x;
  132. const auto qy = q.data.y;
  133. const auto qz = q.data.z;
  134. const auto qw = q.data.w;
  135. return {
  136. 1 - 2 * qy * qy - 2 * qz * qz, 2 * qx * qy - 2 * qz * qw, 2 * qx * qz + 2 * qy * qw,
  137. 2 * qx * qy + 2 * qz * qw, 1 - 2 * qx * qx - 2 * qz * qz, 2 * qy * qz - 2 * qx * qw,
  138. 2 * qx * qz - 2 * qy * qw, 2 * qy * qz + 2 * qx * qw, 1 - 2 * qx * qx - 2 * qy * qy,
  139. };
  140. }
  141. Matrix33 Matrix33::RotateX(float rad)
  142. {
  143. const float s = std::sin(rad);
  144. const float c = std::cos(rad);
  145. Matrix33 mtx = {};
  146. mtx.data[0] = 1;
  147. mtx.data[4] = c;
  148. mtx.data[5] = -s;
  149. mtx.data[7] = s;
  150. mtx.data[8] = c;
  151. return mtx;
  152. }
  153. Matrix33 Matrix33::RotateY(float rad)
  154. {
  155. const float s = std::sin(rad);
  156. const float c = std::cos(rad);
  157. Matrix33 mtx = {};
  158. mtx.data[0] = c;
  159. mtx.data[2] = s;
  160. mtx.data[4] = 1;
  161. mtx.data[6] = -s;
  162. mtx.data[8] = c;
  163. return mtx;
  164. }
  165. Matrix33 Matrix33::RotateZ(float rad)
  166. {
  167. const float s = std::sin(rad);
  168. const float c = std::cos(rad);
  169. Matrix33 mtx = {};
  170. mtx.data[0] = c;
  171. mtx.data[1] = -s;
  172. mtx.data[3] = s;
  173. mtx.data[4] = c;
  174. mtx.data[8] = 1;
  175. return mtx;
  176. }
  177. Matrix33 Matrix33::Rotate(float rad, const Vec3& axis)
  178. {
  179. const float s = std::sin(rad);
  180. const float c = std::cos(rad);
  181. Matrix33 mtx;
  182. mtx.data[0] = axis.x * axis.x * (1 - c) + c;
  183. mtx.data[1] = axis.x * axis.y * (1 - c) - axis.z * s;
  184. mtx.data[2] = axis.x * axis.z * (1 - c) + axis.y * s;
  185. mtx.data[3] = axis.y * axis.x * (1 - c) + axis.z * s;
  186. mtx.data[4] = axis.y * axis.y * (1 - c) + c;
  187. mtx.data[5] = axis.y * axis.z * (1 - c) - axis.x * s;
  188. mtx.data[6] = axis.z * axis.x * (1 - c) - axis.y * s;
  189. mtx.data[7] = axis.z * axis.y * (1 - c) + axis.x * s;
  190. mtx.data[8] = axis.z * axis.z * (1 - c) + c;
  191. return mtx;
  192. }
  193. Matrix33 Matrix33::Scale(const Vec3& vec)
  194. {
  195. Matrix33 mtx = {};
  196. mtx.data[0] = vec.x;
  197. mtx.data[4] = vec.y;
  198. mtx.data[8] = vec.z;
  199. return mtx;
  200. }
  201. void Matrix33::Multiply(const Matrix33& a, const Matrix33& b, Matrix33* result)
  202. {
  203. result->data = MatrixMultiply<3, 3, 3>(a.data, b.data);
  204. }
  205. void Matrix33::Multiply(const Matrix33& a, const Vec3& vec, Vec3* result)
  206. {
  207. result->data = MatrixMultiply<3, 3, 1>(a.data, vec.data);
  208. }
  209. Matrix33 Matrix33::Inverted() const
  210. {
  211. const auto m = [this](int x, int y) { return data[y + x * 3]; };
  212. const auto invdet = 1 / Determinant();
  213. Matrix33 result;
  214. const auto minv = [&result](int x, int y) -> auto& { return result.data[y + x * 3]; };
  215. minv(0, 0) = (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) * invdet;
  216. minv(0, 1) = (m(0, 2) * m(2, 1) - m(0, 1) * m(2, 2)) * invdet;
  217. minv(0, 2) = (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * invdet;
  218. minv(1, 0) = (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) * invdet;
  219. minv(1, 1) = (m(0, 0) * m(2, 2) - m(0, 2) * m(2, 0)) * invdet;
  220. minv(1, 2) = (m(1, 0) * m(0, 2) - m(0, 0) * m(1, 2)) * invdet;
  221. minv(2, 0) = (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1)) * invdet;
  222. minv(2, 1) = (m(2, 0) * m(0, 1) - m(0, 0) * m(2, 1)) * invdet;
  223. minv(2, 2) = (m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1)) * invdet;
  224. return result;
  225. }
  226. float Matrix33::Determinant() const
  227. {
  228. const auto m = [this](int x, int y) { return data[y + x * 3]; };
  229. return m(0, 0) * (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) -
  230. m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
  231. m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0));
  232. }
  233. Matrix44 Matrix44::Identity()
  234. {
  235. Matrix44 mtx = {};
  236. mtx.data[0] = 1.0f;
  237. mtx.data[5] = 1.0f;
  238. mtx.data[10] = 1.0f;
  239. mtx.data[15] = 1.0f;
  240. return mtx;
  241. }
  242. Matrix44 Matrix44::FromMatrix33(const Matrix33& m33)
  243. {
  244. Matrix44 mtx;
  245. for (int i = 0; i < 3; ++i)
  246. {
  247. for (int j = 0; j < 3; ++j)
  248. {
  249. mtx.data[i * 4 + j] = m33.data[i * 3 + j];
  250. }
  251. }
  252. for (int i = 0; i < 3; ++i)
  253. {
  254. mtx.data[i * 4 + 3] = 0;
  255. mtx.data[i + 12] = 0;
  256. }
  257. mtx.data[15] = 1.0f;
  258. return mtx;
  259. }
  260. Matrix44 Matrix44::FromQuaternion(const Quaternion& q)
  261. {
  262. return FromMatrix33(Matrix33::FromQuaternion(q));
  263. }
  264. Matrix44 Matrix44::FromArray(const std::array<float, 16>& arr)
  265. {
  266. Matrix44 mtx;
  267. mtx.data = arr;
  268. return mtx;
  269. }
  270. Matrix44 Matrix44::Translate(const Vec3& vec)
  271. {
  272. Matrix44 mtx = Matrix44::Identity();
  273. mtx.data[3] = vec.x;
  274. mtx.data[7] = vec.y;
  275. mtx.data[11] = vec.z;
  276. return mtx;
  277. }
  278. Matrix44 Matrix44::Shear(const float a, const float b)
  279. {
  280. Matrix44 mtx = Matrix44::Identity();
  281. mtx.data[2] = a;
  282. mtx.data[6] = b;
  283. return mtx;
  284. }
  285. Matrix44 Matrix44::Perspective(float fov_y, float aspect_ratio, float z_near, float z_far)
  286. {
  287. Matrix44 mtx{};
  288. const float tan_half_fov_y = std::tan(fov_y / 2);
  289. mtx.data[0] = 1 / (aspect_ratio * tan_half_fov_y);
  290. mtx.data[5] = 1 / tan_half_fov_y;
  291. mtx.data[10] = -(z_far + z_near) / (z_far - z_near);
  292. mtx.data[11] = -(2 * z_far * z_near) / (z_far - z_near);
  293. mtx.data[14] = -1;
  294. return mtx;
  295. }
  296. void Matrix44::Multiply(const Matrix44& a, const Matrix44& b, Matrix44* result)
  297. {
  298. result->data = MatrixMultiply<4, 4, 4>(a.data, b.data);
  299. }
  300. Vec3 Matrix44::Transform(const Vec3& v, float w) const
  301. {
  302. const auto result = MatrixMultiply<4, 4, 1>(data, {v.x, v.y, v.z, w});
  303. return Vec3{result[0], result[1], result[2]};
  304. }
  305. void Matrix44::Multiply(const Matrix44& a, const Vec4& vec, Vec4* result)
  306. {
  307. result->data = MatrixMultiply<4, 4, 1>(a.data, vec.data);
  308. }
  309. float Matrix44::Determinant() const
  310. {
  311. const auto& m = data;
  312. return m[12] * m[9] * m[6] * m[3] - m[8] * m[13] * m[6] * m[3] - m[12] * m[5] * m[10] * m[3] +
  313. m[4] * m[13] * m[10] * m[3] + m[8] * m[5] * m[14] * m[3] - m[4] * m[9] * m[14] * m[3] -
  314. m[12] * m[9] * m[2] * m[7] + m[8] * m[13] * m[2] * m[7] + m[12] * m[1] * m[10] * m[7] -
  315. m[0] * m[13] * m[10] * m[7] - m[8] * m[1] * m[14] * m[7] + m[0] * m[9] * m[14] * m[7] +
  316. m[12] * m[5] * m[2] * m[11] - m[4] * m[13] * m[2] * m[11] - m[12] * m[1] * m[6] * m[11] +
  317. m[0] * m[13] * m[6] * m[11] + m[4] * m[1] * m[14] * m[11] - m[0] * m[5] * m[14] * m[11] -
  318. m[8] * m[5] * m[2] * m[15] + m[4] * m[9] * m[2] * m[15] + m[8] * m[1] * m[6] * m[15] -
  319. m[0] * m[9] * m[6] * m[15] - m[4] * m[1] * m[10] * m[15] + m[0] * m[5] * m[10] * m[15];
  320. }
  321. } // namespace Common