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