matrix.inl 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  1. // This code is in the public domain -- [email protected]
  2. #pragma once
  3. #ifndef NV_MATH_MATRIX_INL
  4. #define NV_MATH_MATRIX_INL
  5. #include "matrix.h"
  6. namespace nv
  7. {
  8. inline Matrix3::Matrix3() {}
  9. inline Matrix3::Matrix3(float f)
  10. {
  11. for(int i = 0; i < 9; i++) {
  12. m_data[i] = f;
  13. }
  14. }
  15. inline Matrix3::Matrix3(identity_t)
  16. {
  17. for(int i = 0; i < 3; i++) {
  18. for(int j = 0; j < 3; j++) {
  19. m_data[3*j+i] = (i == j) ? 1.0f : 0.0f;
  20. }
  21. }
  22. }
  23. inline Matrix3::Matrix3(const Matrix3 & m)
  24. {
  25. for(int i = 0; i < 9; i++) {
  26. m_data[i] = m.m_data[i];
  27. }
  28. }
  29. inline Matrix3::Matrix3(Vector3::Arg v0, Vector3::Arg v1, Vector3::Arg v2)
  30. {
  31. m_data[0] = v0.x; m_data[1] = v0.y; m_data[2] = v0.z;
  32. m_data[3] = v1.x; m_data[4] = v1.y; m_data[5] = v1.z;
  33. m_data[6] = v2.x; m_data[7] = v2.y; m_data[8] = v2.z;
  34. }
  35. inline float Matrix3::data(uint idx) const
  36. {
  37. nvDebugCheck(idx < 9);
  38. return m_data[idx];
  39. }
  40. inline float & Matrix3::data(uint idx)
  41. {
  42. nvDebugCheck(idx < 9);
  43. return m_data[idx];
  44. }
  45. inline float Matrix3::get(uint row, uint col) const
  46. {
  47. nvDebugCheck(row < 3 && col < 3);
  48. return m_data[col * 3 + row];
  49. }
  50. inline float Matrix3::operator()(uint row, uint col) const
  51. {
  52. nvDebugCheck(row < 3 && col < 3);
  53. return m_data[col * 3 + row];
  54. }
  55. inline float & Matrix3::operator()(uint row, uint col)
  56. {
  57. nvDebugCheck(row < 3 && col < 3);
  58. return m_data[col * 3 + row];
  59. }
  60. inline Vector3 Matrix3::row(uint i) const
  61. {
  62. nvDebugCheck(i < 3);
  63. return Vector3(get(i, 0), get(i, 1), get(i, 2));
  64. }
  65. inline Vector3 Matrix3::column(uint i) const
  66. {
  67. nvDebugCheck(i < 3);
  68. return Vector3(get(0, i), get(1, i), get(2, i));
  69. }
  70. inline void Matrix3::operator*=(float s)
  71. {
  72. for(int i = 0; i < 9; i++) {
  73. m_data[i] *= s;
  74. }
  75. }
  76. inline void Matrix3::operator/=(float s)
  77. {
  78. float is = 1.0f /s;
  79. for(int i = 0; i < 9; i++) {
  80. m_data[i] *= is;
  81. }
  82. }
  83. inline void Matrix3::operator+=(const Matrix3 & m)
  84. {
  85. for(int i = 0; i < 9; i++) {
  86. m_data[i] += m.m_data[i];
  87. }
  88. }
  89. inline void Matrix3::operator-=(const Matrix3 & m)
  90. {
  91. for(int i = 0; i < 9; i++) {
  92. m_data[i] -= m.m_data[i];
  93. }
  94. }
  95. inline Matrix3 operator+(const Matrix3 & a, const Matrix3 & b)
  96. {
  97. Matrix3 m = a;
  98. m += b;
  99. return m;
  100. }
  101. inline Matrix3 operator-(const Matrix3 & a, const Matrix3 & b)
  102. {
  103. Matrix3 m = a;
  104. m -= b;
  105. return m;
  106. }
  107. inline Matrix3 operator*(const Matrix3 & a, float s)
  108. {
  109. Matrix3 m = a;
  110. m *= s;
  111. return m;
  112. }
  113. inline Matrix3 operator*(float s, const Matrix3 & a)
  114. {
  115. Matrix3 m = a;
  116. m *= s;
  117. return m;
  118. }
  119. inline Matrix3 operator/(const Matrix3 & a, float s)
  120. {
  121. Matrix3 m = a;
  122. m /= s;
  123. return m;
  124. }
  125. inline Matrix3 mul(const Matrix3 & a, const Matrix3 & b)
  126. {
  127. Matrix3 m;
  128. for(int i = 0; i < 3; i++) {
  129. const float ai0 = a(i,0), ai1 = a(i,1), ai2 = a(i,2);
  130. m(i, 0) = ai0 * b(0,0) + ai1 * b(1,0) + ai2 * b(2,0);
  131. m(i, 1) = ai0 * b(0,1) + ai1 * b(1,1) + ai2 * b(2,1);
  132. m(i, 2) = ai0 * b(0,2) + ai1 * b(1,2) + ai2 * b(2,2);
  133. }
  134. return m;
  135. }
  136. inline Matrix3 operator*(const Matrix3 & a, const Matrix3 & b)
  137. {
  138. return mul(a, b);
  139. }
  140. // Transform the given 3d vector with the given matrix.
  141. inline Vector3 transform(const Matrix3 & m, const Vector3 & p)
  142. {
  143. return Vector3(
  144. p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2),
  145. p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2),
  146. p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2));
  147. }
  148. inline void Matrix3::scale(float s)
  149. {
  150. for (int i = 0; i < 9; i++) {
  151. m_data[i] *= s;
  152. }
  153. }
  154. inline void Matrix3::scale(Vector3::Arg s)
  155. {
  156. m_data[0] *= s.x; m_data[1] *= s.x; m_data[2] *= s.x;
  157. m_data[3] *= s.y; m_data[4] *= s.y; m_data[5] *= s.y;
  158. m_data[6] *= s.z; m_data[7] *= s.z; m_data[8] *= s.z;
  159. }
  160. inline float Matrix3::determinant() const
  161. {
  162. return
  163. get(0,0) * get(1,1) * get(2,2) +
  164. get(0,1) * get(1,2) * get(2,0) +
  165. get(0,2) * get(1,0) * get(2,1) -
  166. get(0,2) * get(1,1) * get(2,0) -
  167. get(0,1) * get(1,0) * get(2,2) -
  168. get(0,0) * get(1,2) * get(2,1);
  169. }
  170. // Inverse using Cramer's rule.
  171. inline Matrix3 inverseCramer(const Matrix3 & m)
  172. {
  173. const float det = m.determinant();
  174. if (equal(det, 0.0f, 0.0f)) {
  175. return Matrix3(0);
  176. }
  177. Matrix3 r;
  178. r.data(0) = - m.data(5) * m.data(7) + m.data(4) * m.data(8);
  179. r.data(1) = + m.data(5) * m.data(6) - m.data(3) * m.data(8);
  180. r.data(2) = - m.data(4) * m.data(6) + m.data(3) * m.data(7);
  181. r.data(3) = + m.data(2) * m.data(7) - m.data(1) * m.data(8);
  182. r.data(4) = - m.data(2) * m.data(6) + m.data(0) * m.data(8);
  183. r.data(5) = + m.data(1) * m.data(6) - m.data(0) * m.data(7);
  184. r.data(6) = - m.data(2) * m.data(4) + m.data(1) * m.data(5);
  185. r.data(7) = + m.data(2) * m.data(3) - m.data(0) * m.data(5);
  186. r.data(8) = - m.data(1) * m.data(3) + m.data(0) * m.data(4);
  187. r.scale(1.0f / det);
  188. return r;
  189. }
  190. inline Matrix::Matrix()
  191. {
  192. }
  193. inline Matrix::Matrix(float f)
  194. {
  195. for(int i = 0; i < 16; i++) {
  196. m_data[i] = 0.0f;
  197. }
  198. }
  199. inline Matrix::Matrix(identity_t)
  200. {
  201. for(int i = 0; i < 4; i++) {
  202. for(int j = 0; j < 4; j++) {
  203. m_data[4*j+i] = (i == j) ? 1.0f : 0.0f;
  204. }
  205. }
  206. }
  207. inline Matrix::Matrix(const Matrix & m)
  208. {
  209. for(int i = 0; i < 16; i++) {
  210. m_data[i] = m.m_data[i];
  211. }
  212. }
  213. inline Matrix::Matrix(const Matrix3 & m)
  214. {
  215. for(int i = 0; i < 3; i++) {
  216. for(int j = 0; j < 3; j++) {
  217. operator()(i, j) = m.get(i, j);
  218. }
  219. }
  220. for(int i = 0; i < 4; i++) {
  221. operator()(3, i) = 0;
  222. operator()(i, 3) = 0;
  223. }
  224. }
  225. inline Matrix::Matrix(Vector4::Arg v0, Vector4::Arg v1, Vector4::Arg v2, Vector4::Arg v3)
  226. {
  227. m_data[ 0] = v0.x; m_data[ 1] = v0.y; m_data[ 2] = v0.z; m_data[ 3] = v0.w;
  228. m_data[ 4] = v1.x; m_data[ 5] = v1.y; m_data[ 6] = v1.z; m_data[ 7] = v1.w;
  229. m_data[ 8] = v2.x; m_data[ 9] = v2.y; m_data[10] = v2.z; m_data[11] = v2.w;
  230. m_data[12] = v3.x; m_data[13] = v3.y; m_data[14] = v3.z; m_data[15] = v3.w;
  231. }
  232. /*inline Matrix::Matrix(const float m[])
  233. {
  234. for(int i = 0; i < 16; i++) {
  235. m_data[i] = m[i];
  236. }
  237. }*/
  238. // Accessors
  239. inline float Matrix::data(uint idx) const
  240. {
  241. nvDebugCheck(idx < 16);
  242. return m_data[idx];
  243. }
  244. inline float & Matrix::data(uint idx)
  245. {
  246. nvDebugCheck(idx < 16);
  247. return m_data[idx];
  248. }
  249. inline float Matrix::get(uint row, uint col) const
  250. {
  251. nvDebugCheck(row < 4 && col < 4);
  252. return m_data[col * 4 + row];
  253. }
  254. inline float Matrix::operator()(uint row, uint col) const
  255. {
  256. nvDebugCheck(row < 4 && col < 4);
  257. return m_data[col * 4 + row];
  258. }
  259. inline float & Matrix::operator()(uint row, uint col)
  260. {
  261. nvDebugCheck(row < 4 && col < 4);
  262. return m_data[col * 4 + row];
  263. }
  264. inline const float * Matrix::ptr() const
  265. {
  266. return m_data;
  267. }
  268. inline Vector4 Matrix::row(uint i) const
  269. {
  270. nvDebugCheck(i < 4);
  271. return Vector4(get(i, 0), get(i, 1), get(i, 2), get(i, 3));
  272. }
  273. inline Vector4 Matrix::column(uint i) const
  274. {
  275. nvDebugCheck(i < 4);
  276. return Vector4(get(0, i), get(1, i), get(2, i), get(3, i));
  277. }
  278. inline void Matrix::zero()
  279. {
  280. m_data[0] = 0; m_data[1] = 0; m_data[2] = 0; m_data[3] = 0;
  281. m_data[4] = 0; m_data[5] = 0; m_data[6] = 0; m_data[7] = 0;
  282. m_data[8] = 0; m_data[9] = 0; m_data[10] = 0; m_data[11] = 0;
  283. m_data[12] = 0; m_data[13] = 0; m_data[14] = 0; m_data[15] = 0;
  284. }
  285. inline void Matrix::identity()
  286. {
  287. m_data[0] = 1; m_data[1] = 0; m_data[2] = 0; m_data[3] = 0;
  288. m_data[4] = 0; m_data[5] = 1; m_data[6] = 0; m_data[7] = 0;
  289. m_data[8] = 0; m_data[9] = 0; m_data[10] = 1; m_data[11] = 0;
  290. m_data[12] = 0; m_data[13] = 0; m_data[14] = 0; m_data[15] = 1;
  291. }
  292. // Apply scale.
  293. inline void Matrix::scale(float s)
  294. {
  295. m_data[0] *= s; m_data[1] *= s; m_data[2] *= s; m_data[3] *= s;
  296. m_data[4] *= s; m_data[5] *= s; m_data[6] *= s; m_data[7] *= s;
  297. m_data[8] *= s; m_data[9] *= s; m_data[10] *= s; m_data[11] *= s;
  298. m_data[12] *= s; m_data[13] *= s; m_data[14] *= s; m_data[15] *= s;
  299. }
  300. // Apply scale.
  301. inline void Matrix::scale(Vector3::Arg s)
  302. {
  303. m_data[0] *= s.x; m_data[1] *= s.x; m_data[2] *= s.x; m_data[3] *= s.x;
  304. m_data[4] *= s.y; m_data[5] *= s.y; m_data[6] *= s.y; m_data[7] *= s.y;
  305. m_data[8] *= s.z; m_data[9] *= s.z; m_data[10] *= s.z; m_data[11] *= s.z;
  306. }
  307. // Apply translation.
  308. inline void Matrix::translate(Vector3::Arg t)
  309. {
  310. m_data[12] = m_data[0] * t.x + m_data[4] * t.y + m_data[8] * t.z + m_data[12];
  311. m_data[13] = m_data[1] * t.x + m_data[5] * t.y + m_data[9] * t.z + m_data[13];
  312. m_data[14] = m_data[2] * t.x + m_data[6] * t.y + m_data[10] * t.z + m_data[14];
  313. m_data[15] = m_data[3] * t.x + m_data[7] * t.y + m_data[11] * t.z + m_data[15];
  314. }
  315. Matrix rotation(float theta, float v0, float v1, float v2);
  316. // Apply rotation.
  317. inline void Matrix::rotate(float theta, float v0, float v1, float v2)
  318. {
  319. Matrix R(rotation(theta, v0, v1, v2));
  320. apply(R);
  321. }
  322. // Apply transform.
  323. inline void Matrix::apply(Matrix::Arg m)
  324. {
  325. nvDebugCheck(this != &m);
  326. for(int i = 0; i < 4; i++) {
  327. const float ai0 = get(i,0), ai1 = get(i,1), ai2 = get(i,2), ai3 = get(i,3);
  328. m_data[0 + i] = ai0 * m(0,0) + ai1 * m(1,0) + ai2 * m(2,0) + ai3 * m(3,0);
  329. m_data[4 + i] = ai0 * m(0,1) + ai1 * m(1,1) + ai2 * m(2,1) + ai3 * m(3,1);
  330. m_data[8 + i] = ai0 * m(0,2) + ai1 * m(1,2) + ai2 * m(2,2) + ai3 * m(3,2);
  331. m_data[12+ i] = ai0 * m(0,3) + ai1 * m(1,3) + ai2 * m(2,3) + ai3 * m(3,3);
  332. }
  333. }
  334. // Get scale matrix.
  335. inline Matrix scale(Vector3::Arg s)
  336. {
  337. Matrix m(identity);
  338. m(0,0) = s.x;
  339. m(1,1) = s.y;
  340. m(2,2) = s.z;
  341. return m;
  342. }
  343. // Get scale matrix.
  344. inline Matrix scale(float s)
  345. {
  346. Matrix m(identity);
  347. m(0,0) = m(1,1) = m(2,2) = s;
  348. return m;
  349. }
  350. // Get translation matrix.
  351. inline Matrix translation(Vector3::Arg t)
  352. {
  353. Matrix m(identity);
  354. m(0,3) = t.x;
  355. m(1,3) = t.y;
  356. m(2,3) = t.z;
  357. return m;
  358. }
  359. // Get rotation matrix.
  360. inline Matrix rotation(float theta, float v0, float v1, float v2)
  361. {
  362. float cost = cosf(theta);
  363. float sint = sinf(theta);
  364. Matrix m(identity);
  365. if( 1 == v0 && 0 == v1 && 0 == v2 ) {
  366. m(1,1) = cost; m(2,1) = -sint;
  367. m(1,2) = sint; m(2,2) = cost;
  368. }
  369. else if( 0 == v0 && 1 == v1 && 0 == v2 ) {
  370. m(0,0) = cost; m(2,0) = sint;
  371. m(1,2) = -sint; m(2,2) = cost;
  372. }
  373. else if( 0 == v0 && 0 == v1 && 1 == v2 ) {
  374. m(0,0) = cost; m(1,0) = -sint;
  375. m(0,1) = sint; m(1,1) = cost;
  376. }
  377. else {
  378. float a2, b2, c2;
  379. a2 = v0 * v0;
  380. b2 = v1 * v1;
  381. c2 = v2 * v2;
  382. float iscale = 1.0f / sqrtf(a2 + b2 + c2);
  383. v0 *= iscale;
  384. v1 *= iscale;
  385. v2 *= iscale;
  386. float abm, acm, bcm;
  387. float mcos, asin, bsin, csin;
  388. mcos = 1.0f - cost;
  389. abm = v0 * v1 * mcos;
  390. acm = v0 * v2 * mcos;
  391. bcm = v1 * v2 * mcos;
  392. asin = v0 * sint;
  393. bsin = v1 * sint;
  394. csin = v2 * sint;
  395. m(0,0) = a2 * mcos + cost;
  396. m(1,0) = abm - csin;
  397. m(2,0) = acm + bsin;
  398. m(3,0) = abm + csin;
  399. m(1,1) = b2 * mcos + cost;
  400. m(2,1) = bcm - asin;
  401. m(3,1) = acm - bsin;
  402. m(1,2) = bcm + asin;
  403. m(2,2) = c2 * mcos + cost;
  404. }
  405. return m;
  406. }
  407. //Matrix rotation(float yaw, float pitch, float roll);
  408. //Matrix skew(float angle, Vector3::Arg v1, Vector3::Arg v2);
  409. // Get frustum matrix.
  410. inline Matrix frustum(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar)
  411. {
  412. Matrix m(0.0f);
  413. float doubleznear = 2.0f * zNear;
  414. float one_deltax = 1.0f / (xmax - xmin);
  415. float one_deltay = 1.0f / (ymax - ymin);
  416. float one_deltaz = 1.0f / (zFar - zNear);
  417. m(0,0) = doubleznear * one_deltax;
  418. m(1,1) = doubleznear * one_deltay;
  419. m(0,2) = (xmax + xmin) * one_deltax;
  420. m(1,2) = (ymax + ymin) * one_deltay;
  421. m(2,2) = -(zFar + zNear) * one_deltaz;
  422. m(3,2) = -1.0f;
  423. m(2,3) = -(zFar * doubleznear) * one_deltaz;
  424. return m;
  425. }
  426. // Get inverse frustum matrix.
  427. inline Matrix frustumInverse(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar)
  428. {
  429. Matrix m(0.0f);
  430. float one_doubleznear = 1.0f / (2.0f * zNear);
  431. float one_doubleznearzfar = 1.0f / (2.0f * zNear * zFar);
  432. m(0,0) = (xmax - xmin) * one_doubleznear;
  433. m(0,3) = (xmax + xmin) * one_doubleznear;
  434. m(1,1) = (ymax - ymin) * one_doubleznear;
  435. m(1,3) = (ymax + ymin) * one_doubleznear;
  436. m(2,3) = -1;
  437. m(3,2) = -(zFar - zNear) * one_doubleznearzfar;
  438. m(3,3) = (zFar + zNear) * one_doubleznearzfar;
  439. return m;
  440. }
  441. // Get infinite frustum matrix.
  442. inline Matrix frustum(float xmin, float xmax, float ymin, float ymax, float zNear)
  443. {
  444. Matrix m(0.0f);
  445. float doubleznear = 2.0f * zNear;
  446. float one_deltax = 1.0f / (xmax - xmin);
  447. float one_deltay = 1.0f / (ymax - ymin);
  448. float nudge = 1.0; // 0.999;
  449. m(0,0) = doubleznear * one_deltax;
  450. m(1,1) = doubleznear * one_deltay;
  451. m(0,2) = (xmax + xmin) * one_deltax;
  452. m(1,2) = (ymax + ymin) * one_deltay;
  453. m(2,2) = -1.0f * nudge;
  454. m(3,2) = -1.0f;
  455. m(2,3) = -doubleznear * nudge;
  456. return m;
  457. }
  458. // Get perspective matrix.
  459. inline Matrix perspective(float fovy, float aspect, float zNear, float zFar)
  460. {
  461. float xmax = zNear * tanf(fovy / 2);
  462. float xmin = -xmax;
  463. float ymax = xmax / aspect;
  464. float ymin = -ymax;
  465. return frustum(xmin, xmax, ymin, ymax, zNear, zFar);
  466. }
  467. // Get inverse perspective matrix.
  468. inline Matrix perspectiveInverse(float fovy, float aspect, float zNear, float zFar)
  469. {
  470. float xmax = zNear * tanf(fovy / 2);
  471. float xmin = -xmax;
  472. float ymax = xmax / aspect;
  473. float ymin = -ymax;
  474. return frustumInverse(xmin, xmax, ymin, ymax, zNear, zFar);
  475. }
  476. // Get infinite perspective matrix.
  477. inline Matrix perspective(float fovy, float aspect, float zNear)
  478. {
  479. float x = zNear * tanf(fovy / 2);
  480. float y = x / aspect;
  481. return frustum( -x, x, -y, y, zNear );
  482. }
  483. // Get matrix determinant.
  484. inline float Matrix::determinant() const
  485. {
  486. return
  487. m_data[3] * m_data[6] * m_data[ 9] * m_data[12] - m_data[2] * m_data[7] * m_data[ 9] * m_data[12] - m_data[3] * m_data[5] * m_data[10] * m_data[12] + m_data[1] * m_data[7] * m_data[10] * m_data[12] +
  488. m_data[2] * m_data[5] * m_data[11] * m_data[12] - m_data[1] * m_data[6] * m_data[11] * m_data[12] - m_data[3] * m_data[6] * m_data[ 8] * m_data[13] + m_data[2] * m_data[7] * m_data[ 8] * m_data[13] +
  489. m_data[3] * m_data[4] * m_data[10] * m_data[13] - m_data[0] * m_data[7] * m_data[10] * m_data[13] - m_data[2] * m_data[4] * m_data[11] * m_data[13] + m_data[0] * m_data[6] * m_data[11] * m_data[13] +
  490. m_data[3] * m_data[5] * m_data[ 8] * m_data[14] - m_data[1] * m_data[7] * m_data[ 8] * m_data[14] - m_data[3] * m_data[4] * m_data[ 9] * m_data[14] + m_data[0] * m_data[7] * m_data[ 9] * m_data[14] +
  491. m_data[1] * m_data[4] * m_data[11] * m_data[14] - m_data[0] * m_data[5] * m_data[11] * m_data[14] - m_data[2] * m_data[5] * m_data[ 8] * m_data[15] + m_data[1] * m_data[6] * m_data[ 8] * m_data[15] +
  492. m_data[2] * m_data[4] * m_data[ 9] * m_data[15] - m_data[0] * m_data[6] * m_data[ 9] * m_data[15] - m_data[1] * m_data[4] * m_data[10] * m_data[15] + m_data[0] * m_data[5] * m_data[10] * m_data[15];
  493. }
  494. inline Matrix transpose(Matrix::Arg m)
  495. {
  496. Matrix r;
  497. for (int i = 0; i < 4; i++)
  498. {
  499. for (int j = 0; j < 4; j++)
  500. {
  501. r(i, j) = m(j, i);
  502. }
  503. }
  504. return r;
  505. }
  506. // Inverse using Cramer's rule.
  507. inline Matrix inverseCramer(Matrix::Arg m)
  508. {
  509. Matrix r;
  510. r.data( 0) = m.data(6)*m.data(11)*m.data(13) - m.data(7)*m.data(10)*m.data(13) + m.data(7)*m.data(9)*m.data(14) - m.data(5)*m.data(11)*m.data(14) - m.data(6)*m.data(9)*m.data(15) + m.data(5)*m.data(10)*m.data(15);
  511. r.data( 1) = m.data(3)*m.data(10)*m.data(13) - m.data(2)*m.data(11)*m.data(13) - m.data(3)*m.data(9)*m.data(14) + m.data(1)*m.data(11)*m.data(14) + m.data(2)*m.data(9)*m.data(15) - m.data(1)*m.data(10)*m.data(15);
  512. r.data( 2) = m.data(2)*m.data( 7)*m.data(13) - m.data(3)*m.data( 6)*m.data(13) + m.data(3)*m.data(5)*m.data(14) - m.data(1)*m.data( 7)*m.data(14) - m.data(2)*m.data(5)*m.data(15) + m.data(1)*m.data( 6)*m.data(15);
  513. r.data( 3) = m.data(3)*m.data( 6)*m.data( 9) - m.data(2)*m.data( 7)*m.data( 9) - m.data(3)*m.data(5)*m.data(10) + m.data(1)*m.data( 7)*m.data(10) + m.data(2)*m.data(5)*m.data(11) - m.data(1)*m.data( 6)*m.data(11);
  514. r.data( 4) = m.data(7)*m.data(10)*m.data(12) - m.data(6)*m.data(11)*m.data(12) - m.data(7)*m.data(8)*m.data(14) + m.data(4)*m.data(11)*m.data(14) + m.data(6)*m.data(8)*m.data(15) - m.data(4)*m.data(10)*m.data(15);
  515. r.data( 5) = m.data(2)*m.data(11)*m.data(12) - m.data(3)*m.data(10)*m.data(12) + m.data(3)*m.data(8)*m.data(14) - m.data(0)*m.data(11)*m.data(14) - m.data(2)*m.data(8)*m.data(15) + m.data(0)*m.data(10)*m.data(15);
  516. r.data( 6) = m.data(3)*m.data( 6)*m.data(12) - m.data(2)*m.data( 7)*m.data(12) - m.data(3)*m.data(4)*m.data(14) + m.data(0)*m.data( 7)*m.data(14) + m.data(2)*m.data(4)*m.data(15) - m.data(0)*m.data( 6)*m.data(15);
  517. r.data( 7) = m.data(2)*m.data( 7)*m.data( 8) - m.data(3)*m.data( 6)*m.data( 8) + m.data(3)*m.data(4)*m.data(10) - m.data(0)*m.data( 7)*m.data(10) - m.data(2)*m.data(4)*m.data(11) + m.data(0)*m.data( 6)*m.data(11);
  518. r.data( 8) = m.data(5)*m.data(11)*m.data(12) - m.data(7)*m.data( 9)*m.data(12) + m.data(7)*m.data(8)*m.data(13) - m.data(4)*m.data(11)*m.data(13) - m.data(5)*m.data(8)*m.data(15) + m.data(4)*m.data( 9)*m.data(15);
  519. r.data( 9) = m.data(3)*m.data( 9)*m.data(12) - m.data(1)*m.data(11)*m.data(12) - m.data(3)*m.data(8)*m.data(13) + m.data(0)*m.data(11)*m.data(13) + m.data(1)*m.data(8)*m.data(15) - m.data(0)*m.data( 9)*m.data(15);
  520. r.data(10) = m.data(1)*m.data( 7)*m.data(12) - m.data(3)*m.data( 5)*m.data(12) + m.data(3)*m.data(4)*m.data(13) - m.data(0)*m.data( 7)*m.data(13) - m.data(1)*m.data(4)*m.data(15) + m.data(0)*m.data( 5)*m.data(15);
  521. r.data(11) = m.data(3)*m.data( 5)*m.data( 8) - m.data(1)*m.data( 7)*m.data( 8) - m.data(3)*m.data(4)*m.data( 9) + m.data(0)*m.data( 7)*m.data( 9) + m.data(1)*m.data(4)*m.data(11) - m.data(0)*m.data( 5)*m.data(11);
  522. r.data(12) = m.data(6)*m.data( 9)*m.data(12) - m.data(5)*m.data(10)*m.data(12) - m.data(6)*m.data(8)*m.data(13) + m.data(4)*m.data(10)*m.data(13) + m.data(5)*m.data(8)*m.data(14) - m.data(4)*m.data( 9)*m.data(14);
  523. r.data(13) = m.data(1)*m.data(10)*m.data(12) - m.data(2)*m.data( 9)*m.data(12) + m.data(2)*m.data(8)*m.data(13) - m.data(0)*m.data(10)*m.data(13) - m.data(1)*m.data(8)*m.data(14) + m.data(0)*m.data( 9)*m.data(14);
  524. r.data(14) = m.data(2)*m.data( 5)*m.data(12) - m.data(1)*m.data( 6)*m.data(12) - m.data(2)*m.data(4)*m.data(13) + m.data(0)*m.data( 6)*m.data(13) + m.data(1)*m.data(4)*m.data(14) - m.data(0)*m.data( 5)*m.data(14);
  525. r.data(15) = m.data(1)*m.data( 6)*m.data( 8) - m.data(2)*m.data( 5)*m.data( 8) + m.data(2)*m.data(4)*m.data( 9) - m.data(0)*m.data( 6)*m.data( 9) - m.data(1)*m.data(4)*m.data(10) + m.data(0)*m.data( 5)*m.data(10);
  526. r.scale(1.0f / m.determinant());
  527. return r;
  528. }
  529. inline Matrix isometryInverse(Matrix::Arg m)
  530. {
  531. Matrix r(identity);
  532. // transposed 3x3 upper left matrix
  533. for (int i = 0; i < 3; i++)
  534. {
  535. for (int j = 0; j < 3; j++)
  536. {
  537. r(i, j) = m(j, i);
  538. }
  539. }
  540. // translate by the negative offsets
  541. r.translate(-Vector3(m.data(12), m.data(13), m.data(14)));
  542. return r;
  543. }
  544. // Transform the given 3d point with the given matrix.
  545. inline Vector3 transformPoint(Matrix::Arg m, Vector3::Arg p)
  546. {
  547. return Vector3(
  548. p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2) + m(0,3),
  549. p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2) + m(1,3),
  550. p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2) + m(2,3));
  551. }
  552. // Transform the given 3d vector with the given matrix.
  553. inline Vector3 transformVector(Matrix::Arg m, Vector3::Arg p)
  554. {
  555. return Vector3(
  556. p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2),
  557. p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2),
  558. p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2));
  559. }
  560. // Transform the given 4d vector with the given matrix.
  561. inline Vector4 transform(Matrix::Arg m, Vector4::Arg p)
  562. {
  563. return Vector4(
  564. p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2) + p.w * m(0,3),
  565. p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2) + p.w * m(1,3),
  566. p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2) + p.w * m(2,3),
  567. p.x * m(3,0) + p.y * m(3,1) + p.z * m(3,2) + p.w * m(3,3));
  568. }
  569. inline Matrix mul(Matrix::Arg a, Matrix::Arg b)
  570. {
  571. // @@ Is this the right order? mul(a, b) = b * a
  572. Matrix m = a;
  573. m.apply(b);
  574. return m;
  575. }
  576. inline void Matrix::operator+=(const Matrix & m)
  577. {
  578. for(int i = 0; i < 16; i++) {
  579. m_data[i] += m.m_data[i];
  580. }
  581. }
  582. inline void Matrix::operator-=(const Matrix & m)
  583. {
  584. for(int i = 0; i < 16; i++) {
  585. m_data[i] -= m.m_data[i];
  586. }
  587. }
  588. inline Matrix operator+(const Matrix & a, const Matrix & b)
  589. {
  590. Matrix m = a;
  591. m += b;
  592. return m;
  593. }
  594. inline Matrix operator-(const Matrix & a, const Matrix & b)
  595. {
  596. Matrix m = a;
  597. m -= b;
  598. return m;
  599. }
  600. } // nv namespace
  601. #if 0 // old code.
  602. /** @name Special matrices. */
  603. //@{
  604. /** Generate a translation matrix. */
  605. void TranslationMatrix(const Vec3 & v) {
  606. data[0] = 1; data[1] = 0; data[2] = 0; data[3] = 0;
  607. data[4] = 0; data[5] = 1; data[6] = 0; data[7] = 0;
  608. data[8] = 0; data[9] = 0; data[10] = 1; data[11] = 0;
  609. data[12] = v.x; data[13] = v.y; data[14] = v.z; data[15] = 1;
  610. }
  611. /** Rotate theta degrees around v. */
  612. void RotationMatrix( float theta, float v0, float v1, float v2 ) {
  613. float cost = cos(theta);
  614. float sint = sin(theta);
  615. if( 1 == v0 && 0 == v1 && 0 == v2 ) {
  616. data[0] = 1.0f; data[1] = 0.0f; data[2] = 0.0f; data[3] = 0.0f;
  617. data[4] = 0.0f; data[5] = cost; data[6] = -sint;data[7] = 0.0f;
  618. data[8] = 0.0f; data[9] = sint; data[10] = cost;data[11] = 0.0f;
  619. data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f;
  620. }
  621. else if( 0 == v0 && 1 == v1 && 0 == v2 ) {
  622. data[0] = cost; data[1] = 0.0f; data[2] = sint; data[3] = 0.0f;
  623. data[4] = 0.0f; data[5] = 1.0f; data[6] = 0.0f; data[7] = 0.0f;
  624. data[8] = -sint;data[9] = 0.0f;data[10] = cost; data[11] = 0.0f;
  625. data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f;
  626. }
  627. else if( 0 == v0 && 0 == v1 && 1 == v2 ) {
  628. data[0] = cost; data[1] = -sint;data[2] = 0.0f; data[3] = 0.0f;
  629. data[4] = sint; data[5] = cost; data[6] = 0.0f; data[7] = 0.0f;
  630. data[8] = 0.0f; data[9] = 0.0f; data[10] = 1.0f;data[11] = 0.0f;
  631. data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f;
  632. }
  633. else {
  634. //we need scale a,b,c to unit length.
  635. float a2, b2, c2;
  636. a2 = v0 * v0;
  637. b2 = v1 * v1;
  638. c2 = v2 * v2;
  639. float iscale = 1.0f / sqrtf(a2 + b2 + c2);
  640. v0 *= iscale;
  641. v1 *= iscale;
  642. v2 *= iscale;
  643. float abm, acm, bcm;
  644. float mcos, asin, bsin, csin;
  645. mcos = 1.0f - cost;
  646. abm = v0 * v1 * mcos;
  647. acm = v0 * v2 * mcos;
  648. bcm = v1 * v2 * mcos;
  649. asin = v0 * sint;
  650. bsin = v1 * sint;
  651. csin = v2 * sint;
  652. data[0] = a2 * mcos + cost;
  653. data[1] = abm - csin;
  654. data[2] = acm + bsin;
  655. data[3] = abm + csin;
  656. data[4] = 0.0f;
  657. data[5] = b2 * mcos + cost;
  658. data[6] = bcm - asin;
  659. data[7] = acm - bsin;
  660. data[8] = 0.0f;
  661. data[9] = bcm + asin;
  662. data[10] = c2 * mcos + cost;
  663. data[11] = 0.0f;
  664. data[12] = 0.0f;
  665. data[13] = 0.0f;
  666. data[14] = 0.0f;
  667. data[15] = 1.0f;
  668. }
  669. }
  670. /*
  671. void SkewMatrix(float angle, const Vec3 & v1, const Vec3 & v2) {
  672. v1.Normalize();
  673. v2.Normalize();
  674. Vec3 v3;
  675. v3.Cross(v1, v2);
  676. v3.Normalize();
  677. // Get skew factor.
  678. float costheta = Vec3DotProduct(v1, v2);
  679. float sintheta = Real.Sqrt(1 - costheta * costheta);
  680. float skew = tan(Trig.DegreesToRadians(angle) + acos(sintheta)) * sintheta - costheta;
  681. // Build orthonormal matrix.
  682. v1 = FXVector3.Cross(v3, v2);
  683. v1.Normalize();
  684. Matrix R = Matrix::Identity;
  685. R[0, 0] = v3.X; // Not sure this is in the correct order...
  686. R[1, 0] = v3.Y;
  687. R[2, 0] = v3.Z;
  688. R[0, 1] = v1.X;
  689. R[1, 1] = v1.Y;
  690. R[2, 1] = v1.Z;
  691. R[0, 2] = v2.X;
  692. R[1, 2] = v2.Y;
  693. R[2, 2] = v2.Z;
  694. // Build skew matrix.
  695. Matrix S = Matrix::Identity;
  696. S[2, 1] = -skew;
  697. // Return skew transform.
  698. return R * S * R.Transpose; // Not sure this is in the correct order...
  699. }
  700. */
  701. /**
  702. * Generate rotation matrix for the euler angles. This is the same as computing
  703. * 3 rotation matrices and multiplying them together in our custom order.
  704. *
  705. * @todo Have to recompute this code for our new convention.
  706. **/
  707. void RotationMatrix( float yaw, float pitch, float roll ) {
  708. float sy = sin(yaw+ToRadian(90));
  709. float cy = cos(yaw+ToRadian(90));
  710. float sp = sin(pitch-ToRadian(90));
  711. float cp = cos(pitch-ToRadian(90));
  712. float sr = sin(roll);
  713. float cr = cos(roll);
  714. data[0] = cr*cy + sr*sp*sy;
  715. data[1] = cp*sy;
  716. data[2] = -sr*cy + cr*sp*sy;
  717. data[3] = 0;
  718. data[4] = -cr*sy + sr*sp*cy;
  719. data[5] = cp*cy;
  720. data[6] = sr*sy + cr*sp*cy;
  721. data[7] = 0;
  722. data[8] = sr*cp;
  723. data[9] = -sp;
  724. data[10] = cr*cp;
  725. data[11] = 0;
  726. data[12] = 0;
  727. data[13] = 0;
  728. data[14] = 0;
  729. data[15] = 1;
  730. }
  731. /** Create a frustum matrix with the far plane at the infinity. */
  732. void Frustum( float xmin, float xmax, float ymin, float ymax, float zNear, float zFar ) {
  733. float one_deltax, one_deltay, one_deltaz, doubleznear;
  734. doubleznear = 2.0f * zNear;
  735. one_deltax = 1.0f / (xmax - xmin);
  736. one_deltay = 1.0f / (ymax - ymin);
  737. one_deltaz = 1.0f / (zFar - zNear);
  738. data[0] = (float)(doubleznear * one_deltax);
  739. data[1] = 0.0f;
  740. data[2] = 0.0f;
  741. data[3] = 0.0f;
  742. data[4] = 0.0f;
  743. data[5] = (float)(doubleznear * one_deltay);
  744. data[6] = 0.f;
  745. data[7] = 0.f;
  746. data[8] = (float)((xmax + xmin) * one_deltax);
  747. data[9] = (float)((ymax + ymin) * one_deltay);
  748. data[10] = (float)(-(zFar + zNear) * one_deltaz);
  749. data[11] = -1.f;
  750. data[12] = 0.f;
  751. data[13] = 0.f;
  752. data[14] = (float)(-(zFar * doubleznear) * one_deltaz);
  753. data[15] = 0.f;
  754. }
  755. /** Create a frustum matrix with the far plane at the infinity. */
  756. void FrustumInf( float xmin, float xmax, float ymin, float ymax, float zNear ) {
  757. float one_deltax, one_deltay, doubleznear, nudge;
  758. doubleznear = 2.0f * zNear;
  759. one_deltax = 1.0f / (xmax - xmin);
  760. one_deltay = 1.0f / (ymax - ymin);
  761. nudge = 1.0; // 0.999;
  762. data[0] = doubleznear * one_deltax;
  763. data[1] = 0.0f;
  764. data[2] = 0.0f;
  765. data[3] = 0.0f;
  766. data[4] = 0.0f;
  767. data[5] = doubleznear * one_deltay;
  768. data[6] = 0.f;
  769. data[7] = 0.f;
  770. data[8] = (xmax + xmin) * one_deltax;
  771. data[9] = (ymax + ymin) * one_deltay;
  772. data[10] = -1.0f * nudge;
  773. data[11] = -1.0f;
  774. data[12] = 0.f;
  775. data[13] = 0.f;
  776. data[14] = -doubleznear * nudge;
  777. data[15] = 0.f;
  778. }
  779. /** Create an inverse frustum matrix with the far plane at the infinity. */
  780. void FrustumInfInv( float left, float right, float bottom, float top, float zNear ) {
  781. // this matrix is wrong (not tested floatly) I think it should be transposed.
  782. data[0] = (right - left) / (2 * zNear);
  783. data[1] = 0;
  784. data[2] = 0;
  785. data[3] = (right + left) / (2 * zNear);
  786. data[4] = 0;
  787. data[5] = (top - bottom) / (2 * zNear);
  788. data[6] = 0;
  789. data[7] = (top + bottom) / (2 * zNear);
  790. data[8] = 0;
  791. data[9] = 0;
  792. data[10] = 0;
  793. data[11] = -1;
  794. data[12] = 0;
  795. data[13] = 0;
  796. data[14] = -1 / (2 * zNear);
  797. data[15] = 1 / (2 * zNear);
  798. }
  799. /** Create an homogeneous projection matrix. */
  800. void Perspective( float fov, float aspect, float zNear, float zFar ) {
  801. float xmin, xmax, ymin, ymax;
  802. xmax = zNear * tan( fov/2 );
  803. xmin = -xmax;
  804. ymax = xmax / aspect;
  805. ymin = -ymax;
  806. Frustum(xmin, xmax, ymin, ymax, zNear, zFar);
  807. }
  808. /** Create a projection matrix with the far plane at the infinity. */
  809. void PerspectiveInf( float fov, float aspect, float zNear ) {
  810. float x = zNear * tan( fov/2 );
  811. float y = x / aspect;
  812. FrustumInf( -x, x, -y, y, zNear );
  813. }
  814. /** Create an inverse projection matrix with far plane at the infinity. */
  815. void PerspectiveInfInv( float fov, float aspect, float zNear ) {
  816. float x = zNear * tan( fov/2 );
  817. float y = x / aspect;
  818. FrustumInfInv( -x, x, -y, y, zNear );
  819. }
  820. /** Build bone matrix from quatertion and offset. */
  821. void BoneMatrix(const Quat & q, const Vec3 & offset) {
  822. float x2, y2, z2, xx, xy, xz, yy, yz, zz, wx, wy, wz;
  823. // calculate coefficients
  824. x2 = q.x + q.x;
  825. y2 = q.y + q.y;
  826. z2 = q.z + q.z;
  827. xx = q.x * x2; xy = q.x * y2; xz = q.x * z2;
  828. yy = q.y * y2; yz = q.y * z2; zz = q.z * z2;
  829. wx = q.w * x2; wy = q.w * y2; wz = q.w * z2;
  830. data[0] = 1.0f - (yy + zz);
  831. data[1] = xy - wz;
  832. data[2] = xz + wy;
  833. data[3] = 0.0f;
  834. data[4] = xy + wz;
  835. data[5] = 1.0f - (xx + zz);
  836. data[6] = yz - wx;
  837. data[7] = 0.0f;
  838. data[8] = xz - wy;
  839. data[9] = yz + wx;
  840. data[10] = 1.0f - (xx + yy);
  841. data[11] = 0.0f;
  842. data[12] = offset.x;
  843. data[13] = offset.y;
  844. data[14] = offset.z;
  845. data[15] = 1.0f;
  846. }
  847. //@}
  848. /** @name Transformations: */
  849. //@{
  850. /** Apply a general scale. */
  851. void Scale( float x, float y, float z ) {
  852. data[0] *= x; data[4] *= y; data[8] *= z;
  853. data[1] *= x; data[5] *= y; data[9] *= z;
  854. data[2] *= x; data[6] *= y; data[10] *= z;
  855. data[3] *= x; data[7] *= y; data[11] *= z;
  856. }
  857. /** Apply a rotation of theta degrees around the axis v*/
  858. void Rotate( float theta, const Vec3 & v ) {
  859. Matrix b;
  860. b.RotationMatrix( theta, v[0], v[1], v[2] );
  861. Multiply4x3( b );
  862. }
  863. /** Apply a rotation of theta degrees around the axis v*/
  864. void Rotate( float theta, float v0, float v1, float v2 ) {
  865. Matrix b;
  866. b.RotationMatrix( theta, v0, v1, v2 );
  867. Multiply4x3( b );
  868. }
  869. /**
  870. * Translate the matrix by t. This is the same as multiplying by a
  871. * translation matrix with the given offset.
  872. * this = T * this
  873. */
  874. void Translate( const Vec3 &t ) {
  875. data[12] = data[0] * t.x + data[4] * t.y + data[8] * t.z + data[12];
  876. data[13] = data[1] * t.x + data[5] * t.y + data[9] * t.z + data[13];
  877. data[14] = data[2] * t.x + data[6] * t.y + data[10] * t.z + data[14];
  878. data[15] = data[3] * t.x + data[7] * t.y + data[11] * t.z + data[15];
  879. }
  880. /**
  881. * Translate the matrix by x, y, z. This is the same as multiplying by a
  882. * translation matrix with the given offsets.
  883. */
  884. void Translate( float x, float y, float z ) {
  885. data[12] = data[0] * x + data[4] * y + data[8] * z + data[12];
  886. data[13] = data[1] * x + data[5] * y + data[9] * z + data[13];
  887. data[14] = data[2] * x + data[6] * y + data[10] * z + data[14];
  888. data[15] = data[3] * x + data[7] * y + data[11] * z + data[15];
  889. }
  890. /** Compute the transposed matrix. */
  891. void Transpose() {
  892. piSwap(data[1], data[4]);
  893. piSwap(data[2], data[8]);
  894. piSwap(data[6], data[9]);
  895. piSwap(data[3], data[12]);
  896. piSwap(data[7], data[13]);
  897. piSwap(data[11], data[14]);
  898. }
  899. /** Compute the inverse of a rigid-body/isometry/orthonormal matrix. */
  900. void IsometryInverse() {
  901. // transposed 3x3 upper left matrix
  902. piSwap(data[1], data[4]);
  903. piSwap(data[2], data[8]);
  904. piSwap(data[6], data[9]);
  905. // translate by the negative offsets
  906. Vec3 v(-data[12], -data[13], -data[14]);
  907. data[12] = data[13] = data[14] = 0;
  908. Translate(v);
  909. }
  910. /** Compute the inverse of the affine portion of this matrix. */
  911. void AffineInverse() {
  912. data[12] = data[13] = data[14] = 0;
  913. Transpose();
  914. }
  915. //@}
  916. /** @name Matrix operations: */
  917. //@{
  918. /** Return the determinant of this matrix. */
  919. float Determinant() const {
  920. return data[0] * data[5] * data[10] * data[15] +
  921. data[1] * data[6] * data[11] * data[12] +
  922. data[2] * data[7] * data[ 8] * data[13] +
  923. data[3] * data[4] * data[ 9] * data[14] -
  924. data[3] * data[6] * data[ 9] * data[12] -
  925. data[2] * data[5] * data[ 8] * data[15] -
  926. data[1] * data[4] * data[11] * data[14] -
  927. data[0] * data[7] * data[10] * data[12];
  928. }
  929. /** Standard matrix product: this *= B. */
  930. void Multiply4x4( const Matrix & restrict B ) {
  931. Multiply4x4(*this, B);
  932. }
  933. /** Standard matrix product: this = A * B. this != B*/
  934. void Multiply4x4( const Matrix & A, const Matrix & restrict B ) {
  935. piDebugCheck(this != &B);
  936. for(int i = 0; i < 4; i++) {
  937. const float ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3);
  938. GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
  939. GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
  940. GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
  941. GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
  942. }
  943. /* Unrolled but does not allow this == A
  944. data[0] = A.data[0] * B.data[0] + A.data[4] * B.data[1] + A.data[8] * B.data[2] + A.data[12] * B.data[3];
  945. data[1] = A.data[1] * B.data[0] + A.data[5] * B.data[1] + A.data[9] * B.data[2] + A.data[13] * B.data[3];
  946. data[2] = A.data[2] * B.data[0] + A.data[6] * B.data[1] + A.data[10] * B.data[2] + A.data[14] * B.data[3];
  947. data[3] = A.data[3] * B.data[0] + A.data[7] * B.data[1] + A.data[11] * B.data[2] + A.data[15] * B.data[3];
  948. data[4] = A.data[0] * B.data[4] + A.data[4] * B.data[5] + A.data[8] * B.data[6] + A.data[12] * B.data[7];
  949. data[5] = A.data[1] * B.data[4] + A.data[5] * B.data[5] + A.data[9] * B.data[6] + A.data[13] * B.data[7];
  950. data[6] = A.data[2] * B.data[4] + A.data[6] * B.data[5] + A.data[10] * B.data[6] + A.data[14] * B.data[7];
  951. data[7] = A.data[3] * B.data[4] + A.data[7] * B.data[5] + A.data[11] * B.data[6] + A.data[15] * B.data[7];
  952. data[8] = A.data[0] * B.data[8] + A.data[4] * B.data[9] + A.data[8] * B.data[10] + A.data[12] * B.data[11];
  953. data[9] = A.data[1] * B.data[8] + A.data[5] * B.data[9] + A.data[9] * B.data[10] + A.data[13] * B.data[11];
  954. data[10]= A.data[2] * B.data[8] + A.data[6] * B.data[9] + A.data[10] * B.data[10] + A.data[14] * B.data[11];
  955. data[11]= A.data[3] * B.data[8] + A.data[7] * B.data[9] + A.data[11] * B.data[10] + A.data[15] * B.data[11];
  956. data[12]= A.data[0] * B.data[12] + A.data[4] * B.data[13] + A.data[8] * B.data[14] + A.data[12] * B.data[15];
  957. data[13]= A.data[1] * B.data[12] + A.data[5] * B.data[13] + A.data[9] * B.data[14] + A.data[13] * B.data[15];
  958. data[14]= A.data[2] * B.data[12] + A.data[6] * B.data[13] + A.data[10] * B.data[14] + A.data[14] * B.data[15];
  959. data[15]= A.data[3] * B.data[12] + A.data[7] * B.data[13] + A.data[11] * B.data[14] + A.data[15] * B.data[15];
  960. */
  961. }
  962. /** Standard matrix product: this *= B. */
  963. void Multiply4x3( const Matrix & restrict B ) {
  964. Multiply4x3(*this, B);
  965. }
  966. /** Standard product of matrices, where the last row is [0 0 0 1]. */
  967. void Multiply4x3( const Matrix & A, const Matrix & restrict B ) {
  968. piDebugCheck(this != &B);
  969. for(int i = 0; i < 3; i++) {
  970. const float ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3);
  971. GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
  972. GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
  973. GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
  974. GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
  975. }
  976. data[3] = 0.0f; data[7] = 0.0f; data[11] = 0.0f; data[15] = 1.0f;
  977. /* Unrolled but does not allow this == A
  978. data[0] = a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] + a.data[12] * b.data[3];
  979. data[1] = a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] + a.data[13] * b.data[3];
  980. data[2] = a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] + a.data[14] * b.data[3];
  981. data[3] = 0.0f;
  982. data[4] = a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] + a.data[12] * b.data[7];
  983. data[5] = a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] + a.data[13] * b.data[7];
  984. data[6] = a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] + a.data[14] * b.data[7];
  985. data[7] = 0.0f;
  986. data[8] = a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] + a.data[12] * b.data[11];
  987. data[9] = a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] + a.data[13] * b.data[11];
  988. data[10]= a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] + a.data[14] * b.data[11];
  989. data[11]= 0.0f;
  990. data[12]= a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] + a.data[12] * b.data[15];
  991. data[13]= a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] + a.data[13] * b.data[15];
  992. data[14]= a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] + a.data[14] * b.data[15];
  993. data[15]= 1.0f;
  994. */
  995. }
  996. //@}
  997. /** @name Vector operations: */
  998. //@{
  999. /** Transform 3d vector (w=0). */
  1000. void TransformVec3(const Vec3 & restrict orig, Vec3 * restrict dest) const {
  1001. piDebugCheck(&orig != dest);
  1002. dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8];
  1003. dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9];
  1004. dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10];
  1005. }
  1006. /** Transform 3d vector by the transpose (w=0). */
  1007. void TransformVec3T(const Vec3 & restrict orig, Vec3 * restrict dest) const {
  1008. piDebugCheck(&orig != dest);
  1009. dest->x = orig.x * data[0] + orig.y * data[1] + orig.z * data[2];
  1010. dest->y = orig.x * data[4] + orig.y * data[5] + orig.z * data[6];
  1011. dest->z = orig.x * data[8] + orig.y * data[9] + orig.z * data[10];
  1012. }
  1013. /** Transform a 3d homogeneous vector, where the fourth coordinate is assumed to be 1. */
  1014. void TransformPoint(const Vec3 & restrict orig, Vec3 * restrict dest) const {
  1015. piDebugCheck(&orig != dest);
  1016. dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
  1017. dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
  1018. dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
  1019. }
  1020. /** Transform a point, normalize it, and return w. */
  1021. float TransformPointAndNormalize(const Vec3 & restrict orig, Vec3 * restrict dest) const {
  1022. piDebugCheck(&orig != dest);
  1023. float w;
  1024. dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
  1025. dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
  1026. dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
  1027. w = 1 / (orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]);
  1028. *dest *= w;
  1029. return w;
  1030. }
  1031. /** Transform a point and return w. */
  1032. float TransformPointReturnW(const Vec3 & restrict orig, Vec3 * restrict dest) const {
  1033. piDebugCheck(&orig != dest);
  1034. dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
  1035. dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
  1036. dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
  1037. return orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15];
  1038. }
  1039. /** Transform a normalized 3d point by a 4d matrix and return the resulting 4d vector. */
  1040. void TransformVec4(const Vec3 & orig, Vec4 * dest) const {
  1041. dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
  1042. dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
  1043. dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
  1044. dest->w = orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15];
  1045. }
  1046. //@}
  1047. /** @name Matrix analysis. */
  1048. //@{
  1049. /** Get the ZYZ euler angles from the matrix. Assumes the matrix is orthonormal. */
  1050. void GetEulerAnglesZYZ(float * s, float * t, float * r) const {
  1051. if( GetElem(2,2) < 1.0f ) {
  1052. if( GetElem(2,2) > -1.0f ) {
  1053. // cs*ct*cr-ss*sr -ss*ct*cr-cs*sr st*cr
  1054. // cs*ct*sr+ss*cr -ss*ct*sr+cs*cr st*sr
  1055. // -cs*st ss*st ct
  1056. *s = atan2(GetElem(1,2), -GetElem(0,2));
  1057. *t = acos(GetElem(2,2));
  1058. *r = atan2(GetElem(2,1), GetElem(2,0));
  1059. }
  1060. else {
  1061. // -c(s-r) s(s-r) 0
  1062. // s(s-r) c(s-r) 0
  1063. // 0 0 -1
  1064. *s = atan2(GetElem(0, 1), -GetElem(0, 0)); // = s-r
  1065. *t = PI;
  1066. *r = 0;
  1067. }
  1068. }
  1069. else {
  1070. // c(s+r) -s(s+r) 0
  1071. // s(s+r) c(s+r) 0
  1072. // 0 0 1
  1073. *s = atan2(GetElem(0, 1), GetElem(0, 0)); // = s+r
  1074. *t = 0;
  1075. *r = 0;
  1076. }
  1077. }
  1078. //@}
  1079. MATHLIB_API friend PiStream & operator<< ( PiStream & s, Matrix & m );
  1080. /** Print to debug output. */
  1081. void Print() const {
  1082. piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[0], data[4], data[8], data[12] );
  1083. piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[1], data[5], data[9], data[13] );
  1084. piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[2], data[6], data[10], data[14] );
  1085. piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[3], data[7], data[11], data[15] );
  1086. }
  1087. public:
  1088. float data[16];
  1089. };
  1090. #endif
  1091. #endif // NV_MATH_MATRIX_INL