/src/away3d/core/math/Matrix3DUtils.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 367 lines · 292 code · 41 blank · 34 comment · 25 complexity · a77b9aabe8ed50ddc2dc95bb9d8d7441 MD5 · raw file

  1. package away3d.core.math {
  2. import flash.geom.*;
  3. /**
  4. * Matrix3DUtils provides additional Matrix3D math functions.
  5. */
  6. public class Matrix3DUtils {
  7. /**
  8. * A reference to a Vector to be used as a temporary raw data container, to prevent object creation.
  9. */
  10. public static const RAW_DATA_CONTAINER:Vector.<Number> = new Vector.<Number>(16);
  11. public static const CALCULATION_MATRIX:Matrix3D = new Matrix3D();
  12. public static const CALCULATION_VECTOR3D:Vector3D = new Vector3D();
  13. public static const CALCULATION_DECOMPOSE:Vector.<Vector3D> = Vector.<Vector3D>([new Vector3D(), new Vector3D(), new Vector3D()]);
  14. /**
  15. * Fills the 3d matrix object with values representing the transformation made by the given quaternion.
  16. *
  17. * @param quarternion The quarterion object to convert.
  18. */
  19. public static function quaternion2matrix(quarternion:Quaternion, m:Matrix3D = null):Matrix3D {
  20. var x:Number = quarternion.x;
  21. var y:Number = quarternion.y;
  22. var z:Number = quarternion.z;
  23. var w:Number = quarternion.w;
  24. var xx:Number = x * x;
  25. var xy:Number = x * y;
  26. var xz:Number = x * z;
  27. var xw:Number = x * w;
  28. var yy:Number = y * y;
  29. var yz:Number = y * z;
  30. var yw:Number = y * w;
  31. var zz:Number = z * z;
  32. var zw:Number = z * w;
  33. var raw:Vector.<Number> = RAW_DATA_CONTAINER;
  34. raw[0] = 1 - 2 * (yy + zz);
  35. raw[1] = 2 * (xy + zw);
  36. raw[2] = 2 * (xz - yw);
  37. raw[4] = 2 * (xy - zw);
  38. raw[5] = 1 - 2 * (xx + zz);
  39. raw[6] = 2 * (yz + xw);
  40. raw[8] = 2 * (xz + yw);
  41. raw[9] = 2 * (yz - xw);
  42. raw[10] = 1 - 2 * (xx + yy);
  43. raw[3] = raw[7] = raw[11] = raw[12] = raw[13] = raw[14] = 0;
  44. raw[15] = 1;
  45. if (m) {
  46. m.copyRawDataFrom(raw);
  47. return m;
  48. } else
  49. return new Matrix3D(raw);
  50. }
  51. /**
  52. * Returns a normalised <code>Vector3D</code> object representing the forward vector of the given matrix.
  53. * @param m The Matrix3D object to use to get the forward vector
  54. * @param v [optional] A vector holder to prevent make new Vector3D instance if already exists. Default is null.
  55. * @return The forward vector
  56. */
  57. public static function getForward(m:Matrix3D, v:Vector3D = null):Vector3D {
  58. if(!v) v = new Vector3D();
  59. m.copyColumnTo(2, v);
  60. v.normalize();
  61. return v;
  62. }
  63. /**
  64. * Returns a normalised <code>Vector3D</code> object representing the up vector of the given matrix.
  65. * @param m The Matrix3D object to use to get the up vector
  66. * @param v [optional] A vector holder to prevent make new Vector3D instance if already exists. Default is null.
  67. * @return The up vector
  68. */
  69. public static function getUp(m:Matrix3D, v:Vector3D = null):Vector3D {
  70. if(!v) v = new Vector3D();
  71. m.copyColumnTo(1, v);
  72. v.normalize();
  73. return v;
  74. }
  75. /**
  76. * Returns a normalised <code>Vector3D</code> object representing the right vector of the given matrix.
  77. * @param m The Matrix3D object to use to get the right vector
  78. * @param v [optional] A vector holder to prevent make new Vector3D instance if already exists. Default is null.
  79. * @return The right vector
  80. */
  81. public static function getRight(m:Matrix3D, v:Vector3D = null):Vector3D {
  82. if(!v) v = new Vector3D();
  83. m.copyColumnTo(0, v);
  84. v.normalize();
  85. return v;
  86. }
  87. /**
  88. * Returns a boolean value representing whether there is any significant difference between the two given 3d matrices.
  89. */
  90. public static function compare(m1:Matrix3D, m2:Matrix3D):Boolean {
  91. var r1:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
  92. var r2:Vector.<Number> = m2.rawData;
  93. m1.copyRawDataTo(r1);
  94. for (var i:uint = 0; i < 16; ++i) {
  95. if (r1[i] != r2[i])
  96. return false;
  97. }
  98. return true;
  99. }
  100. public static function lookAt(matrix:Matrix3D, pos:Vector3D, dir:Vector3D, up:Vector3D):void {
  101. var dirN:Vector3D;
  102. var upN:Vector3D;
  103. var lftN:Vector3D;
  104. var raw:Vector.<Number> = RAW_DATA_CONTAINER;
  105. lftN = dir.crossProduct(up);
  106. lftN.normalize();
  107. upN = lftN.crossProduct(dir);
  108. upN.normalize();
  109. dirN = dir.clone();
  110. dirN.normalize();
  111. raw[0] = lftN.x;
  112. raw[1] = upN.x;
  113. raw[2] = -dirN.x;
  114. raw[3] = 0.0;
  115. raw[4] = lftN.y;
  116. raw[5] = upN.y;
  117. raw[6] = -dirN.y;
  118. raw[7] = 0.0;
  119. raw[8] = lftN.z;
  120. raw[9] = upN.z;
  121. raw[10] = -dirN.z;
  122. raw[11] = 0.0;
  123. raw[12] = -lftN.dotProduct(pos);
  124. raw[13] = -upN.dotProduct(pos);
  125. raw[14] = dirN.dotProduct(pos);
  126. raw[15] = 1.0;
  127. matrix.copyRawDataFrom(raw);
  128. }
  129. public static function reflection(plane:Plane3D, target:Matrix3D = null):Matrix3D {
  130. target ||= new Matrix3D();
  131. var a:Number = plane.a, b:Number = plane.b, c:Number = plane.c, d:Number = plane.d;
  132. var rawData:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
  133. var ab2:Number = -2 * a * b;
  134. var ac2:Number = -2 * a * c;
  135. var bc2:Number = -2 * b * c;
  136. // reflection matrix
  137. rawData[0] = 1 - 2 * a * a;
  138. rawData[4] = ab2;
  139. rawData[8] = ac2;
  140. rawData[12] = -2 * a * d;
  141. rawData[1] = ab2;
  142. rawData[5] = 1 - 2 * b * b;
  143. rawData[9] = bc2;
  144. rawData[13] = -2 * b * d;
  145. rawData[2] = ac2;
  146. rawData[6] = bc2;
  147. rawData[10] = 1 - 2 * c * c;
  148. rawData[14] = -2 * c * d;
  149. rawData[3] = 0;
  150. rawData[7] = 0;
  151. rawData[11] = 0;
  152. rawData[15] = 1;
  153. target.copyRawDataFrom(rawData);
  154. return target;
  155. }
  156. public static function decompose(sourceMatrix:Matrix3D, orientationStyle:String = "eulerAngles"):Vector.<Vector3D> {
  157. var raw:Vector.<Number> = RAW_DATA_CONTAINER;
  158. sourceMatrix.copyRawDataTo(raw);
  159. var a:Number = raw[0];
  160. var e:Number = raw[1];
  161. var i:Number = raw[2];
  162. var b:Number = raw[4];
  163. var f:Number = raw[5];
  164. var j:Number = raw[6];
  165. var c:Number = raw[8];
  166. var g:Number = raw[9];
  167. var k:Number = raw[10];
  168. var x:Number = raw[12];
  169. var y:Number = raw[13];
  170. var z:Number = raw[14];
  171. var tx:Number = Math.sqrt(a * a + e * e + i * i);
  172. var ty:Number = Math.sqrt(b * b + f * f + j * j);
  173. var tz:Number = Math.sqrt(c * c + g * g + k * k);
  174. var tw:Number = 0;
  175. var scaleX:Number = tx;
  176. var scaleY:Number = ty;
  177. var scaleZ:Number = tz;
  178. if (a*(f*k - j*g) - e*(b*k - j*c) + i*(b*g - f*c) < 0) {
  179. scaleZ = -scaleZ;
  180. }
  181. a = a / scaleX;
  182. e = e / scaleX;
  183. i = i / scaleX;
  184. b = b / scaleY;
  185. f = f / scaleY;
  186. j = j / scaleY;
  187. c = c / scaleZ;
  188. g = g / scaleZ;
  189. k = k / scaleZ;
  190. //from away3d-ts
  191. if (orientationStyle == Orientation3D.EULER_ANGLES) {
  192. tx = Math.atan2(j, k);
  193. ty = Math.atan2(-i, Math.sqrt(a * a + e * e));
  194. var s1:Number = Math.sin(tx);
  195. var c1:Number = Math.cos(tx);
  196. tz = Math.atan2(s1*c-c1*b, c1*f - s1*g);
  197. } else if (orientationStyle == Orientation3D.AXIS_ANGLE) {
  198. tw = Math.acos((a + f + k - 1) / 2);
  199. var len:Number = Math.sqrt((j - g) * (j - g) + (c - i) * (c - i) + (e - b) * (e - b));
  200. tx = (j - g) / len;
  201. ty = (c - i) / len;
  202. tz = (e - b) / len;
  203. } else {//Orientation3D.QUATERNION
  204. var tr:Number = a + f + k;
  205. if (tr > 0) {
  206. tw = Math.sqrt(1 + tr) / 2;
  207. tx = (j - g) / (4 * tw);
  208. ty = (c - i) / (4 * tw);
  209. tz = (e - b) / (4 * tw);
  210. } else if ((a > f) && (a > k)) {
  211. tx = Math.sqrt(1 + a - f - k) / 2;
  212. tw = (j - g) / (4 * tx);
  213. ty = (e + b) / (4 * tx);
  214. tz = (c + i) / (4 * tx);
  215. } else if (f > k) {
  216. ty = Math.sqrt(1 + f - a - k) / 2;
  217. tx = (e + b) / (4 * ty);
  218. tw = (c - i) / (4 * ty);
  219. tz = (j + g) / (4 * ty);
  220. } else {
  221. tz = Math.sqrt(1 + k - a - f) / 2;
  222. tx = (c + i) / (4 * tz);
  223. ty = (j + g) / (4 * tz);
  224. tw = (e - b) / (4 * tz);
  225. }
  226. }
  227. var v:Vector.<Vector3D> = CALCULATION_DECOMPOSE;
  228. v[0].x = x;
  229. v[0].y = y;
  230. v[0].z = z;
  231. v[1].x = tx;
  232. v[1].y = ty;
  233. v[1].z = tz;
  234. v[1].w = tw;
  235. v[2].x = scaleX;
  236. v[2].y = scaleY;
  237. v[2].z = scaleZ;
  238. return v;
  239. }
  240. public static function transformVector(matrix:Matrix3D, vector:Vector3D, result:Vector3D = null):Vector3D {
  241. if (!result) result = new Vector3D();
  242. var raw:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
  243. matrix.copyRawDataTo(raw);
  244. var a:Number = raw[0];
  245. var e:Number = raw[1];
  246. var i:Number = raw[2];
  247. var m:Number = raw[3];
  248. var b:Number = raw[4];
  249. var f:Number = raw[5];
  250. var j:Number = raw[6];
  251. var n:Number = raw[7];
  252. var c:Number = raw[8];
  253. var g:Number = raw[9];
  254. var k:Number = raw[10];
  255. var o:Number = raw[11];
  256. var d:Number = raw[12];
  257. var h:Number = raw[13];
  258. var l:Number = raw[14];
  259. var p:Number = raw[15];
  260. var x:Number = vector.x;
  261. var y:Number = vector.y;
  262. var z:Number = vector.z;
  263. result.x = a * x + b * y + c * z + d;
  264. result.y = e * x + f * y + g * z + h;
  265. result.z = i * x + j * y + k * z + l;
  266. result.w = m * x + n * y + o * z + p;
  267. return result;
  268. }
  269. public static function deltaTransformVector(matrix:Matrix3D, vector:Vector3D, result:Vector3D = null):Vector3D {
  270. if (!result) result = new Vector3D();
  271. var raw:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
  272. matrix.copyRawDataTo(raw);
  273. var a:Number = raw[0];
  274. var e:Number = raw[1];
  275. var i:Number = raw[2];
  276. var m:Number = raw[3];
  277. var b:Number = raw[4];
  278. var f:Number = raw[5];
  279. var j:Number = raw[6];
  280. var n:Number = raw[7];
  281. var c:Number = raw[8];
  282. var g:Number = raw[9];
  283. var k:Number = raw[10];
  284. var o:Number = raw[11];
  285. var x:Number = vector.x;
  286. var y:Number = vector.y;
  287. var z:Number = vector.z;
  288. result.x = a * x + b * y + c * z;
  289. result.y = e * x + f * y + g * z;
  290. result.z = i * x + j * y + k * z;
  291. result.w = m * x + n * y + o * z;
  292. return result;
  293. }
  294. public static function getTranslation(transform:Matrix3D, result:Vector3D = null):Vector3D {
  295. if(!result) result = new Vector3D();
  296. transform.copyColumnTo(3, result);
  297. return result;
  298. }
  299. public static function deltaTransformVectors(matrix:Matrix3D, vin:Vector.<Number>, vout:Vector.<Number>):void {
  300. var raw:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
  301. matrix.copyRawDataTo(raw);
  302. var a:Number = raw[0];
  303. var e:Number = raw[1];
  304. var i:Number = raw[2];
  305. var m:Number = raw[3];
  306. var b:Number = raw[4];
  307. var f:Number = raw[5];
  308. var j:Number = raw[6];
  309. var n:Number = raw[7];
  310. var c:Number = raw[8];
  311. var g:Number = raw[9];
  312. var k:Number = raw[10];
  313. var o:Number = raw[11];
  314. var outIndex:uint = 0;
  315. var length:Number = vin.length;
  316. for(var index:uint = 0; index<length; index+=3) {
  317. var x:Number = vin[index];
  318. var y:Number = vin[index+1];
  319. var z:Number = vin[index+2];
  320. vout[outIndex++] = a * x + b * y + c * z;
  321. vout[outIndex++] = e * x + f * y + g * z;
  322. vout[outIndex++] = i * x + j * y + k * z;
  323. }
  324. }
  325. }
  326. }