Matrix3.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /**
  2. * @author bhouston / http://exocortex.com
  3. */
  4. QUnit.module( "Matrix3" );
  5. var matrixEquals3 = function( a, b, tolerance ) {
  6. tolerance = tolerance || 0.0001;
  7. if( a.elements.length != b.elements.length ) {
  8. return false;
  9. }
  10. for( var i = 0, il = a.elements.length; i < il; i ++ ) {
  11. var delta = a.elements[i] - b.elements[i];
  12. if( delta > tolerance ) {
  13. return false;
  14. }
  15. }
  16. return true;
  17. };
  18. var toMatrix4 = function( m3 ) {
  19. var result = new THREE.Matrix4();
  20. var re = result.elements;
  21. var me = m3.elements;
  22. re[0] = me[0];
  23. re[1] = me[1];
  24. re[2] = me[2];
  25. re[4] = me[3];
  26. re[5] = me[4];
  27. re[6] = me[5];
  28. re[8] = me[6];
  29. re[9] = me[7];
  30. re[10] = me[8];
  31. return result;
  32. };
  33. QUnit.test( "constructor" , function( assert ) {
  34. var a = new THREE.Matrix3();
  35. assert.ok( a.determinant() == 1, "Passed!" );
  36. var b = new THREE.Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
  37. assert.ok( b.elements[0] == 0 );
  38. assert.ok( b.elements[1] == 3 );
  39. assert.ok( b.elements[2] == 6 );
  40. assert.ok( b.elements[3] == 1 );
  41. assert.ok( b.elements[4] == 4 );
  42. assert.ok( b.elements[5] == 7 );
  43. assert.ok( b.elements[6] == 2 );
  44. assert.ok( b.elements[7] == 5 );
  45. assert.ok( b.elements[8] == 8 );
  46. assert.ok( ! matrixEquals3( a, b ), "Passed!" );
  47. });
  48. QUnit.test( "copy" , function( assert ) {
  49. var a = new THREE.Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
  50. var b = new THREE.Matrix3().copy( a );
  51. assert.ok( matrixEquals3( a, b ), "Passed!" );
  52. // ensure that it is a true copy
  53. a.elements[0] = 2;
  54. assert.ok( ! matrixEquals3( a, b ), "Passed!" );
  55. });
  56. QUnit.test( "set" , function( assert ) {
  57. var b = new THREE.Matrix3();
  58. assert.ok( b.determinant() == 1, "Passed!" );
  59. b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
  60. assert.ok( b.elements[0] == 0 );
  61. assert.ok( b.elements[1] == 3 );
  62. assert.ok( b.elements[2] == 6 );
  63. assert.ok( b.elements[3] == 1 );
  64. assert.ok( b.elements[4] == 4 );
  65. assert.ok( b.elements[5] == 7 );
  66. assert.ok( b.elements[6] == 2 );
  67. assert.ok( b.elements[7] == 5 );
  68. assert.ok( b.elements[8] == 8 );
  69. });
  70. QUnit.test( "identity" , function( assert ) {
  71. var b = new THREE.Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
  72. assert.ok( b.elements[0] == 0 );
  73. assert.ok( b.elements[1] == 3 );
  74. assert.ok( b.elements[2] == 6 );
  75. assert.ok( b.elements[3] == 1 );
  76. assert.ok( b.elements[4] == 4 );
  77. assert.ok( b.elements[5] == 7 );
  78. assert.ok( b.elements[6] == 2 );
  79. assert.ok( b.elements[7] == 5 );
  80. assert.ok( b.elements[8] == 8 );
  81. var a = new THREE.Matrix3();
  82. assert.ok( ! matrixEquals3( a, b ), "Passed!" );
  83. b.identity();
  84. assert.ok( matrixEquals3( a, b ), "Passed!" );
  85. });
  86. QUnit.test( "multiplyMatrices" , function ( assert ) {
  87. // Reference:
  88. //
  89. // #!/usr/bin/env python
  90. // from __future__ import print_function
  91. // import numpy as np
  92. // print(
  93. // np.dot(
  94. // np.reshape([2, 3, 5, 7, 11, 13, 17, 19, 23], (3, 3)),
  95. // np.reshape([29, 31, 37, 41, 43, 47, 53, 59, 61], (3, 3))
  96. // )
  97. // )
  98. //
  99. // [[ 446 486 520]
  100. // [1343 1457 1569]
  101. // [2491 2701 2925]]
  102. var lhs = new THREE.Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 );
  103. var rhs = new THREE.Matrix3().set( 29, 31, 37, 41, 43, 47, 53, 59, 61 );
  104. var ans = new THREE.Matrix3();
  105. ans.multiplyMatrices(lhs, rhs);
  106. assert.ok( ans.elements[0] == 446 );
  107. assert.ok( ans.elements[1] == 1343 );
  108. assert.ok( ans.elements[2] == 2491 );
  109. assert.ok( ans.elements[3] == 486 );
  110. assert.ok( ans.elements[4] == 1457 );
  111. assert.ok( ans.elements[5] == 2701 );
  112. assert.ok( ans.elements[6] == 520 );
  113. assert.ok( ans.elements[7] == 1569 );
  114. assert.ok( ans.elements[8] == 2925 );
  115. });
  116. QUnit.test( "multiplyScalar" , function( assert ) {
  117. var b = new THREE.Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
  118. assert.ok( b.elements[0] == 0 );
  119. assert.ok( b.elements[1] == 3 );
  120. assert.ok( b.elements[2] == 6 );
  121. assert.ok( b.elements[3] == 1 );
  122. assert.ok( b.elements[4] == 4 );
  123. assert.ok( b.elements[5] == 7 );
  124. assert.ok( b.elements[6] == 2 );
  125. assert.ok( b.elements[7] == 5 );
  126. assert.ok( b.elements[8] == 8 );
  127. b.multiplyScalar( 2 );
  128. assert.ok( b.elements[0] == 0*2 );
  129. assert.ok( b.elements[1] == 3*2 );
  130. assert.ok( b.elements[2] == 6*2 );
  131. assert.ok( b.elements[3] == 1*2 );
  132. assert.ok( b.elements[4] == 4*2 );
  133. assert.ok( b.elements[5] == 7*2 );
  134. assert.ok( b.elements[6] == 2*2 );
  135. assert.ok( b.elements[7] == 5*2 );
  136. assert.ok( b.elements[8] == 8*2 );
  137. });
  138. QUnit.test( "determinant" , function( assert ) {
  139. var a = new THREE.Matrix3();
  140. assert.ok( a.determinant() == 1, "Passed!" );
  141. a.elements[0] = 2;
  142. assert.ok( a.determinant() == 2, "Passed!" );
  143. a.elements[0] = 0;
  144. assert.ok( a.determinant() == 0, "Passed!" );
  145. // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/threeD/index.htm
  146. a.set( 2, 3, 4, 5, 13, 7, 8, 9, 11 );
  147. assert.ok( a.determinant() == -73, "Passed!" );
  148. });
  149. QUnit.test( "getInverse" , function( assert ) {
  150. var identity = new THREE.Matrix3();
  151. var identity4 = new THREE.Matrix4();
  152. var a = new THREE.Matrix3();
  153. var b = new THREE.Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
  154. var c = new THREE.Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
  155. b.getInverse( a, false );
  156. assert.ok( matrixEquals3( a, identity ), "Passed!" );
  157. try {
  158. b.getInverse( c, true );
  159. assert.ok( false, "Passed!" ); // should never get here.
  160. }
  161. catch( err ) {
  162. assert.ok( true, "Passed!" );
  163. }
  164. var testMatrices = [
  165. new THREE.Matrix4().makeRotationX( 0.3 ),
  166. new THREE.Matrix4().makeRotationX( -0.3 ),
  167. new THREE.Matrix4().makeRotationY( 0.3 ),
  168. new THREE.Matrix4().makeRotationY( -0.3 ),
  169. new THREE.Matrix4().makeRotationZ( 0.3 ),
  170. new THREE.Matrix4().makeRotationZ( -0.3 ),
  171. new THREE.Matrix4().makeScale( 1, 2, 3 ),
  172. new THREE.Matrix4().makeScale( 1/8, 1/2, 1/3 )
  173. ];
  174. for( var i = 0, il = testMatrices.length; i < il; i ++ ) {
  175. var m = testMatrices[i];
  176. a.setFromMatrix4( m );
  177. var mInverse3 = b.getInverse( a );
  178. var mInverse = toMatrix4( mInverse3 );
  179. // the determinant of the inverse should be the reciprocal
  180. assert.ok( Math.abs( a.determinant() * mInverse3.determinant() - 1 ) < 0.0001, "Passed!" );
  181. assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" );
  182. var mProduct = new THREE.Matrix4().multiplyMatrices( m, mInverse );
  183. assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" );
  184. assert.ok( matrixEquals3( mProduct, identity4 ), "Passed!" );
  185. }
  186. });
  187. QUnit.test( "transpose" , function( assert ) {
  188. var a = new THREE.Matrix3();
  189. var b = a.clone().transpose();
  190. assert.ok( matrixEquals3( a, b ), "Passed!" );
  191. b = new THREE.Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
  192. var c = b.clone().transpose();
  193. assert.ok( ! matrixEquals3( b, c ), "Passed!" );
  194. c.transpose();
  195. assert.ok( matrixEquals3( b, c ), "Passed!" );
  196. });
  197. QUnit.test( "clone" , function( assert ) {
  198. var a = new THREE.Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
  199. var b = a.clone();
  200. assert.ok( matrixEquals3( a, b ), "Passed!" );
  201. // ensure that it is a true copy
  202. a.elements[0] = 2;
  203. assert.ok( ! matrixEquals3( a, b ), "Passed!" );
  204. });