PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/HelloOpenGL/HelloOpenGL/CC3Kazmath.c

https://gitlab.com/praveenvelanati/ios-demo
C | 641 lines | 428 code | 84 blank | 129 comment | 41 complexity | 1d931b82c9459d1060b4546cdcede606 MD5 | raw file
  1. /*
  2. * CC3Kazmath.c
  3. *
  4. * Copyright (c) 2008, Luke Benstead.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted provided that the following conditions are met:
  9. *
  10. * Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the following disclaimer.
  12. * Redistributions in binary form must reproduce the above copyright notice,
  13. * this list of conditions and the following disclaimer in the documentation
  14. * and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  20. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  23. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. * http://www.kazade.co.uk/kazmath/
  28. *
  29. * Augmented and modified for use with Objective-C in cocos3D by Bill Hollings
  30. * Additions and modifications copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
  31. * http://www.brenwill.com
  32. *
  33. * See header file CC3Kazmath.h for full API documentation.
  34. */
  35. #import "CC3Kazmath.h"
  36. #import <stdlib.h>
  37. #import <memory.h>
  38. #import <math.h>
  39. // Returns a kmVec3 structure constructed from the vector components.
  40. kmVec3 kmVec3Make(kmScalar x, kmScalar y, kmScalar z) {
  41. kmVec3 v;
  42. v.x = x;
  43. v.y = y;
  44. v.z = z;
  45. return v;
  46. }
  47. // Returns the length of the vector.
  48. kmScalar kmVec3Length(const kmVec3* pIn) {
  49. return sqrtf((pIn->x * pIn->x) + (pIn->y * pIn->y) + (pIn->z * pIn->z));
  50. }
  51. // Normalizes the vector to unit length, stores the result in pOut and returns the result.
  52. kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn) {
  53. kmScalar l = 1.0f / kmVec3Length(pIn);
  54. kmVec3 v;
  55. v.x = pIn->x * l;
  56. v.y = pIn->y * l;
  57. v.z = pIn->z * l;
  58. pOut->x = v.x;
  59. pOut->y = v.y;
  60. pOut->z = v.z;
  61. return pOut;
  62. }
  63. // Multiplies pM1 with pM2, stores the result in pOut, returns pOut
  64. kmMat4* kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2) {
  65. const float *m1 = pM1->mat, *m2 = pM2->mat;
  66. float *m = pOut->mat;
  67. m[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
  68. m[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
  69. m[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
  70. m[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
  71. m[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
  72. m[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
  73. m[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
  74. m[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
  75. m[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
  76. m[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
  77. m[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
  78. m[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
  79. m[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
  80. m[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
  81. m[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
  82. m[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
  83. return pOut;
  84. }
  85. // Builds a rotation matrix that rotates around all three axes, y (yaw), x (pitch), z (roll),
  86. // (equivalently to separate rotations, in that order), stores the result in pOut and returns the result.
  87. kmMat4* kmMat4RotationYXZ(kmMat4* pOut, const kmScalar xRadians, const kmScalar yRadians, const kmScalar zRadians) {
  88. /*
  89. | cycz + sxsysz czsxsy - cysz cxsy 0 |
  90. M = | cxsz cxcz -sx 0 |
  91. | cysxsz - czsy cyczsx + sysz cxcy 0 |
  92. | 0 0 0 1 |
  93. where cA = cos(A), sA = sin(A) for A = x,y,z
  94. */
  95. kmScalar* m = pOut->mat;
  96. kmScalar cx = cosf(xRadians);
  97. kmScalar sx = sinf(xRadians);
  98. kmScalar cy = cosf(yRadians);
  99. kmScalar sy = sinf(yRadians);
  100. kmScalar cz = cosf(zRadians);
  101. kmScalar sz = sinf(zRadians);
  102. m[0] = (cy * cz) + (sx * sy * sz);
  103. m[1] = cx * sz;
  104. m[2] = (cy * sx * sz) - (cz * sy);
  105. m[3] = 0.0;
  106. m[4] = (cz * sx * sy) - (cy * sz);
  107. m[5] = cx * cz;
  108. m[6] = (cy * cz * sx) + (sy * sz);
  109. m[7] = 0.0;
  110. m[8] = cx * sy;
  111. m[9] = -sx;
  112. m[10] = cx * cy;
  113. m[11] = 0.0;
  114. m[12] = 0.0;
  115. m[13] = 0.0;
  116. m[14] = 0.0;
  117. m[15] = 1.0;
  118. return pOut;
  119. }
  120. // Builds a rotation matrix that rotates around all three axes, z (roll), y (yaw), x (pitch),
  121. // (equivalently to separate rotations, in that order), stores the result in pOut and returns the result.
  122. kmMat4* kmMat4RotationZYX(kmMat4* pOut, const kmScalar xRadians, const kmScalar yRadians, const kmScalar zRadians) {
  123. /*
  124. | cycz -cxsz + sxsycz sxsz + cxsycz 0 |
  125. M = | cysz cxcz + sxsysz -sxcz + cxsysz 0 |
  126. | -sy sxcy cxcy 0 |
  127. | 0 0 0 1 |
  128. where cA = cos(A), sA = sin(A) for A = x,y,z
  129. */
  130. kmScalar* m = pOut->mat;
  131. kmScalar cx = cosf(xRadians);
  132. kmScalar sx = sinf(xRadians);
  133. kmScalar cy = cosf(yRadians);
  134. kmScalar sy = sinf(yRadians);
  135. kmScalar cz = cosf(zRadians);
  136. kmScalar sz = sinf(zRadians);
  137. m[0] = cy * cz;
  138. m[1] = cy * sz;
  139. m[2] = -sy;
  140. m[3] = 0.0;
  141. m[4] = -(cx * sz) + (sx * sy * cz);
  142. m[5] = (cx * cz) + (sx * sy * sz);
  143. m[6] = sx * cy;
  144. m[7] = 0.0;
  145. m[8] = (sx * sz) + (cx * sy * cz);
  146. m[9] = -(sx * cz) + (cx * sy * sz);
  147. m[10] = cx * cy;
  148. m[11] = 0.0;
  149. m[12] = 0.0;
  150. m[13] = 0.0;
  151. m[14] = 0.0;
  152. m[15] = 1.0;
  153. return pOut;
  154. }
  155. // Builds a rotation matrix around the X-axis, stores the result in pOut and returns the result
  156. kmMat4* kmMat4RotationX(kmMat4* pOut, const float radians) {
  157. /*
  158. | 1 0 0 0 |
  159. M = | 0 cos(A) -sin(A) 0 |
  160. | 0 sin(A) cos(A) 0 |
  161. | 0 0 0 1 |
  162. */
  163. kmScalar* m = pOut->mat;
  164. m[0] = 1.0f;
  165. m[1] = 0.0f;
  166. m[2] = 0.0f;
  167. m[3] = 0.0f;
  168. m[4] = 0.0f;
  169. m[5] = cosf(radians);
  170. m[6] = sinf(radians);
  171. m[7] = 0.0f;
  172. m[8] = 0.0f;
  173. m[9] = -sinf(radians);
  174. m[10] = cosf(radians);
  175. m[11] = 0.0f;
  176. m[12] = 0.0f;
  177. m[13] = 0.0f;
  178. m[14] = 0.0f;
  179. m[15] = 1.0f;
  180. return pOut;
  181. }
  182. // Builds a rotation matrix around the Y-axis, stores the result in pOut and returns the result
  183. kmMat4* kmMat4RotationY(kmMat4* pOut, const float radians) {
  184. /*
  185. | cos(A) 0 sin(A) 0 |
  186. M = | 0 1 0 0 |
  187. | -sin(A) 0 cos(A) 0 |
  188. | 0 0 0 1 |
  189. */
  190. kmScalar* m = pOut->mat;
  191. m[0] = cosf(radians);
  192. m[1] = 0.0f;
  193. m[2] = -sinf(radians);
  194. m[3] = 0.0f;
  195. m[4] = 0.0f;
  196. m[5] = 1.0f;
  197. m[6] = 0.0f;
  198. m[7] = 0.0f;
  199. m[8] = sinf(radians);
  200. m[9] = 0.0f;
  201. m[10] = cosf(radians);
  202. m[11] = 0.0f;
  203. m[12] = 0.0f;
  204. m[13] = 0.0f;
  205. m[14] = 0.0f;
  206. m[15] = 1.0f;
  207. return pOut;
  208. }
  209. // Builds a rotation matrix around the Z-axis, stores the result in pOut and returns the result
  210. kmMat4* kmMat4RotationZ(kmMat4* pOut, const float radians) {
  211. /*
  212. | cos(A) -sin(A) 0 0 |
  213. M = | sin(A) cos(A) 0 0 |
  214. | 0 0 1 0 |
  215. | 0 0 0 1 |
  216. */
  217. kmScalar* m = pOut->mat;
  218. m[0] = cosf(radians);
  219. m[1] = sinf(radians);
  220. m[2] = 0.0f;
  221. m[3] = 0.0f;
  222. m[4] = -sinf(radians);;
  223. m[5] = cosf(radians);
  224. m[6] = 0.0f;
  225. m[7] = 0.0f;
  226. m[8] = 0.0f;
  227. m[9] = 0.0f;
  228. m[10] = 1.0f;
  229. m[11] = 0.0f;
  230. m[12] = 0.0f;
  231. m[13] = 0.0f;
  232. m[14] = 0.0f;
  233. m[15] = 1.0f;
  234. return pOut;
  235. }
  236. // Build a rotation matrix from an axis and an angle, stores the result in pOut and returns the result.
  237. kmMat4* kmMat4RotationAxisAngle(kmMat4* pOut, const kmVec3* axis, kmScalar radians) {
  238. /*
  239. | |
  240. | C + XX(1 - C) -ZS + XY(1-C) YS + ZX(1-C) 0 |
  241. | |
  242. M = | ZS + XY(1-C) C + YY(1 - C) -XS + YZ(1-C) 0 |
  243. | |
  244. | -YS + ZX(1-C) XS + YZ(1-C) C + ZZ(1 - C) 0 |
  245. | |
  246. | 0 0 0 1 |
  247. where X, Y, Z define axis of rotation and C = cos(A), S = sin(A) for A = angle of rotation
  248. */
  249. kmScalar ca = cosf(radians);
  250. kmScalar sa = sinf(radians);
  251. kmVec3 rax;
  252. kmVec3Normalize(&rax, axis);
  253. pOut->mat[0] = ca + rax.x * rax.x * (1 - ca);
  254. pOut->mat[1] = rax.z * sa + rax.y * rax.x * (1 - ca);
  255. pOut->mat[2] = -rax.y * sa + rax.z * rax.x * (1 - ca);
  256. pOut->mat[3] = 0.0f;
  257. pOut->mat[4] = -rax.z * sa + rax.x * rax.y * (1 - ca);
  258. pOut->mat[5] = ca + rax.y * rax.y * (1 - ca);
  259. pOut->mat[6] = rax.x * sa + rax.z * rax.y * (1 - ca);
  260. pOut->mat[7] = 0.0f;
  261. pOut->mat[8] = rax.y * sa + rax.x * rax.z * (1 - ca);
  262. pOut->mat[9] = -rax.x * sa + rax.y * rax.z * (1 - ca);
  263. pOut->mat[10] = ca + rax.z * rax.z * (1 - ca);
  264. pOut->mat[11] = 0.0f;
  265. pOut->mat[12] = 0.0f;
  266. pOut->mat[13] = 0.0f;
  267. pOut->mat[14] = 0.0f;
  268. pOut->mat[15] = 1.0f;
  269. return pOut;
  270. }
  271. // Builds a rotation matrix from a quaternion to a rotation matrix,
  272. // stores the result in pOut and returns the result
  273. kmMat4* kmMat4RotationQuaternion(kmMat4* pOut, const kmQuaternion* pQ) {
  274. /*
  275. | 2 2 |
  276. | 1 - 2Y - 2Z 2XY + 2ZW 2XZ - 2YW 0 |
  277. | |
  278. | 2 2 |
  279. M = | 2XY - 2ZW 1 - 2X - 2Z 2YZ + 2XW 0 |
  280. | |
  281. | 2 2 |
  282. | 2XZ + 2YW 2YZ - 2XW 1 - 2X - 2Y 0 |
  283. | |
  284. | 0 0 0 1 |
  285. */
  286. kmScalar* m = pOut->mat;
  287. kmScalar twoXX = 2.0f * pQ->x * pQ->x;
  288. kmScalar twoXY = 2.0f * pQ->x * pQ->y;
  289. kmScalar twoXZ = 2.0f * pQ->x * pQ->z;
  290. kmScalar twoXW = 2.0f * pQ->x * pQ->w;
  291. kmScalar twoYY = 2.0f * pQ->y * pQ->y;
  292. kmScalar twoYZ = 2.0f * pQ->y * pQ->z;
  293. kmScalar twoYW = 2.0f * pQ->y * pQ->w;
  294. kmScalar twoZZ = 2.0f * pQ->z * pQ->z;
  295. kmScalar twoZW = 2.0f * pQ->z * pQ->w;
  296. m[0] = 1.0f - twoYY - twoZZ;
  297. m[1] = twoXY - twoZW;
  298. m[2] = twoXZ + twoYW;
  299. m[3] = 0.0f;
  300. m[4] = twoXY + twoZW;
  301. m[5] = 1.0f - twoXX - twoZZ;
  302. m[6] = twoYZ - twoXW;
  303. m[7] = 0.0f;
  304. m[8] = twoXZ - twoYW;
  305. m[9] = twoYZ + twoXW;
  306. m[10] = 1.0f - twoXX - twoYY;
  307. m[11] = 0.0f;
  308. m[12] = 0.0f;
  309. m[13] = 0.0f;
  310. m[14] = 0.0f;
  311. m[15] = 1.0f;
  312. return pOut;
  313. }
  314. // Extracts a quaternion from a rotation matrix, stores the result in quat and returns the result.
  315. // This implementation is actually taken from the Quaternions article in Jeff LaMarche's excellent
  316. // series on OpenGL programming for the iOS. Jeff's original source and explanation can be found here:
  317. // http://iphonedevelopment.blogspot.com/2010/04/opengl-es-from-ground-up-9-intermission.html
  318. // It has been adapted here for this library.
  319. kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* quat, const kmMat4* pIn) {
  320. #define QUATERNION_TRACE_ZERO_TOLERANCE 0.0001f
  321. kmScalar trace, s;
  322. const kmScalar* m = pIn->mat;
  323. trace = m[0] + m[5] + m[10];
  324. if (trace > 0.0f) {
  325. s = sqrtf(trace + 1.0f);
  326. quat->w = s * 0.5f;
  327. s = 0.5f / s;
  328. quat->x = (m[9] - m[6]) * s;
  329. quat->y = (m[2] - m[8]) * s;
  330. quat->z = (m[4] - m[1]) * s;
  331. } else {
  332. enum {A,E,I} biggest;
  333. if (m[0] > m[5])
  334. if (m[10] > m[0])
  335. biggest = I;
  336. else
  337. biggest = A;
  338. else
  339. if (m[10] > m[0])
  340. biggest = I;
  341. else
  342. biggest = E;
  343. switch (biggest) {
  344. case A:
  345. s = sqrtf(m[0] - (m[5] + m[10]) + 1.0f);
  346. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  347. quat->x = s * 0.5f;
  348. s = 0.5f / s;
  349. quat->w = (m[9] - m[6]) * s;
  350. quat->y = (m[1] + m[4]) * s;
  351. quat->z = (m[2] + m[8]) * s;
  352. break;
  353. }
  354. s = sqrtf(m[10] - (m[0] + m[5]) + 1.0f);
  355. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  356. quat->z = s * 0.5f;
  357. s = 0.5f / s;
  358. quat->w = (m[4] - m[1]) * s;
  359. quat->x = (m[8] + m[2]) * s;
  360. quat->y = (m[9] + m[6]) * s;
  361. break;
  362. }
  363. s = sqrtf(m[5] - (m[10] + m[0]) + 1.0f);
  364. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  365. quat->y = s * 0.5f;
  366. s = 0.5f / s;
  367. quat->w = (m[2] - m[8]) * s;
  368. quat->z = (m[6] + m[9]) * s;
  369. quat->x = (m[4] + m[1]) * s;
  370. break;
  371. }
  372. break;
  373. case E:
  374. s = sqrtf(m[5] - (m[10] + m[0]) + 1.0f);
  375. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  376. quat->y = s * 0.5f;
  377. s = 0.5f / s;
  378. quat->w = (m[2] - m[8]) * s;
  379. quat->z = (m[6] + m[9]) * s;
  380. quat->x = (m[4] + m[1]) * s;
  381. break;
  382. }
  383. s = sqrtf(m[10] - (m[0] + m[5]) + 1.0f);
  384. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  385. quat->z = s * 0.5f;
  386. s = 0.5f / s;
  387. quat->w = (m[4] - m[1]) * s;
  388. quat->x = (m[8] + m[2]) * s;
  389. quat->y = (m[9] + m[6]) * s;
  390. break;
  391. }
  392. s = sqrtf(m[0] - (m[5] + m[10]) + 1.0f);
  393. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  394. quat->x = s * 0.5f;
  395. s = 0.5f / s;
  396. quat->w = (m[9] - m[6]) * s;
  397. quat->y = (m[1] + m[4]) * s;
  398. quat->z = (m[2] + m[8]) * s;
  399. break;
  400. }
  401. break;
  402. case I:
  403. s = sqrtf(m[10] - (m[0] + m[5]) + 1.0f);
  404. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  405. quat->z = s * 0.5f;
  406. s = 0.5f / s;
  407. quat->w = (m[4] - m[1]) * s;
  408. quat->x = (m[8] + m[2]) * s;
  409. quat->y = (m[9] + m[6]) * s;
  410. break;
  411. }
  412. s = sqrtf(m[0] - (m[5] + m[10]) + 1.0f);
  413. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  414. quat->x = s * 0.5f;
  415. s = 0.5f / s;
  416. quat->w = (m[9] - m[6]) * s;
  417. quat->y = (m[1] + m[4]) * s;
  418. quat->z = (m[2] + m[8]) * s;
  419. break;
  420. }
  421. s = sqrtf(m[5] - (m[10] + m[0]) + 1.0f);
  422. if (s > QUATERNION_TRACE_ZERO_TOLERANCE) {
  423. quat->y = s * 0.5f;
  424. s = 0.5f / s;
  425. quat->w = (m[2] - m[8]) * s;
  426. quat->z = (m[6] + m[9]) * s;
  427. quat->x = (m[4] + m[1]) * s;
  428. break;
  429. }
  430. break;
  431. default:
  432. break;
  433. }
  434. }
  435. return quat;
  436. }
  437. // Builds a transformation matrix that translates, rotates and scales according to the specified vectors,
  438. // stores the result in pOut and returns the result
  439. kmMat4* kmMat4Transformation(kmMat4* pOut, const kmVec3 translation, const kmVec3 rotation, const kmVec3 scale) {
  440. /*
  441. | gxR0 gyR4 gzR8 tx |
  442. M = | gxR1 gyR5 gzR9 ty |
  443. | gxR2 gyR6 gzR10 tz |
  444. | 0 0 0 1 |
  445. where Rn is an element of the rotation matrix (R0 - R15).
  446. where tx = translation.x, ty = translation.y, tz = translation.z
  447. where gx = scale.x, gy = scale.y, gz = scale.z
  448. */
  449. // Start with basic rotation matrix
  450. kmMat4RotationYXZ(pOut, rotation.x, rotation.y, rotation.z);
  451. // Adjust for scale and translation
  452. kmScalar* m = pOut->mat;
  453. m[0] *= scale.x;
  454. m[1] *= scale.x;
  455. m[2] *= scale.x;
  456. m[3] = 0.0;
  457. m[4] *= scale.y;
  458. m[5] *= scale.y;
  459. m[6] *= scale.y;
  460. m[7] = 0.0;
  461. m[8] *= scale.z;
  462. m[9] *= scale.z;
  463. m[10] *= scale.z;
  464. m[11] = 0.0;
  465. m[12] = translation.x;
  466. m[13] = translation.y;
  467. m[14] = translation.z;
  468. m[15] = 1.0;
  469. return pOut;
  470. }
  471. float kmMatGet(const kmMat4* pIn, int row, int col) {
  472. return pIn->mat[row + 4*col];
  473. }
  474. void kmMatSet(kmMat4* pIn, int row, int col, float value) {
  475. pIn->mat[row + 4*col] = value;
  476. }
  477. void kmMatSwap(kmMat4* pIn, int r1, int c1, int r2, int c2) {
  478. float tmp = kmMatGet(pIn,r1,c1);
  479. kmMatSet(pIn,r1,c1,kmMatGet(pIn,r2,c2));
  480. kmMatSet(pIn,r2,c2, tmp);
  481. }
  482. // Returns an upper and a lower triangular matrix which are L and R in the Gauss algorithm
  483. int kmGaussJordan(kmMat4* a, kmMat4* b) {
  484. int i, icol = 0, irow = 0, j, k, l, ll, n = 4, m = 4;
  485. float big, dum, pivinv;
  486. int indxc[n];
  487. int indxr[n];
  488. int ipiv[n];
  489. for (j = 0; j < n; j++) {
  490. ipiv[j] = 0;
  491. }
  492. for (i = 0; i < n; i++) {
  493. big = 0.0f;
  494. for (j = 0; j < n; j++) {
  495. if (ipiv[j] != 1) {
  496. for (k = 0; k < n; k++) {
  497. if (ipiv[k] == 0) {
  498. if (abs(kmMatGet(a,j, k)) >= big) {
  499. big = abs(kmMatGet(a,j, k));
  500. irow = j;
  501. icol = k;
  502. }
  503. }
  504. }
  505. }
  506. }
  507. ++(ipiv[icol]);
  508. if (irow != icol) {
  509. for (l = 0; l < n; l++) {
  510. kmMatSwap(a,irow, l, icol, l);
  511. }
  512. for (l = 0; l < m; l++) {
  513. kmMatSwap(b,irow, l, icol, l);
  514. }
  515. }
  516. indxr[i] = irow;
  517. indxc[i] = icol;
  518. if (kmMatGet(a,icol, icol) == 0.0) {
  519. return KM_FALSE;
  520. }
  521. pivinv = 1.0f / kmMatGet(a,icol, icol);
  522. kmMatSet(a,icol, icol, 1.0f);
  523. for (l = 0; l < n; l++) {
  524. kmMatSet(a,icol, l, kmMatGet(a,icol, l) * pivinv);
  525. }
  526. for (l = 0; l < m; l++) {
  527. kmMatSet(b,icol, l, kmMatGet(b,icol, l) * pivinv);
  528. }
  529. for (ll = 0; ll < n; ll++) {
  530. if (ll != icol) {
  531. dum = kmMatGet(a,ll, icol);
  532. kmMatSet(a,ll, icol, 0.0f);
  533. for (l = 0; l < n; l++) {
  534. kmMatSet(a,ll, l, kmMatGet(a,ll, l) - kmMatGet(a,icol, l) * dum);
  535. }
  536. for (l = 0; l < m; l++) {
  537. kmMatSet(b,ll, l, kmMatGet(a,ll, l) - kmMatGet(b,icol, l) * dum);
  538. }
  539. }
  540. }
  541. }
  542. // This is the end of the main loop over columns of the reduction. It only remains to unscram-
  543. // ble the solution in view of the column interchanges. We do this by interchanging pairs of
  544. // columns in the reverse order that the permutation was built up.
  545. for (l = n - 1; l >= 0; l--) {
  546. if (indxr[l] != indxc[l]) {
  547. for (k = 0; k < n; k++) {
  548. kmMatSwap(a,k, indxr[l], k, indxc[l]);
  549. }
  550. }
  551. }
  552. return KM_TRUE;
  553. }