1/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 2 3Redistribution and use in source and binary forms, with or without modification, 4are permitted provided that the following conditions are met: 5 6 * Redistributions of source code must retain the above copyright notice, this 7 list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright notice, 9 this list of conditions and the following disclaimer in the documentation 10 and/or other materials provided with the distribution. 11 12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 22 23/** 24 * @class 3x3 Matrix 25 * @name mat3 26 */ 27var mat3 = {}; 28 29/** 30 * Creates a new identity mat3 31 * 32 * @returns {mat3} a new 3x3 matrix 33 */ 34mat3.create = function() { 35 var out = new GLMAT_ARRAY_TYPE(9); 36 out[0] = 1; 37 out[1] = 0; 38 out[2] = 0; 39 out[3] = 0; 40 out[4] = 1; 41 out[5] = 0; 42 out[6] = 0; 43 out[7] = 0; 44 out[8] = 1; 45 return out; 46}; 47 48/** 49 * Copies the upper-left 3x3 values into the given mat3. 50 * 51 * @param {mat3} out the receiving 3x3 matrix 52 * @param {mat4} a the source 4x4 matrix 53 * @returns {mat3} out 54 */ 55mat3.fromMat4 = function(out, a) { 56 out[0] = a[0]; 57 out[1] = a[1]; 58 out[2] = a[2]; 59 out[3] = a[4]; 60 out[4] = a[5]; 61 out[5] = a[6]; 62 out[6] = a[8]; 63 out[7] = a[9]; 64 out[8] = a[10]; 65 return out; 66}; 67 68/** 69 * Creates a new mat3 initialized with values from an existing matrix 70 * 71 * @param {mat3} a matrix to clone 72 * @returns {mat3} a new 3x3 matrix 73 */ 74mat3.clone = function(a) { 75 var out = new GLMAT_ARRAY_TYPE(9); 76 out[0] = a[0]; 77 out[1] = a[1]; 78 out[2] = a[2]; 79 out[3] = a[3]; 80 out[4] = a[4]; 81 out[5] = a[5]; 82 out[6] = a[6]; 83 out[7] = a[7]; 84 out[8] = a[8]; 85 return out; 86}; 87 88/** 89 * Copy the values from one mat3 to another 90 * 91 * @param {mat3} out the receiving matrix 92 * @param {mat3} a the source matrix 93 * @returns {mat3} out 94 */ 95mat3.copy = function(out, a) { 96 out[0] = a[0]; 97 out[1] = a[1]; 98 out[2] = a[2]; 99 out[3] = a[3]; 100 out[4] = a[4]; 101 out[5] = a[5]; 102 out[6] = a[6]; 103 out[7] = a[7]; 104 out[8] = a[8]; 105 return out; 106}; 107 108/** 109 * Set a mat3 to the identity matrix 110 * 111 * @param {mat3} out the receiving matrix 112 * @returns {mat3} out 113 */ 114mat3.identity = function(out) { 115 out[0] = 1; 116 out[1] = 0; 117 out[2] = 0; 118 out[3] = 0; 119 out[4] = 1; 120 out[5] = 0; 121 out[6] = 0; 122 out[7] = 0; 123 out[8] = 1; 124 return out; 125}; 126 127/** 128 * Transpose the values of a mat3 129 * 130 * @param {mat3} out the receiving matrix 131 * @param {mat3} a the source matrix 132 * @returns {mat3} out 133 */ 134mat3.transpose = function(out, a) { 135 // If we are transposing ourselves we can skip a few steps but have to cache some values 136 if (out === a) { 137 var a01 = a[1], a02 = a[2], a12 = a[5]; 138 out[1] = a[3]; 139 out[2] = a[6]; 140 out[3] = a01; 141 out[5] = a[7]; 142 out[6] = a02; 143 out[7] = a12; 144 } else { 145 out[0] = a[0]; 146 out[1] = a[3]; 147 out[2] = a[6]; 148 out[3] = a[1]; 149 out[4] = a[4]; 150 out[5] = a[7]; 151 out[6] = a[2]; 152 out[7] = a[5]; 153 out[8] = a[8]; 154 } 155 156 return out; 157}; 158 159/** 160 * Inverts a mat3 161 * 162 * @param {mat3} out the receiving matrix 163 * @param {mat3} a the source matrix 164 * @returns {mat3} out 165 */ 166mat3.invert = function(out, a) { 167 var a00 = a[0], a01 = a[1], a02 = a[2], 168 a10 = a[3], a11 = a[4], a12 = a[5], 169 a20 = a[6], a21 = a[7], a22 = a[8], 170 171 b01 = a22 * a11 - a12 * a21, 172 b11 = -a22 * a10 + a12 * a20, 173 b21 = a21 * a10 - a11 * a20, 174 175 // Calculate the determinant 176 det = a00 * b01 + a01 * b11 + a02 * b21; 177 178 if (!det) { 179 return null; 180 } 181 det = 1.0 / det; 182 183 out[0] = b01 * det; 184 out[1] = (-a22 * a01 + a02 * a21) * det; 185 out[2] = (a12 * a01 - a02 * a11) * det; 186 out[3] = b11 * det; 187 out[4] = (a22 * a00 - a02 * a20) * det; 188 out[5] = (-a12 * a00 + a02 * a10) * det; 189 out[6] = b21 * det; 190 out[7] = (-a21 * a00 + a01 * a20) * det; 191 out[8] = (a11 * a00 - a01 * a10) * det; 192 return out; 193}; 194 195/** 196 * Calculates the adjugate of a mat3 197 * 198 * @param {mat3} out the receiving matrix 199 * @param {mat3} a the source matrix 200 * @returns {mat3} out 201 */ 202mat3.adjoint = function(out, a) { 203 var a00 = a[0], a01 = a[1], a02 = a[2], 204 a10 = a[3], a11 = a[4], a12 = a[5], 205 a20 = a[6], a21 = a[7], a22 = a[8]; 206 207 out[0] = (a11 * a22 - a12 * a21); 208 out[1] = (a02 * a21 - a01 * a22); 209 out[2] = (a01 * a12 - a02 * a11); 210 out[3] = (a12 * a20 - a10 * a22); 211 out[4] = (a00 * a22 - a02 * a20); 212 out[5] = (a02 * a10 - a00 * a12); 213 out[6] = (a10 * a21 - a11 * a20); 214 out[7] = (a01 * a20 - a00 * a21); 215 out[8] = (a00 * a11 - a01 * a10); 216 return out; 217}; 218 219/** 220 * Calculates the determinant of a mat3 221 * 222 * @param {mat3} a the source matrix 223 * @returns {Number} determinant of a 224 */ 225mat3.determinant = function (a) { 226 var a00 = a[0], a01 = a[1], a02 = a[2], 227 a10 = a[3], a11 = a[4], a12 = a[5], 228 a20 = a[6], a21 = a[7], a22 = a[8]; 229 230 return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); 231}; 232 233/** 234 * Multiplies two mat3's 235 * 236 * @param {mat3} out the receiving matrix 237 * @param {mat3} a the first operand 238 * @param {mat3} b the second operand 239 * @returns {mat3} out 240 */ 241mat3.multiply = function (out, a, b) { 242 var a00 = a[0], a01 = a[1], a02 = a[2], 243 a10 = a[3], a11 = a[4], a12 = a[5], 244 a20 = a[6], a21 = a[7], a22 = a[8], 245 246 b00 = b[0], b01 = b[1], b02 = b[2], 247 b10 = b[3], b11 = b[4], b12 = b[5], 248 b20 = b[6], b21 = b[7], b22 = b[8]; 249 250 out[0] = b00 * a00 + b01 * a10 + b02 * a20; 251 out[1] = b00 * a01 + b01 * a11 + b02 * a21; 252 out[2] = b00 * a02 + b01 * a12 + b02 * a22; 253 254 out[3] = b10 * a00 + b11 * a10 + b12 * a20; 255 out[4] = b10 * a01 + b11 * a11 + b12 * a21; 256 out[5] = b10 * a02 + b11 * a12 + b12 * a22; 257 258 out[6] = b20 * a00 + b21 * a10 + b22 * a20; 259 out[7] = b20 * a01 + b21 * a11 + b22 * a21; 260 out[8] = b20 * a02 + b21 * a12 + b22 * a22; 261 return out; 262}; 263 264/** 265 * Alias for {@link mat3.multiply} 266 * @function 267 */ 268mat3.mul = mat3.multiply; 269 270/** 271 * Translate a mat3 by the given vector 272 * 273 * @param {mat3} out the receiving matrix 274 * @param {mat3} a the matrix to translate 275 * @param {vec2} v vector to translate by 276 * @returns {mat3} out 277 */ 278mat3.translate = function(out, a, v) { 279 var a00 = a[0], a01 = a[1], a02 = a[2], 280 a10 = a[3], a11 = a[4], a12 = a[5], 281 a20 = a[6], a21 = a[7], a22 = a[8], 282 x = v[0], y = v[1]; 283 284 out[0] = a00; 285 out[1] = a01; 286 out[2] = a02; 287 288 out[3] = a10; 289 out[4] = a11; 290 out[5] = a12; 291 292 out[6] = x * a00 + y * a10 + a20; 293 out[7] = x * a01 + y * a11 + a21; 294 out[8] = x * a02 + y * a12 + a22; 295 return out; 296}; 297 298/** 299 * Rotates a mat3 by the given angle 300 * 301 * @param {mat3} out the receiving matrix 302 * @param {mat3} a the matrix to rotate 303 * @param {Number} rad the angle to rotate the matrix by 304 * @returns {mat3} out 305 */ 306mat3.rotate = function (out, a, rad) { 307 var a00 = a[0], a01 = a[1], a02 = a[2], 308 a10 = a[3], a11 = a[4], a12 = a[5], 309 a20 = a[6], a21 = a[7], a22 = a[8], 310 311 s = Math.sin(rad), 312 c = Math.cos(rad); 313 314 out[0] = c * a00 + s * a10; 315 out[1] = c * a01 + s * a11; 316 out[2] = c * a02 + s * a12; 317 318 out[3] = c * a10 - s * a00; 319 out[4] = c * a11 - s * a01; 320 out[5] = c * a12 - s * a02; 321 322 out[6] = a20; 323 out[7] = a21; 324 out[8] = a22; 325 return out; 326}; 327 328/** 329 * Scales the mat3 by the dimensions in the given vec2 330 * 331 * @param {mat3} out the receiving matrix 332 * @param {mat3} a the matrix to rotate 333 * @param {vec2} v the vec2 to scale the matrix by 334 * @returns {mat3} out 335 **/ 336mat3.scale = function(out, a, v) { 337 var x = v[0], y = v[2]; 338 339 out[0] = x * a[0]; 340 out[1] = x * a[1]; 341 out[2] = x * a[2]; 342 343 out[3] = y * a[3]; 344 out[4] = y * a[4]; 345 out[5] = y * a[5]; 346 347 out[6] = a[6]; 348 out[7] = a[7]; 349 out[8] = a[8]; 350 return out; 351}; 352 353/** 354 * Copies the values from a mat2d into a mat3 355 * 356 * @param {mat3} out the receiving matrix 357 * @param {mat3} a the matrix to rotate 358 * @param {vec2} v the vec2 to scale the matrix by 359 * @returns {mat3} out 360 **/ 361mat3.fromMat2d = function(out, a) { 362 out[0] = a[0]; 363 out[1] = a[1]; 364 out[2] = 0; 365 366 out[3] = a[2]; 367 out[4] = a[3]; 368 out[5] = 0; 369 370 out[6] = a[4]; 371 out[7] = a[5]; 372 out[8] = 1; 373 return out; 374}; 375 376/** 377* Calculates a 3x3 matrix from the given quaternion 378* 379* @param {mat3} out mat3 receiving operation result 380* @param {quat} q Quaternion to create matrix from 381* 382* @returns {mat3} out 383*/ 384mat3.fromQuat = function (out, q) { 385 var x = q[0], y = q[1], z = q[2], w = q[3], 386 x2 = x + x, 387 y2 = y + y, 388 z2 = z + z, 389 390 xx = x * x2, 391 xy = x * y2, 392 xz = x * z2, 393 yy = y * y2, 394 yz = y * z2, 395 zz = z * z2, 396 wx = w * x2, 397 wy = w * y2, 398 wz = w * z2; 399 400 out[0] = 1 - (yy + zz); 401 out[1] = xy + wz; 402 out[2] = xz - wy; 403 404 out[3] = xy - wz; 405 out[4] = 1 - (xx + zz); 406 out[5] = yz + wx; 407 408 out[6] = xz + wy; 409 out[7] = yz - wx; 410 out[8] = 1 - (xx + yy); 411 412 return out; 413}; 414 415/** 416 * Returns a string representation of a mat3 417 * 418 * @param {mat3} mat matrix to represent as a string 419 * @returns {String} string representation of the matrix 420 */ 421mat3.str = function (a) { 422 return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 423 a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + 424 a[6] + ', ' + a[7] + ', ' + a[8] + ')'; 425}; 426 427if(typeof(exports) !== 'undefined') { 428 exports.mat3 = mat3; 429} 430