You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

582 lines
16 KiB

4 years ago
  1. ///////////////////////////////////////////////////////////////////////////////////
  2. /// OpenGL Mathematics (glm.g-truc.net)
  3. ///
  4. /// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net)
  5. /// Permission is hereby granted, free of charge, to any person obtaining a copy
  6. /// of this software and associated documentation files (the "Software"), to deal
  7. /// in the Software without restriction, including without limitation the rights
  8. /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. /// copies of the Software, and to permit persons to whom the Software is
  10. /// furnished to do so, subject to the following conditions:
  11. ///
  12. /// The above copyright notice and this permission notice shall be included in
  13. /// all copies or substantial portions of the Software.
  14. ///
  15. /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. /// THE SOFTWARE.
  22. ///
  23. /// @ref core
  24. /// @file glm/core/func_matrix.inl
  25. /// @date 2008-03-08 / 2011-06-15
  26. /// @author Christophe Riccio
  27. ///////////////////////////////////////////////////////////////////////////////////
  28. namespace glm
  29. {
  30. // matrixCompMult
  31. template <typename matType>
  32. GLM_FUNC_QUALIFIER matType matrixCompMult
  33. (
  34. matType const & x,
  35. matType const & y
  36. )
  37. {
  38. GLM_STATIC_ASSERT(detail::type<typename matType::value_type>::is_float, "'matrixCompMult' only accept floating-point inputs");
  39. matType result(matType::null);
  40. for(typename matType::size_type i = 0; i < matType::row_size(); ++i)
  41. result[i] = x[i] * y[i];
  42. return result;
  43. }
  44. // outerProduct
  45. template <typename T>
  46. GLM_FUNC_QUALIFIER detail::tmat2x2<T> outerProduct
  47. (
  48. detail::tvec2<T> const & c,
  49. detail::tvec2<T> const & r
  50. )
  51. {
  52. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  53. detail::tmat2x2<T> m(detail::tmat2x2<T>::null);
  54. m[0][0] = c[0] * r[0];
  55. m[0][1] = c[1] * r[0];
  56. m[1][0] = c[0] * r[1];
  57. m[1][1] = c[1] * r[1];
  58. return m;
  59. }
  60. template <typename T>
  61. GLM_FUNC_QUALIFIER detail::tmat3x3<T> outerProduct
  62. (
  63. detail::tvec3<T> const & c,
  64. detail::tvec3<T> const & r
  65. )
  66. {
  67. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  68. detail::tmat3x3<T> m(detail::tmat3x3<T>::null);
  69. for(typename detail::tmat3x3<T>::size_type i(0); i < m.length(); ++i)
  70. m[i] = c * r[i];
  71. return m;
  72. }
  73. template <typename T>
  74. GLM_FUNC_QUALIFIER detail::tmat4x4<T> outerProduct
  75. (
  76. detail::tvec4<T> const & c,
  77. detail::tvec4<T> const & r
  78. )
  79. {
  80. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  81. detail::tmat4x4<T> m(detail::tmat4x4<T>::null);
  82. for(typename detail::tmat4x4<T>::size_type i(0); i < m.length(); ++i)
  83. m[i] = c * r[i];
  84. return m;
  85. }
  86. template <typename T>
  87. GLM_FUNC_QUALIFIER detail::tmat2x3<T> outerProduct
  88. (
  89. detail::tvec3<T> const & c,
  90. detail::tvec2<T> const & r
  91. )
  92. {
  93. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  94. detail::tmat2x3<T> m(detail::tmat2x3<T>::null);
  95. m[0][0] = c.x * r.x;
  96. m[0][1] = c.y * r.x;
  97. m[0][2] = c.z * r.x;
  98. m[1][0] = c.x * r.y;
  99. m[1][1] = c.y * r.y;
  100. m[1][2] = c.z * r.y;
  101. return m;
  102. }
  103. template <typename T>
  104. GLM_FUNC_QUALIFIER detail::tmat3x2<T> outerProduct
  105. (
  106. detail::tvec2<T> const & c,
  107. detail::tvec3<T> const & r
  108. )
  109. {
  110. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  111. detail::tmat3x2<T> m(detail::tmat3x2<T>::null);
  112. m[0][0] = c.x * r.x;
  113. m[0][1] = c.y * r.x;
  114. m[1][0] = c.x * r.y;
  115. m[1][1] = c.y * r.y;
  116. m[2][0] = c.x * r.z;
  117. m[2][1] = c.y * r.z;
  118. return m;
  119. }
  120. template <typename T>
  121. GLM_FUNC_QUALIFIER detail::tmat2x4<T> outerProduct
  122. (
  123. detail::tvec4<T> const & c,
  124. detail::tvec2<T> const & r
  125. )
  126. {
  127. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  128. detail::tmat2x4<T> m(detail::tmat2x4<T>::null);
  129. m[0][0] = c.x * r.x;
  130. m[0][1] = c.y * r.x;
  131. m[0][2] = c.z * r.x;
  132. m[0][3] = c.w * r.x;
  133. m[1][0] = c.x * r.y;
  134. m[1][1] = c.y * r.y;
  135. m[1][2] = c.z * r.y;
  136. m[1][3] = c.w * r.y;
  137. return m;
  138. }
  139. template <typename T>
  140. GLM_FUNC_QUALIFIER detail::tmat4x2<T> outerProduct
  141. (
  142. detail::tvec2<T> const & c,
  143. detail::tvec4<T> const & r
  144. )
  145. {
  146. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  147. detail::tmat4x2<T> m(detail::tmat4x2<T>::null);
  148. m[0][0] = c.x * r.x;
  149. m[0][1] = c.y * r.x;
  150. m[1][0] = c.x * r.y;
  151. m[1][1] = c.y * r.y;
  152. m[2][0] = c.x * r.z;
  153. m[2][1] = c.y * r.z;
  154. m[3][0] = c.x * r.w;
  155. m[3][1] = c.y * r.w;
  156. return m;
  157. }
  158. template <typename T>
  159. GLM_FUNC_QUALIFIER detail::tmat3x4<T> outerProduct
  160. (
  161. detail::tvec4<T> const & c,
  162. detail::tvec3<T> const & r
  163. )
  164. {
  165. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  166. detail::tmat3x4<T> m(detail::tmat3x4<T>::null);
  167. m[0][0] = c.x * r.x;
  168. m[0][1] = c.y * r.x;
  169. m[0][2] = c.z * r.x;
  170. m[0][3] = c.w * r.x;
  171. m[1][0] = c.x * r.y;
  172. m[1][1] = c.y * r.y;
  173. m[1][2] = c.z * r.y;
  174. m[1][3] = c.w * r.y;
  175. m[2][0] = c.x * r.z;
  176. m[2][1] = c.y * r.z;
  177. m[2][2] = c.z * r.z;
  178. m[2][3] = c.w * r.z;
  179. return m;
  180. }
  181. template <typename T>
  182. GLM_FUNC_QUALIFIER detail::tmat4x3<T> outerProduct
  183. (
  184. detail::tvec3<T> const & c,
  185. detail::tvec4<T> const & r
  186. )
  187. {
  188. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'outerProduct' only accept floating-point inputs");
  189. detail::tmat4x3<T> m(detail::tmat4x3<T>::null);
  190. m[0][0] = c.x * r.x;
  191. m[0][1] = c.y * r.x;
  192. m[0][2] = c.z * r.x;
  193. m[1][0] = c.x * r.y;
  194. m[1][1] = c.y * r.y;
  195. m[1][2] = c.z * r.y;
  196. m[2][0] = c.x * r.z;
  197. m[2][1] = c.y * r.z;
  198. m[2][2] = c.z * r.z;
  199. m[3][0] = c.x * r.w;
  200. m[3][1] = c.y * r.w;
  201. m[3][2] = c.z * r.w;
  202. return m;
  203. }
  204. template <typename T>
  205. GLM_FUNC_QUALIFIER detail::tmat2x2<T> transpose
  206. (
  207. detail::tmat2x2<T> const & m
  208. )
  209. {
  210. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  211. detail::tmat2x2<T> result(detail::tmat2x2<T>::null);
  212. result[0][0] = m[0][0];
  213. result[0][1] = m[1][0];
  214. result[1][0] = m[0][1];
  215. result[1][1] = m[1][1];
  216. return result;
  217. }
  218. template <typename T>
  219. GLM_FUNC_QUALIFIER detail::tmat3x3<T> transpose
  220. (
  221. detail::tmat3x3<T> const & m
  222. )
  223. {
  224. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  225. detail::tmat3x3<T> result(detail::tmat3x3<T>::null);
  226. result[0][0] = m[0][0];
  227. result[0][1] = m[1][0];
  228. result[0][2] = m[2][0];
  229. result[1][0] = m[0][1];
  230. result[1][1] = m[1][1];
  231. result[1][2] = m[2][1];
  232. result[2][0] = m[0][2];
  233. result[2][1] = m[1][2];
  234. result[2][2] = m[2][2];
  235. return result;
  236. }
  237. template <typename T>
  238. GLM_FUNC_QUALIFIER detail::tmat4x4<T> transpose
  239. (
  240. detail::tmat4x4<T> const & m
  241. )
  242. {
  243. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  244. detail::tmat4x4<T> result(detail::tmat4x4<T>::null);
  245. result[0][0] = m[0][0];
  246. result[0][1] = m[1][0];
  247. result[0][2] = m[2][0];
  248. result[0][3] = m[3][0];
  249. result[1][0] = m[0][1];
  250. result[1][1] = m[1][1];
  251. result[1][2] = m[2][1];
  252. result[1][3] = m[3][1];
  253. result[2][0] = m[0][2];
  254. result[2][1] = m[1][2];
  255. result[2][2] = m[2][2];
  256. result[2][3] = m[3][2];
  257. result[3][0] = m[0][3];
  258. result[3][1] = m[1][3];
  259. result[3][2] = m[2][3];
  260. result[3][3] = m[3][3];
  261. return result;
  262. }
  263. template <typename T>
  264. GLM_FUNC_QUALIFIER detail::tmat2x3<T> transpose
  265. (
  266. detail::tmat3x2<T> const & m
  267. )
  268. {
  269. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  270. detail::tmat2x3<T> result(detail::tmat2x3<T>::null);
  271. result[0][0] = m[0][0];
  272. result[0][1] = m[1][0];
  273. result[0][2] = m[2][0];
  274. result[1][0] = m[0][1];
  275. result[1][1] = m[1][1];
  276. result[1][2] = m[2][1];
  277. return result;
  278. }
  279. template <typename T>
  280. GLM_FUNC_QUALIFIER detail::tmat3x2<T> transpose
  281. (
  282. detail::tmat2x3<T> const & m
  283. )
  284. {
  285. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  286. detail::tmat3x2<T> result(detail::tmat3x2<T>::null);
  287. result[0][0] = m[0][0];
  288. result[0][1] = m[1][0];
  289. result[1][0] = m[0][1];
  290. result[1][1] = m[1][1];
  291. result[2][0] = m[0][2];
  292. result[2][1] = m[1][2];
  293. return result;
  294. }
  295. template <typename T>
  296. GLM_FUNC_QUALIFIER detail::tmat2x4<T> transpose
  297. (
  298. detail::tmat4x2<T> const & m
  299. )
  300. {
  301. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  302. detail::tmat2x4<T> result(detail::tmat2x4<T>::null);
  303. result[0][0] = m[0][0];
  304. result[0][1] = m[1][0];
  305. result[0][2] = m[2][0];
  306. result[0][3] = m[3][0];
  307. result[1][0] = m[0][1];
  308. result[1][1] = m[1][1];
  309. result[1][2] = m[2][1];
  310. result[1][3] = m[3][1];
  311. return result;
  312. }
  313. template <typename T>
  314. GLM_FUNC_QUALIFIER detail::tmat4x2<T> transpose
  315. (
  316. detail::tmat2x4<T> const & m
  317. )
  318. {
  319. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  320. detail::tmat4x2<T> result(detail::tmat4x2<T>::null);
  321. result[0][0] = m[0][0];
  322. result[0][1] = m[1][0];
  323. result[1][0] = m[0][1];
  324. result[1][1] = m[1][1];
  325. result[2][0] = m[0][2];
  326. result[2][1] = m[1][2];
  327. result[3][0] = m[0][3];
  328. result[3][1] = m[1][3];
  329. return result;
  330. }
  331. template <typename T>
  332. GLM_FUNC_QUALIFIER detail::tmat3x4<T> transpose
  333. (
  334. detail::tmat4x3<T> const & m
  335. )
  336. {
  337. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  338. detail::tmat3x4<T> result(detail::tmat3x4<T>::null);
  339. result[0][0] = m[0][0];
  340. result[0][1] = m[1][0];
  341. result[0][2] = m[2][0];
  342. result[0][3] = m[3][0];
  343. result[1][0] = m[0][1];
  344. result[1][1] = m[1][1];
  345. result[1][2] = m[2][1];
  346. result[1][3] = m[3][1];
  347. result[2][0] = m[0][2];
  348. result[2][1] = m[1][2];
  349. result[2][2] = m[2][2];
  350. result[2][3] = m[3][2];
  351. return result;
  352. }
  353. template <typename T>
  354. GLM_FUNC_QUALIFIER detail::tmat4x3<T> transpose
  355. (
  356. detail::tmat3x4<T> const & m
  357. )
  358. {
  359. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'transpose' only accept floating-point inputs");
  360. detail::tmat4x3<T> result(detail::tmat4x3<T>::null);
  361. result[0][0] = m[0][0];
  362. result[0][1] = m[1][0];
  363. result[0][2] = m[2][0];
  364. result[1][0] = m[0][1];
  365. result[1][1] = m[1][1];
  366. result[1][2] = m[2][1];
  367. result[2][0] = m[0][2];
  368. result[2][1] = m[1][2];
  369. result[2][2] = m[2][2];
  370. result[3][0] = m[0][3];
  371. result[3][1] = m[1][3];
  372. result[3][2] = m[2][3];
  373. return result;
  374. }
  375. template <typename T>
  376. GLM_FUNC_QUALIFIER typename detail::tmat2x2<T>::value_type determinant
  377. (
  378. detail::tmat2x2<T> const & m
  379. )
  380. {
  381. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'determinant' only accept floating-point inputs");
  382. return m[0][0] * m[1][1] - m[1][0] * m[0][1];
  383. }
  384. template <typename T>
  385. GLM_FUNC_QUALIFIER typename detail::tmat3x3<T>::value_type determinant
  386. (
  387. detail::tmat3x3<T> const & m
  388. )
  389. {
  390. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'determinant' only accept floating-point inputs");
  391. return
  392. + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
  393. - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
  394. + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
  395. }
  396. template <typename T>
  397. GLM_FUNC_QUALIFIER typename detail::tmat4x4<T>::value_type determinant
  398. (
  399. detail::tmat4x4<T> const & m
  400. )
  401. {
  402. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'determinant' only accept floating-point inputs");
  403. T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
  404. T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
  405. T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
  406. T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
  407. T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
  408. T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
  409. detail::tvec4<T> DetCof(
  410. + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02),
  411. - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04),
  412. + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05),
  413. - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05));
  414. return m[0][0] * DetCof[0]
  415. + m[0][1] * DetCof[1]
  416. + m[0][2] * DetCof[2]
  417. + m[0][3] * DetCof[3];
  418. }
  419. template <typename T>
  420. GLM_FUNC_QUALIFIER detail::tmat2x2<T> inverse
  421. (
  422. detail::tmat2x2<T> const & m
  423. )
  424. {
  425. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'inverse' only accept floating-point inputs");
  426. //valType Determinant = m[0][0] * m[1][1] - m[1][0] * m[0][1];
  427. T Determinant = determinant(m);
  428. detail::tmat2x2<T> Inverse(
  429. + m[1][1] / Determinant,
  430. - m[0][1] / Determinant,
  431. - m[1][0] / Determinant,
  432. + m[0][0] / Determinant);
  433. return Inverse;
  434. }
  435. template <typename T>
  436. GLM_FUNC_QUALIFIER detail::tmat3x3<T> inverse
  437. (
  438. detail::tmat3x3<T> const & m
  439. )
  440. {
  441. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'inverse' only accept floating-point inputs");
  442. //valType Determinant = m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
  443. // - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
  444. // + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
  445. T Determinant = determinant(m);
  446. detail::tmat3x3<T> Inverse(detail::tmat3x3<T>::null);
  447. Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
  448. Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]);
  449. Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]);
  450. Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
  451. Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]);
  452. Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]);
  453. Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
  454. Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]);
  455. Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]);
  456. Inverse /= Determinant;
  457. return Inverse;
  458. }
  459. template <typename T>
  460. GLM_FUNC_QUALIFIER detail::tmat4x4<T> inverse
  461. (
  462. detail::tmat4x4<T> const & m
  463. )
  464. {
  465. GLM_STATIC_ASSERT(detail::type<T>::is_float, "'inverse' only accept floating-point inputs");
  466. T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
  467. T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
  468. T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
  469. T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
  470. T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
  471. T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
  472. T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
  473. T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
  474. T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
  475. T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
  476. T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
  477. T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
  478. T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
  479. T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
  480. T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
  481. T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
  482. T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
  483. T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
  484. detail::tvec4<T> const SignA(+1, -1, +1, -1);
  485. detail::tvec4<T> const SignB(-1, +1, -1, +1);
  486. detail::tvec4<T> Fac0(Coef00, Coef00, Coef02, Coef03);
  487. detail::tvec4<T> Fac1(Coef04, Coef04, Coef06, Coef07);
  488. detail::tvec4<T> Fac2(Coef08, Coef08, Coef10, Coef11);
  489. detail::tvec4<T> Fac3(Coef12, Coef12, Coef14, Coef15);
  490. detail::tvec4<T> Fac4(Coef16, Coef16, Coef18, Coef19);
  491. detail::tvec4<T> Fac5(Coef20, Coef20, Coef22, Coef23);
  492. detail::tvec4<T> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]);
  493. detail::tvec4<T> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]);
  494. detail::tvec4<T> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]);
  495. detail::tvec4<T> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]);
  496. detail::tvec4<T> Inv0 = SignA * (Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2);
  497. detail::tvec4<T> Inv1 = SignB * (Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4);
  498. detail::tvec4<T> Inv2 = SignA * (Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5);
  499. detail::tvec4<T> Inv3 = SignB * (Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5);
  500. detail::tmat4x4<T> Inverse(Inv0, Inv1, Inv2, Inv3);
  501. detail::tvec4<T> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]);
  502. T Determinant = glm::dot(m[0], Row0);
  503. Inverse /= Determinant;
  504. return Inverse;
  505. }
  506. }//namespace glm