diff --git a/Gruntfile.js b/Gruntfile.js index bf51893..45dbfa7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -44,21 +44,12 @@ module.exports = function(grunt) { "typedefs" : { "deps" : [], "exports" : "typedefs" - }, - "glMatrix" : { - "deps" : ["typedefs"], - "exports" : "glMatrix" - }, - "glMatrixAddon" : { - "deps" : ["glMatrix"], - "exports" : "glMatrixAddon" } }, "paths" : { "typedefs" : "typedefs", - "glMatrix" : "vendor/glMatrix", - "glMatrixAddon" : "glMatrixAddon" + "gl-matrix": "../node_modules/gl-matrix/dist/gl-matrix" } } } diff --git a/dist/quagga.js b/dist/quagga.js index 0089a8d..f61b3d2 100644 --- a/dist/quagga.js +++ b/dist/quagga.js @@ -1875,2350 +1875,3950 @@ define('subImage',["typedefs"], function() { return (SubImage); }); -/* jshint undef: true, unused: true, browser:true, devel: true */ -/* global define, vec2 */ +/** + * @fileoverview gl-matrix - High performance matrix and vector operations + * @author Brandon Jones + * @author Colin MacKenzie IV + * @version 2.1.0 + */ + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + +(function() { + + + var shim = {}; + if (typeof(exports) === 'undefined') { + if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + shim.exports = {}; + define('gl-matrix',[],function() { + return shim.exports; + }); + } else { + // gl-matrix lives in a browser, define its namespaces in global + shim.exports = window; + } + } + else { + // gl-matrix lives in commonjs, define its namespaces in exports + shim.exports = exports; + } + + (function(exports) { + /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + +if(!GLMAT_EPSILON) { + var GLMAT_EPSILON = 0.000001; +} + +if(!GLMAT_ARRAY_TYPE) { + var GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array; +} + +/** + * @class Common utilities + * @name glMatrix + */ +var glMatrix = {}; + +/** + * Sets the type of array used when creating new vectors and matricies + * + * @param {Type} type Array type, such as Float32Array or Array + */ +glMatrix.setMatrixArrayType = function(type) { + GLMAT_ARRAY_TYPE = type; +} + +if(typeof(exports) !== 'undefined') { + exports.glMatrix = glMatrix; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class 2 Dimensional Vector + * @name vec2 + */ + +var vec2 = {}; + +/** + * Creates a new, empty vec2 + * + * @returns {vec2} a new 2D vector + */ +vec2.create = function() { + var out = new GLMAT_ARRAY_TYPE(2); + out[0] = 0; + out[1] = 0; + return out; +}; + +/** + * Creates a new vec2 initialized with values from an existing vector + * + * @param {vec2} a vector to clone + * @returns {vec2} a new 2D vector + */ +vec2.clone = function(a) { + var out = new GLMAT_ARRAY_TYPE(2); + out[0] = a[0]; + out[1] = a[1]; + return out; +}; + +/** + * Creates a new vec2 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @returns {vec2} a new 2D vector + */ +vec2.fromValues = function(x, y) { + var out = new GLMAT_ARRAY_TYPE(2); + out[0] = x; + out[1] = y; + return out; +}; + +/** + * Copy the values from one vec2 to another + * + * @param {vec2} out the receiving vector + * @param {vec2} a the source vector + * @returns {vec2} out + */ +vec2.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + return out; +}; + +/** + * Set the components of a vec2 to the given values + * + * @param {vec2} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @returns {vec2} out + */ +vec2.set = function(out, x, y) { + out[0] = x; + out[1] = y; + return out; +}; + +/** + * Adds two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.add = function(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + return out; +}; + +/** + * Subtracts two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.subtract = function(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + return out; +}; + +/** + * Alias for {@link vec2.subtract} + * @function + */ +vec2.sub = vec2.subtract; + +/** + * Multiplies two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.multiply = function(out, a, b) { + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + return out; +}; + +/** + * Alias for {@link vec2.multiply} + * @function + */ +vec2.mul = vec2.multiply; + +/** + * Divides two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.divide = function(out, a, b) { + out[0] = a[0] / b[0]; + out[1] = a[1] / b[1]; + return out; +}; + +/** + * Alias for {@link vec2.divide} + * @function + */ +vec2.div = vec2.divide; + +/** + * Returns the minimum of two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.min = function(out, a, b) { + out[0] = Math.min(a[0], b[0]); + out[1] = Math.min(a[1], b[1]); + return out; +}; + +/** + * Returns the maximum of two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.max = function(out, a, b) { + out[0] = Math.max(a[0], b[0]); + out[1] = Math.max(a[1], b[1]); + return out; +}; + +/** + * Scales a vec2 by a scalar number + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec2} out + */ +vec2.scale = function(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + return out; +}; + +/** + * Calculates the euclidian distance between two vec2's + * + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {Number} distance between a and b + */ +vec2.distance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1]; + return Math.sqrt(x*x + y*y); +}; + +/** + * Alias for {@link vec2.distance} + * @function + */ +vec2.dist = vec2.distance; + +/** + * Calculates the squared euclidian distance between two vec2's + * + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {Number} squared distance between a and b + */ +vec2.squaredDistance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1]; + return x*x + y*y; +}; + +/** + * Alias for {@link vec2.squaredDistance} + * @function + */ +vec2.sqrDist = vec2.squaredDistance; + +/** + * Calculates the length of a vec2 + * + * @param {vec2} a vector to calculate length of + * @returns {Number} length of a + */ +vec2.length = function (a) { + var x = a[0], + y = a[1]; + return Math.sqrt(x*x + y*y); +}; + +/** + * Alias for {@link vec2.length} + * @function + */ +vec2.len = vec2.length; + +/** + * Calculates the squared length of a vec2 + * + * @param {vec2} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +vec2.squaredLength = function (a) { + var x = a[0], + y = a[1]; + return x*x + y*y; +}; + +/** + * Alias for {@link vec2.squaredLength} + * @function + */ +vec2.sqrLen = vec2.squaredLength; + +/** + * Negates the components of a vec2 + * + * @param {vec2} out the receiving vector + * @param {vec2} a vector to negate + * @returns {vec2} out + */ +vec2.negate = function(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + return out; +}; + +/** + * Normalize a vec2 + * + * @param {vec2} out the receiving vector + * @param {vec2} a vector to normalize + * @returns {vec2} out + */ +vec2.normalize = function(out, a) { + var x = a[0], + y = a[1]; + var len = x*x + y*y; + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len); + out[0] = a[0] * len; + out[1] = a[1] * len; + } + return out; +}; + +/** + * Calculates the dot product of two vec2's + * + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {Number} dot product of a and b + */ +vec2.dot = function (a, b) { + return a[0] * b[0] + a[1] * b[1]; +}; + +/** + * Computes the cross product of two vec2's + * Note that the cross product must by definition produce a 3D vector + * + * @param {vec3} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec3} out + */ +vec2.cross = function(out, a, b) { + var z = a[0] * b[1] - a[1] * b[0]; + out[0] = out[1] = 0; + out[2] = z; + return out; +}; + +/** + * Performs a linear interpolation between two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec2} out + */ +vec2.lerp = function (out, a, b, t) { + var ax = a[0], + ay = a[1]; + out[0] = ax + t * (b[0] - ax); + out[1] = ay + t * (b[1] - ay); + return out; +}; + +/** + * Transforms the vec2 with a mat2 + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat2} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat2 = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[2] * y; + out[1] = m[1] * x + m[3] * y; + return out; +}; + +/** + * Transforms the vec2 with a mat2d + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat2d} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat2d = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[2] * y + m[4]; + out[1] = m[1] * x + m[3] * y + m[5]; + return out; +}; + +/** + * Transforms the vec2 with a mat3 + * 3rd vector component is implicitly '1' + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat3} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat3 = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[3] * y + m[6]; + out[1] = m[1] * x + m[4] * y + m[7]; + return out; +}; + +/** + * Transforms the vec2 with a mat4 + * 3rd vector component is implicitly '0' + * 4th vector component is implicitly '1' + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat4 = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[4] * y + m[12]; + out[1] = m[1] * x + m[5] * y + m[13]; + return out; +}; + +/** + * Perform some operation over an array of vec2s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +vec2.forEach = (function() { + var vec = vec2.create(); + + return function(a, stride, offset, count, fn, arg) { + var i, l; + if(!stride) { + stride = 2; + } + + if(!offset) { + offset = 0; + } + + if(count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i]; vec[1] = a[i+1]; + fn(vec, vec, arg); + a[i] = vec[0]; a[i+1] = vec[1]; + } + + return a; + }; +})(); + +/** + * Returns a string representation of a vector + * + * @param {vec2} vec vector to represent as a string + * @returns {String} string representation of the vector + */ +vec2.str = function (a) { + return 'vec2(' + a[0] + ', ' + a[1] + ')'; +}; + +if(typeof(exports) !== 'undefined') { + exports.vec2 = vec2; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class 3 Dimensional Vector + * @name vec3 + */ + +var vec3 = {}; + +/** + * Creates a new, empty vec3 + * + * @returns {vec3} a new 3D vector + */ +vec3.create = function() { + var out = new GLMAT_ARRAY_TYPE(3); + out[0] = 0; + out[1] = 0; + out[2] = 0; + return out; +}; + +/** + * Creates a new vec3 initialized with values from an existing vector + * + * @param {vec3} a vector to clone + * @returns {vec3} a new 3D vector + */ +vec3.clone = function(a) { + var out = new GLMAT_ARRAY_TYPE(3); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + return out; +}; + +/** + * Creates a new vec3 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} a new 3D vector + */ +vec3.fromValues = function(x, y, z) { + var out = new GLMAT_ARRAY_TYPE(3); + out[0] = x; + out[1] = y; + out[2] = z; + return out; +}; + +/** + * Copy the values from one vec3 to another + * + * @param {vec3} out the receiving vector + * @param {vec3} a the source vector + * @returns {vec3} out + */ +vec3.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + return out; +}; + +/** + * Set the components of a vec3 to the given values + * + * @param {vec3} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} out + */ +vec3.set = function(out, x, y, z) { + out[0] = x; + out[1] = y; + out[2] = z; + return out; +}; + +/** + * Adds two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.add = function(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + return out; +}; + +/** + * Subtracts two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.subtract = function(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + return out; +}; + +/** + * Alias for {@link vec3.subtract} + * @function + */ +vec3.sub = vec3.subtract; + +/** + * Multiplies two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.multiply = function(out, a, b) { + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + return out; +}; + +/** + * Alias for {@link vec3.multiply} + * @function + */ +vec3.mul = vec3.multiply; + +/** + * Divides two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.divide = function(out, a, b) { + out[0] = a[0] / b[0]; + out[1] = a[1] / b[1]; + out[2] = a[2] / b[2]; + return out; +}; + +/** + * Alias for {@link vec3.divide} + * @function + */ +vec3.div = vec3.divide; + +/** + * Returns the minimum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.min = function(out, a, b) { + out[0] = Math.min(a[0], b[0]); + out[1] = Math.min(a[1], b[1]); + out[2] = Math.min(a[2], b[2]); + return out; +}; + +/** + * Returns the maximum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.max = function(out, a, b) { + out[0] = Math.max(a[0], b[0]); + out[1] = Math.max(a[1], b[1]); + out[2] = Math.max(a[2], b[2]); + return out; +}; + +/** + * Scales a vec3 by a scalar number + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec3} out + */ +vec3.scale = function(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + return out; +}; + +/** + * Calculates the euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} distance between a and b + */ +vec3.distance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2]; + return Math.sqrt(x*x + y*y + z*z); +}; + +/** + * Alias for {@link vec3.distance} + * @function + */ +vec3.dist = vec3.distance; + +/** + * Calculates the squared euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} squared distance between a and b + */ +vec3.squaredDistance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2]; + return x*x + y*y + z*z; +}; + +/** + * Alias for {@link vec3.squaredDistance} + * @function + */ +vec3.sqrDist = vec3.squaredDistance; + +/** + * Calculates the length of a vec3 + * + * @param {vec3} a vector to calculate length of + * @returns {Number} length of a + */ +vec3.length = function (a) { + var x = a[0], + y = a[1], + z = a[2]; + return Math.sqrt(x*x + y*y + z*z); +}; + +/** + * Alias for {@link vec3.length} + * @function + */ +vec3.len = vec3.length; + +/** + * Calculates the squared length of a vec3 + * + * @param {vec3} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +vec3.squaredLength = function (a) { + var x = a[0], + y = a[1], + z = a[2]; + return x*x + y*y + z*z; +}; + +/** + * Alias for {@link vec3.squaredLength} + * @function + */ +vec3.sqrLen = vec3.squaredLength; + +/** + * Negates the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to negate + * @returns {vec3} out + */ +vec3.negate = function(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + return out; +}; + +/** + * Normalize a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to normalize + * @returns {vec3} out + */ +vec3.normalize = function(out, a) { + var x = a[0], + y = a[1], + z = a[2]; + var len = x*x + y*y + z*z; + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len); + out[0] = a[0] * len; + out[1] = a[1] * len; + out[2] = a[2] * len; + } + return out; +}; + +/** + * Calculates the dot product of two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} dot product of a and b + */ +vec3.dot = function (a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +}; -define('cluster',[],function() { - - - /** - * Creates a cluster for grouping similar orientations of datapoints - */ - var Cluster = { - create : function(point, threshold) { - var points = [], center = { - rad : 0, - vec : vec2.create([0, 0]) - }, pointMap = {}; +/** + * Computes the cross product of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.cross = function(out, a, b) { + var ax = a[0], ay = a[1], az = a[2], + bx = b[0], by = b[1], bz = b[2]; + + out[0] = ay * bz - az * by; + out[1] = az * bx - ax * bz; + out[2] = ax * by - ay * bx; + return out; +}; - function init() { - add(point); - updateCenter(); - } +/** + * Performs a linear interpolation between two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec3} out + */ +vec3.lerp = function (out, a, b, t) { + var ax = a[0], + ay = a[1], + az = a[2]; + out[0] = ax + t * (b[0] - ax); + out[1] = ay + t * (b[1] - ay); + out[2] = az + t * (b[2] - az); + return out; +}; - function add(point) { - pointMap[point.id] = point; - points.push(point); - } +/** + * Transforms the vec3 with a mat4. + * 4th vector component is implicitly '1' + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec3} out + */ +vec3.transformMat4 = function(out, a, m) { + var x = a[0], y = a[1], z = a[2]; + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12]; + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13]; + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14]; + return out; +}; - function updateCenter() { - var i, sum = 0; - for ( i = 0; i < points.length; i++) { - sum += points[i].rad; - } - center.rad = sum / points.length; - center.vec = vec2.create([Math.cos(center.rad), Math.sin(center.rad)]); - } +/** + * Transforms the vec3 with a quat + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {quat} q quaternion to transform with + * @returns {vec3} out + */ +vec3.transformQuat = function(out, a, q) { + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; + out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; + out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return out; +}; - init(); +/** + * Perform some operation over an array of vec3s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +vec3.forEach = (function() { + var vec = vec3.create(); - return { - add : function(point) { - if (!pointMap[point.id]) { - add(point); - updateCenter(); - } - }, - fits : function(point) { - // check cosine similarity to center-angle - var similarity = Math.abs(vec2.dot(point.point.vec, center.vec)); - if (similarity > threshold) { - return true; - } - return false; - }, - getPoints : function() { - return points; - }, - getCenter : function() { - return center; - } - }; - }, - createPoint : function(point, id, property) { - return { - rad : point[property], - point : point, - id : id - }; + return function(a, stride, offset, count, fn, arg) { + var i, l; + if(!stride) { + stride = 3; + } + + if(!offset) { + offset = 0; + } + + if(count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; + fn(vec, vec, arg); + a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; + } + + return a; + }; +})(); + +/** + * Returns a string representation of a vector + * + * @param {vec3} vec vector to represent as a string + * @returns {String} string representation of the vector + */ +vec3.str = function (a) { + return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; +}; + +if(typeof(exports) !== 'undefined') { + exports.vec3 = vec3; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class 4 Dimensional Vector + * @name vec4 + */ + +var vec4 = {}; + +/** + * Creates a new, empty vec4 + * + * @returns {vec4} a new 4D vector + */ +vec4.create = function() { + var out = new GLMAT_ARRAY_TYPE(4); + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 0; + return out; +}; + +/** + * Creates a new vec4 initialized with values from an existing vector + * + * @param {vec4} a vector to clone + * @returns {vec4} a new 4D vector + */ +vec4.clone = function(a) { + var out = new GLMAT_ARRAY_TYPE(4); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Creates a new vec4 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} a new 4D vector + */ +vec4.fromValues = function(x, y, z, w) { + var out = new GLMAT_ARRAY_TYPE(4); + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = w; + return out; +}; + +/** + * Copy the values from one vec4 to another + * + * @param {vec4} out the receiving vector + * @param {vec4} a the source vector + * @returns {vec4} out + */ +vec4.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Set the components of a vec4 to the given values + * + * @param {vec4} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} out + */ +vec4.set = function(out, x, y, z, w) { + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = w; + return out; +}; + +/** + * Adds two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.add = function(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; + return out; +}; + +/** + * Subtracts two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.subtract = function(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; + return out; +}; + +/** + * Alias for {@link vec4.subtract} + * @function + */ +vec4.sub = vec4.subtract; + +/** + * Multiplies two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.multiply = function(out, a, b) { + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + out[3] = a[3] * b[3]; + return out; +}; + +/** + * Alias for {@link vec4.multiply} + * @function + */ +vec4.mul = vec4.multiply; + +/** + * Divides two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.divide = function(out, a, b) { + out[0] = a[0] / b[0]; + out[1] = a[1] / b[1]; + out[2] = a[2] / b[2]; + out[3] = a[3] / b[3]; + return out; +}; + +/** + * Alias for {@link vec4.divide} + * @function + */ +vec4.div = vec4.divide; + +/** + * Returns the minimum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.min = function(out, a, b) { + out[0] = Math.min(a[0], b[0]); + out[1] = Math.min(a[1], b[1]); + out[2] = Math.min(a[2], b[2]); + out[3] = Math.min(a[3], b[3]); + return out; +}; + +/** + * Returns the maximum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.max = function(out, a, b) { + out[0] = Math.max(a[0], b[0]); + out[1] = Math.max(a[1], b[1]); + out[2] = Math.max(a[2], b[2]); + out[3] = Math.max(a[3], b[3]); + return out; +}; + +/** + * Scales a vec4 by a scalar number + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec4} out + */ +vec4.scale = function(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + out[3] = a[3] * b; + return out; +}; + +/** + * Calculates the euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} distance between a and b + */ +vec4.distance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3]; + return Math.sqrt(x*x + y*y + z*z + w*w); +}; + +/** + * Alias for {@link vec4.distance} + * @function + */ +vec4.dist = vec4.distance; + +/** + * Calculates the squared euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} squared distance between a and b + */ +vec4.squaredDistance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3]; + return x*x + y*y + z*z + w*w; +}; + +/** + * Alias for {@link vec4.squaredDistance} + * @function + */ +vec4.sqrDist = vec4.squaredDistance; + +/** + * Calculates the length of a vec4 + * + * @param {vec4} a vector to calculate length of + * @returns {Number} length of a + */ +vec4.length = function (a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3]; + return Math.sqrt(x*x + y*y + z*z + w*w); +}; + +/** + * Alias for {@link vec4.length} + * @function + */ +vec4.len = vec4.length; + +/** + * Calculates the squared length of a vec4 + * + * @param {vec4} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +vec4.squaredLength = function (a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3]; + return x*x + y*y + z*z + w*w; +}; + +/** + * Alias for {@link vec4.squaredLength} + * @function + */ +vec4.sqrLen = vec4.squaredLength; + +/** + * Negates the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to negate + * @returns {vec4} out + */ +vec4.negate = function(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = -a[3]; + return out; +}; + +/** + * Normalize a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to normalize + * @returns {vec4} out + */ +vec4.normalize = function(out, a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3]; + var len = x*x + y*y + z*z + w*w; + if (len > 0) { + len = 1 / Math.sqrt(len); + out[0] = a[0] * len; + out[1] = a[1] * len; + out[2] = a[2] * len; + out[3] = a[3] * len; + } + return out; +}; + +/** + * Calculates the dot product of two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} dot product of a and b + */ +vec4.dot = function (a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +}; + +/** + * Performs a linear interpolation between two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec4} out + */ +vec4.lerp = function (out, a, b, t) { + var ax = a[0], + ay = a[1], + az = a[2], + aw = a[3]; + out[0] = ax + t * (b[0] - ax); + out[1] = ay + t * (b[1] - ay); + out[2] = az + t * (b[2] - az); + out[3] = aw + t * (b[3] - aw); + return out; +}; + +/** + * Transforms the vec4 with a mat4. + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec4} out + */ +vec4.transformMat4 = function(out, a, m) { + var x = a[0], y = a[1], z = a[2], w = a[3]; + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; + return out; +}; + +/** + * Transforms the vec4 with a quat + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {quat} q quaternion to transform with + * @returns {vec4} out + */ +vec4.transformQuat = function(out, a, q) { + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; + out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; + out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return out; +}; + +/** + * Perform some operation over an array of vec4s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +vec4.forEach = (function() { + var vec = vec4.create(); + + return function(a, stride, offset, count, fn, arg) { + var i, l; + if(!stride) { + stride = 4; + } + + if(!offset) { + offset = 0; + } + + if(count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; + fn(vec, vec, arg); + a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; } + + return a; }; +})(); + +/** + * Returns a string representation of a vector + * + * @param {vec4} vec vector to represent as a string + * @returns {String} string representation of the vector + */ +vec4.str = function (a) { + return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; +}; + +if(typeof(exports) !== 'undefined') { + exports.vec4 = vec4; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class 2x2 Matrix + * @name mat2 + */ + +var mat2 = {}; + +var mat2Identity = new Float32Array([ + 1, 0, + 0, 1 +]); - return (Cluster); -}); +/** + * Creates a new identity mat2 + * + * @returns {mat2} a new 2x2 matrix + */ +mat2.create = function() { + var out = new GLMAT_ARRAY_TYPE(4); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +}; -/* - * glMatrix.js - High performance matrix and vector operations for WebGL - * version 0.9.6 +/** + * Creates a new mat2 initialized with values from an existing matrix + * + * @param {mat2} a matrix to clone + * @returns {mat2} a new 2x2 matrix */ - -/* - * Copyright (c) 2011 Brandon Jones +mat2.clone = function(a) { + var out = new GLMAT_ARRAY_TYPE(4); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Copy the values from one mat2 to another * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +mat2.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Set a mat2 to the identity matrix * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: + * @param {mat2} out the receiving matrix + * @returns {mat2} out + */ +mat2.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +}; + +/** + * Transpose the values of a mat2 * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +mat2.transpose = function(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a1 = a[1]; + out[1] = a[2]; + out[2] = a1; + } else { + out[0] = a[0]; + out[1] = a[2]; + out[2] = a[1]; + out[3] = a[3]; + } + + return out; +}; + +/** + * Inverts a mat2 * - * 2. Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +mat2.invert = function(out, a) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + + // Calculate the determinant + det = a0 * a3 - a2 * a1; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = a3 * det; + out[1] = -a1 * det; + out[2] = -a2 * det; + out[3] = a0 * det; + + return out; +}; + +/** + * Calculates the adjugate of a mat2 * - * 3. This notice may not be removed or altered from any source - * distribution. + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out */ +mat2.adjoint = function(out, a) { + // Caching this value is nessecary if out == a + var a0 = a[0]; + out[0] = a[3]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = a0; + + return out; +}; +/** + * Calculates the determinant of a mat2 + * + * @param {mat2} a the source matrix + * @returns {Number} determinant of a + */ +mat2.determinant = function (a) { + return a[0] * a[3] - a[2] * a[1]; +}; +/** + * Multiplies two mat2's + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the first operand + * @param {mat2} b the second operand + * @returns {mat2} out + */ +mat2.multiply = function (out, a, b) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; + var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + out[0] = a0 * b0 + a1 * b2; + out[1] = a0 * b1 + a1 * b3; + out[2] = a2 * b0 + a3 * b2; + out[3] = a2 * b1 + a3 * b3; + return out; +}; -/* - * vec3 - 3 Dimensional Vector +/** + * Alias for {@link mat2.multiply} + * @function */ -var vec3 = {}; +mat2.mul = mat2.multiply; -/* - * vec3.create - * Creates a new instance of a vec3 using the default array type - * Any javascript array containing at least 3 numeric elements can serve as a vec3 - * - * Params: - * vec - Optional, vec3 containing values to initialize with - * - * Returns: - * New vec3 - */ -vec3.create = function(vec) { - var dest; - if(vec) { - dest = new glMatrixArrayType(3); - dest[0] = vec[0]; - dest[1] = vec[1]; - dest[2] = vec[2]; - } else { - if(glMatrixArrayType === Array) - dest = new glMatrixArrayType([0,0,0]); - else - dest = new glMatrixArrayType(3); - } - - return dest; +/** + * Rotates a mat2 by the given angle + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat2} out + */ +mat2.rotate = function (out, a, rad) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + s = Math.sin(rad), + c = Math.cos(rad); + out[0] = a0 * c + a1 * s; + out[1] = a0 * -s + a1 * c; + out[2] = a2 * c + a3 * s; + out[3] = a2 * -s + a3 * c; + return out; }; -/* - * vec3.set - * Copies the values of one vec3 to another +/** + * Scales the mat2 by the dimensions in the given vec2 * - * Params: - * vec - vec3 containing values to copy - * dest - vec3 receiving copied values + * @param {mat2} out the receiving matrix + * @param {mat2} a the matrix to rotate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat2} out + **/ +mat2.scale = function(out, a, v) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + v0 = v[0], v1 = v[1]; + out[0] = a0 * v0; + out[1] = a1 * v1; + out[2] = a2 * v0; + out[3] = a3 * v1; + return out; +}; + +/** + * Returns a string representation of a mat2 * - * Returns: - * dest + * @param {mat2} mat matrix to represent as a string + * @returns {String} string representation of the matrix */ -vec3.set = function(vec, dest) { - dest[0] = vec[0]; - dest[1] = vec[1]; - dest[2] = vec[2]; - - return dest; +mat2.str = function (a) { + return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; -/* - * vec3.add - * Performs a vector addition - * - * Params: - * vec - vec3, first operand - * vec2 - vec3, second operand - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec - * - * Returns: - * dest if specified, vec otherwise - */ -vec3.add = function(vec, vec2, dest) { - if(!dest || vec == dest) { - vec[0] += vec2[0]; - vec[1] += vec2[1]; - vec[2] += vec2[2]; - return vec; - } - - dest[0] = vec[0] + vec2[0]; - dest[1] = vec[1] + vec2[1]; - dest[2] = vec[2] + vec2[2]; - return dest; +if(typeof(exports) !== 'undefined') { + exports.mat2 = mat2; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class 2x3 Matrix + * @name mat2d + * + * @description + * A mat2d contains six elements defined as: + *
+ * [a, b, + * c, d, + * tx,ty] + *+ * This is a short form for the 3x3 matrix: + *
+ * [a, b, 0 + * c, d, 0 + * tx,ty,1] + *+ * The last column is ignored so the array is shorter and operations are faster. + */ + +var mat2d = {}; + +var mat2dIdentity = new Float32Array([ + 1, 0, + 0, 1, + 0, 0 +]); + +/** + * Creates a new identity mat2d + * + * @returns {mat2d} a new 2x3 matrix + */ +mat2d.create = function() { + var out = new GLMAT_ARRAY_TYPE(6); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; }; -/* - * vec3.subtract - * Performs a vector subtraction - * - * Params: - * vec - vec3, first operand - * vec2 - vec3, second operand - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec - * - * Returns: - * dest if specified, vec otherwise - */ -vec3.subtract = function(vec, vec2, dest) { - if(!dest || vec == dest) { - vec[0] -= vec2[0]; - vec[1] -= vec2[1]; - vec[2] -= vec2[2]; - return vec; - } - - dest[0] = vec[0] - vec2[0]; - dest[1] = vec[1] - vec2[1]; - dest[2] = vec[2] - vec2[2]; - return dest; +/** + * Creates a new mat2d initialized with values from an existing matrix + * + * @param {mat2d} a matrix to clone + * @returns {mat2d} a new 2x3 matrix + */ +mat2d.clone = function(a) { + var out = new GLMAT_ARRAY_TYPE(6); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + return out; }; -/* - * vec3.negate - * Negates the components of a vec3 +/** + * Copy the values from one mat2d to another * - * Params: - * vec - vec3 to negate - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the source matrix + * @returns {mat2d} out + */ +mat2d.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + return out; +}; + +/** + * Set a mat2d to the identity matrix * - * Returns: - * dest if specified, vec otherwise + * @param {mat2d} out the receiving matrix + * @returns {mat2d} out */ -vec3.negate = function(vec, dest) { - if(!dest) { dest = vec; } - - dest[0] = -vec[0]; - dest[1] = -vec[1]; - dest[2] = -vec[2]; - return dest; +mat2d.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; }; -/* - * vec3.scale - * Multiplies the components of a vec3 by a scalar value - * - * Params: - * vec - vec3 to scale - * val - Numeric value to scale by - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec - * - * Returns: - * dest if specified, vec otherwise - */ -vec3.scale = function(vec, val, dest) { - if(!dest || vec == dest) { - vec[0] *= val; - vec[1] *= val; - vec[2] *= val; - return vec; - } - - dest[0] = vec[0]*val; - dest[1] = vec[1]*val; - dest[2] = vec[2]*val; - return dest; +/** + * Inverts a mat2d + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the source matrix + * @returns {mat2d} out + */ +mat2d.invert = function(out, a) { + var aa = a[0], ab = a[1], ac = a[2], ad = a[3], + atx = a[4], aty = a[5]; + + var det = aa * ad - ab * ac; + if(!det){ + return null; + } + det = 1.0 / det; + + out[0] = ad * det; + out[1] = -ab * det; + out[2] = -ac * det; + out[3] = aa * det; + out[4] = (ac * aty - ad * atx) * det; + out[5] = (ab * atx - aa * aty) * det; + return out; }; -/* - * vec3.normalize - * Generates a unit vector of the same direction as the provided vec3 - * If vector length is 0, returns [0, 0, 0] - * - * Params: - * vec - vec3 to normalize - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec - * - * Returns: - * dest if specified, vec otherwise - */ -vec3.normalize = function(vec, dest) { - if(!dest) { dest = vec; } - - var x = vec[0], y = vec[1], z = vec[2]; - var len = Math.sqrt(x*x + y*y + z*z); - - if (!len) { - dest[0] = 0; - dest[1] = 0; - dest[2] = 0; - return dest; - } else if (len == 1) { - dest[0] = x; - dest[1] = y; - dest[2] = z; - return dest; - } - - len = 1 / len; - dest[0] = x*len; - dest[1] = y*len; - dest[2] = z*len; - return dest; +/** + * Calculates the determinant of a mat2d + * + * @param {mat2d} a the source matrix + * @returns {Number} determinant of a + */ +mat2d.determinant = function (a) { + return a[0] * a[3] - a[1] * a[2]; }; -/* - * vec3.cross - * Generates the cross product of two vec3s +/** + * Multiplies two mat2d's * - * Params: - * vec - vec3, first operand - * vec2 - vec3, second operand - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the first operand + * @param {mat2d} b the second operand + * @returns {mat2d} out + */ +mat2d.multiply = function (out, a, b) { + var aa = a[0], ab = a[1], ac = a[2], ad = a[3], + atx = a[4], aty = a[5], + ba = b[0], bb = b[1], bc = b[2], bd = b[3], + btx = b[4], bty = b[5]; + + out[0] = aa*ba + ab*bc; + out[1] = aa*bb + ab*bd; + out[2] = ac*ba + ad*bc; + out[3] = ac*bb + ad*bd; + out[4] = ba*atx + bc*aty + btx; + out[5] = bb*atx + bd*aty + bty; + return out; +}; + +/** + * Alias for {@link mat2d.multiply} + * @function + */ +mat2d.mul = mat2d.multiply; + + +/** + * Rotates a mat2d by the given angle * - * Returns: - * dest if specified, vec otherwise + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat2d} out */ -vec3.cross = function(vec, vec2, dest){ - if(!dest) { dest = vec; } - - var x = vec[0], y = vec[1], z = vec[2]; - var x2 = vec2[0], y2 = vec2[1], z2 = vec2[2]; - - dest[0] = y*z2 - z*y2; - dest[1] = z*x2 - x*z2; - dest[2] = x*y2 - y*x2; - return dest; +mat2d.rotate = function (out, a, rad) { + var aa = a[0], + ab = a[1], + ac = a[2], + ad = a[3], + atx = a[4], + aty = a[5], + st = Math.sin(rad), + ct = Math.cos(rad); + + out[0] = aa*ct + ab*st; + out[1] = -aa*st + ab*ct; + out[2] = ac*ct + ad*st; + out[3] = -ac*st + ct*ad; + out[4] = ct*atx + st*aty; + out[5] = ct*aty - st*atx; + return out; }; -/* - * vec3.length - * Caclulates the length of a vec3 +/** + * Scales the mat2d by the dimensions in the given vec2 + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the matrix to translate + * @param {mat2d} v the vec2 to scale the matrix by + * @returns {mat2d} out + **/ +mat2d.scale = function(out, a, v) { + var vx = v[0], vy = v[1]; + out[0] = a[0] * vx; + out[1] = a[1] * vy; + out[2] = a[2] * vx; + out[3] = a[3] * vy; + out[4] = a[4] * vx; + out[5] = a[5] * vy; + return out; +}; + +/** + * Translates the mat2d by the dimensions in the given vec2 * - * Params: - * vec - vec3 to calculate length of + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the matrix to translate + * @param {mat2d} v the vec2 to translate the matrix by + * @returns {mat2d} out + **/ +mat2d.translate = function(out, a, v) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4] + v[0]; + out[5] = a[5] + v[1]; + return out; +}; + +/** + * Returns a string representation of a mat2d * - * Returns: - * Length of vec + * @param {mat2d} a matrix to represent as a string + * @returns {String} string representation of the matrix */ -vec3.length = function(vec){ - var x = vec[0], y = vec[1], z = vec[2]; - return Math.sqrt(x*x + y*y + z*z); +mat2d.str = function (a) { + return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + + a[3] + ', ' + a[4] + ', ' + a[5] + ')'; }; -/* - * vec3.dot - * Caclulates the dot product of two vec3s +if(typeof(exports) !== 'undefined') { + exports.mat2d = mat2d; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class 3x3 Matrix + * @name mat3 + */ + +var mat3 = {}; + +var mat3Identity = new Float32Array([ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 +]); + +/** + * Creates a new identity mat3 * - * Params: - * vec - vec3, first operand - * vec2 - vec3, second operand + * @returns {mat3} a new 3x3 matrix + */ +mat3.create = function() { + var out = new GLMAT_ARRAY_TYPE(9); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 1; + out[5] = 0; + out[6] = 0; + out[7] = 0; + out[8] = 1; + return out; +}; + +/** + * Creates a new mat3 initialized with values from an existing matrix * - * Returns: - * Dot product of vec and vec2 + * @param {mat3} a matrix to clone + * @returns {mat3} a new 3x3 matrix */ -vec3.dot = function(vec, vec2){ - return vec[0]*vec2[0] + vec[1]*vec2[1] + vec[2]*vec2[2]; +mat3.clone = function(a) { + var out = new GLMAT_ARRAY_TYPE(9); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + return out; }; -/* - * vec3.direction - * Generates a unit vector pointing from one vector to another - * - * Params: - * vec - origin vec3 - * vec2 - vec3 to point to - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec - * - * Returns: - * dest if specified, vec otherwise - */ -vec3.direction = function(vec, vec2, dest) { - if(!dest) { dest = vec; } - - var x = vec[0] - vec2[0]; - var y = vec[1] - vec2[1]; - var z = vec[2] - vec2[2]; - - var len = Math.sqrt(x*x + y*y + z*z); - if (!len) { - dest[0] = 0; - dest[1] = 0; - dest[2] = 0; - return dest; - } - - len = 1 / len; - dest[0] = x * len; - dest[1] = y * len; - dest[2] = z * len; - return dest; +/** + * Copy the values from one mat3 to another + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ +mat3.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + return out; }; -/* - * vec3.lerp - * Performs a linear interpolation between two vec3 +/** + * Set a mat3 to the identity matrix * - * Params: - * vec - vec3, first vector - * vec2 - vec3, second vector - * lerp - interpolation amount between the two inputs - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec + * @param {mat3} out the receiving matrix + * @returns {mat3} out + */ +mat3.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 1; + out[5] = 0; + out[6] = 0; + out[7] = 0; + out[8] = 1; + return out; +}; + +/** + * Transpose the values of a mat3 * - * Returns: - * dest if specified, vec otherwise + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out */ -vec3.lerp = function(vec, vec2, lerp, dest){ - if(!dest) { dest = vec; } - - dest[0] = vec[0] + lerp * (vec2[0] - vec[0]); - dest[1] = vec[1] + lerp * (vec2[1] - vec[1]); - dest[2] = vec[2] + lerp * (vec2[2] - vec[2]); +mat3.transpose = function(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a01 = a[1], a02 = a[2], a12 = a[5]; + out[1] = a[3]; + out[2] = a[6]; + out[3] = a01; + out[5] = a[7]; + out[6] = a02; + out[7] = a12; + } else { + out[0] = a[0]; + out[1] = a[3]; + out[2] = a[6]; + out[3] = a[1]; + out[4] = a[4]; + out[5] = a[7]; + out[6] = a[2]; + out[7] = a[5]; + out[8] = a[8]; + } - return dest; + return out; }; -/* - * vec3.str - * Returns a string representation of a vector +/** + * Inverts a mat3 * - * Params: - * vec - vec3 to represent as a string + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ +mat3.invert = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + + b01 = a22 * a11 - a12 * a21, + b11 = -a22 * a10 + a12 * a20, + b21 = a21 * a10 - a11 * a20, + + // Calculate the determinant + det = a00 * b01 + a01 * b11 + a02 * b21; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = b01 * det; + out[1] = (-a22 * a01 + a02 * a21) * det; + out[2] = (a12 * a01 - a02 * a11) * det; + out[3] = b11 * det; + out[4] = (a22 * a00 - a02 * a20) * det; + out[5] = (-a12 * a00 + a02 * a10) * det; + out[6] = b21 * det; + out[7] = (-a21 * a00 + a01 * a20) * det; + out[8] = (a11 * a00 - a01 * a10) * det; + return out; +}; + +/** + * Calculates the adjugate of a mat3 * - * Returns: - * string representation of vec + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out */ -vec3.str = function(vec) { - return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']'; +mat3.adjoint = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8]; + + out[0] = (a11 * a22 - a12 * a21); + out[1] = (a02 * a21 - a01 * a22); + out[2] = (a01 * a12 - a02 * a11); + out[3] = (a12 * a20 - a10 * a22); + out[4] = (a00 * a22 - a02 * a20); + out[5] = (a02 * a10 - a00 * a12); + out[6] = (a10 * a21 - a11 * a20); + out[7] = (a01 * a20 - a00 * a21); + out[8] = (a00 * a11 - a01 * a10); + return out; }; -/* - * mat3 - 3x3 Matrix +/** + * Calculates the determinant of a mat3 + * + * @param {mat3} a the source matrix + * @returns {Number} determinant of a */ -var mat3 = {}; +mat3.determinant = function (a) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8]; -/* - * mat3.create - * Creates a new instance of a mat3 using the default array type - * Any javascript array containing at least 9 numeric elements can serve as a mat3 - * - * Params: - * mat - Optional, mat3 containing values to initialize with - * - * Returns: - * New mat3 - */ -mat3.create = function(mat) { - var dest; - - if(mat) { - dest = new glMatrixArrayType(9); - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[3]; - dest[4] = mat[4]; - dest[5] = mat[5]; - dest[6] = mat[6]; - dest[7] = mat[7]; - dest[8] = mat[8]; - } else { - if(glMatrixArrayType === Array) - dest = new glMatrixArrayType([0,0,0,0,0,0,0,0,0]); - else - dest = new glMatrixArrayType(9); - } - - return dest; + return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); }; -/* - * mat3.set - * Copies the values of one mat3 to another - * - * Params: - * mat - mat3 containing values to copy - * dest - mat3 receiving copied values +/** + * Multiplies two mat3's * - * Returns: - * dest + * @param {mat3} out the receiving matrix + * @param {mat3} a the first operand + * @param {mat3} b the second operand + * @returns {mat3} out */ -mat3.set = function(mat, dest) { - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[3]; - dest[4] = mat[4]; - dest[5] = mat[5]; - dest[6] = mat[6]; - dest[7] = mat[7]; - dest[8] = mat[8]; - return dest; +mat3.multiply = function (out, a, b) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + + b00 = b[0], b01 = b[1], b02 = b[2], + b10 = b[3], b11 = b[4], b12 = b[5], + b20 = b[6], b21 = b[7], b22 = b[8]; + + out[0] = b00 * a00 + b01 * a10 + b02 * a20; + out[1] = b00 * a01 + b01 * a11 + b02 * a21; + out[2] = b00 * a02 + b01 * a12 + b02 * a22; + + out[3] = b10 * a00 + b11 * a10 + b12 * a20; + out[4] = b10 * a01 + b11 * a11 + b12 * a21; + out[5] = b10 * a02 + b11 * a12 + b12 * a22; + + out[6] = b20 * a00 + b21 * a10 + b22 * a20; + out[7] = b20 * a01 + b21 * a11 + b22 * a21; + out[8] = b20 * a02 + b21 * a12 + b22 * a22; + return out; }; -/* - * mat3.identity - * Sets a mat3 to an identity matrix +/** + * Alias for {@link mat3.multiply} + * @function + */ +mat3.mul = mat3.multiply; + +/** + * Translate a mat3 by the given vector * - * Params: - * dest - mat3 to set + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to translate + * @param {vec2} v vector to translate by + * @returns {mat3} out + */ +mat3.translate = function(out, a, v) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + x = v[0], y = v[1]; + + out[0] = a00; + out[1] = a01; + out[2] = a02; + + out[3] = a10; + out[4] = a11; + out[5] = a12; + + out[6] = x * a00 + y * a10 + a20; + out[7] = x * a01 + y * a11 + a21; + out[8] = x * a02 + y * a12 + a22; + return out; +}; + +/** + * Rotates a mat3 by the given angle * - * Returns: - * dest + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat3} out */ -mat3.identity = function(dest) { - dest[0] = 1; - dest[1] = 0; - dest[2] = 0; - dest[3] = 0; - dest[4] = 1; - dest[5] = 0; - dest[6] = 0; - dest[7] = 0; - dest[8] = 1; - return dest; +mat3.rotate = function (out, a, rad) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + + s = Math.sin(rad), + c = Math.cos(rad); + + out[0] = c * a00 + s * a10; + out[1] = c * a01 + s * a11; + out[2] = c * a02 + s * a12; + + out[3] = c * a10 - s * a00; + out[4] = c * a11 - s * a01; + out[5] = c * a12 - s * a02; + + out[6] = a20; + out[7] = a21; + out[8] = a22; + return out; }; -/* - * mat4.transpose - * Transposes a mat3 (flips the values over the diagonal) - * - * Params: - * mat - mat3 to transpose - * dest - Optional, mat3 receiving transposed values. If not specified result is written to mat - * - * Returns: - * dest is specified, mat otherwise - */ -mat3.transpose = function(mat, dest) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if(!dest || mat == dest) { - var a01 = mat[1], a02 = mat[2]; - var a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; +/** + * Scales the mat3 by the dimensions in the given vec2 + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat3} out + **/ +mat3.scale = function(out, a, v) { + var x = v[0], y = v[2]; + + out[0] = x * a[0]; + out[1] = x * a[1]; + out[2] = x * a[2]; + + out[3] = y * a[3]; + out[4] = y * a[4]; + out[5] = y * a[5]; + + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + return out; }; -/* - * mat3.toMat4 - * Copies the elements of a mat3 into the upper 3x3 elements of a mat4 - * - * Params: - * mat - mat3 containing values to copy - * dest - Optional, mat4 receiving copied values - * - * Returns: - * dest if specified, a new mat4 otherwise - */ -mat3.toMat4 = function(mat, dest) { - if(!dest) { dest = mat4.create(); } - - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = 0; - - dest[4] = mat[3]; - dest[5] = mat[4]; - dest[6] = mat[5]; - dest[7] = 0; - - dest[8] = mat[6]; - dest[9] = mat[7]; - dest[10] = mat[8]; - dest[11] = 0; - - dest[12] = 0; - dest[13] = 0; - dest[14] = 0; - dest[15] = 1; - - return dest; +/** + * Copies the values from a mat2d into a mat3 + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat3} out + **/ +mat3.fromMat2d = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = 0; + + out[3] = a[2]; + out[4] = a[3]; + out[5] = 0; + + out[6] = a[4]; + out[7] = a[5]; + out[8] = 1; + return out; }; -/* - * mat3.str +/** +* Calculates a 3x3 matrix from the given quaternion +* +* @param {mat3} out mat3 receiving operation result +* @param {quat} q Quaternion to create matrix from +* +* @returns {mat3} out +*/ +mat3.fromQuat = function (out, q) { + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - (yy + zz); + out[1] = xy + wz; + out[2] = xz - wy; + + out[3] = xy - wz; + out[4] = 1 - (xx + zz); + out[5] = yz + wx; + + out[6] = xz + wy; + out[7] = yz - wx; + out[8] = 1 - (xx + yy); + + return out; +}; + +/** * Returns a string representation of a mat3 * - * Params: - * mat - mat3 to represent as a string - * - * Returns: - * string representation of mat + * @param {mat3} mat matrix to represent as a string + * @returns {String} string representation of the matrix */ -mat3.str = function(mat) { - return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + - ', ' + mat[3] + ', '+ mat[4] + ', ' + mat[5] + - ', ' + mat[6] + ', ' + mat[7] + ', '+ mat[8] + ']'; +mat3.str = function (a) { + return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + + a[6] + ', ' + a[7] + ', ' + a[8] + ')'; }; -/* - * mat4 - 4x4 Matrix +if(typeof(exports) !== 'undefined') { + exports.mat3 = mat3; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class 4x4 Matrix + * @name mat4 */ + var mat4 = {}; -/* - * mat4.create - * Creates a new instance of a mat4 using the default array type - * Any javascript array containing at least 16 numeric elements can serve as a mat4 - * - * Params: - * mat - Optional, mat4 containing values to initialize with - * - * Returns: - * New mat4 - */ -mat4.create = function(mat) { - var dest; - - if(mat) { - dest = new glMatrixArrayType(16); - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[3]; - dest[4] = mat[4]; - dest[5] = mat[5]; - dest[6] = mat[6]; - dest[7] = mat[7]; - dest[8] = mat[8]; - dest[9] = mat[9]; - dest[10] = mat[10]; - dest[11] = mat[11]; - dest[12] = mat[12]; - dest[13] = mat[13]; - dest[14] = mat[14]; - dest[15] = mat[15]; - } else { - if(glMatrixArrayType === Array) - dest = new glMatrixArrayType([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); - else - dest = new glMatrixArrayType(16); - } - - return dest; -}; +var mat4Identity = new Float32Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +]); -/* - * mat4.set - * Copies the values of one mat4 to another - * - * Params: - * mat - mat4 containing values to copy - * dest - mat4 receiving copied values - * - * Returns: - * dest - */ -mat4.set = function(mat, dest) { - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[3]; - dest[4] = mat[4]; - dest[5] = mat[5]; - dest[6] = mat[6]; - dest[7] = mat[7]; - dest[8] = mat[8]; - dest[9] = mat[9]; - dest[10] = mat[10]; - dest[11] = mat[11]; - dest[12] = mat[12]; - dest[13] = mat[13]; - dest[14] = mat[14]; - dest[15] = mat[15]; - return dest; +/** + * Creates a new identity mat4 + * + * @returns {mat4} a new 4x4 matrix + */ +mat4.create = function() { + var out = new GLMAT_ARRAY_TYPE(16); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; }; -/* - * mat4.identity - * Sets a mat4 to an identity matrix - * - * Params: - * dest - mat4 to set - * - * Returns: - * dest - */ -mat4.identity = function(dest) { - dest[0] = 1; - dest[1] = 0; - dest[2] = 0; - dest[3] = 0; - dest[4] = 0; - dest[5] = 1; - dest[6] = 0; - dest[7] = 0; - dest[8] = 0; - dest[9] = 0; - dest[10] = 1; - dest[11] = 0; - dest[12] = 0; - dest[13] = 0; - dest[14] = 0; - dest[15] = 1; - return dest; +/** + * Creates a new mat4 initialized with values from an existing matrix + * + * @param {mat4} a matrix to clone + * @returns {mat4} a new 4x4 matrix + */ +mat4.clone = function(a) { + var out = new GLMAT_ARRAY_TYPE(16); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; }; -/* - * mat4.transpose - * Transposes a mat4 (flips the values over the diagonal) - * - * Params: - * mat - mat4 to transpose - * dest - Optional, mat4 receiving transposed values. If not specified result is written to mat - * - * Returns: - * dest is specified, mat otherwise - */ -mat4.transpose = function(mat, dest) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if(!dest || mat == dest) { - var a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a12 = mat[6], a13 = mat[7]; - var a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; +/** + * Copy the values from one mat4 to another + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; }; -/* - * mat4.determinant - * Calculates the determinant of a mat4 - * - * Params: - * mat - mat4 to calculate determinant of +/** + * Set a mat4 to the identity matrix * - * Returns: - * determinant of mat + * @param {mat4} out the receiving matrix + * @returns {mat4} out */ -mat4.determinant = function(mat) { - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - return a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 + - a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 + - a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 + - a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 + - a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 + - a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33; +mat4.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; }; -/* - * mat4.inverse - * Calculates the inverse matrix of a mat4 - * - * Params: - * mat - mat4 to calculate inverse of - * dest - Optional, mat4 receiving inverse matrix. If not specified result is written to mat - * - * Returns: - * dest is specified, mat otherwise - */ -mat4.inverse = function(mat, dest) { - if(!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - var b00 = a00*a11 - a01*a10; - var b01 = a00*a12 - a02*a10; - var b02 = a00*a13 - a03*a10; - var b03 = a01*a12 - a02*a11; - var b04 = a01*a13 - a03*a11; - var b05 = a02*a13 - a03*a12; - var b06 = a20*a31 - a21*a30; - var b07 = a20*a32 - a22*a30; - var b08 = a20*a33 - a23*a30; - var b09 = a21*a32 - a22*a31; - var b10 = a21*a33 - a23*a31; - var b11 = a22*a33 - a23*a32; - - // Calculate the determinant (inlined to avoid double-caching) - var invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); - - dest[0] = (a11*b11 - a12*b10 + a13*b09)*invDet; - dest[1] = (-a01*b11 + a02*b10 - a03*b09)*invDet; - dest[2] = (a31*b05 - a32*b04 + a33*b03)*invDet; - dest[3] = (-a21*b05 + a22*b04 - a23*b03)*invDet; - dest[4] = (-a10*b11 + a12*b08 - a13*b07)*invDet; - dest[5] = (a00*b11 - a02*b08 + a03*b07)*invDet; - dest[6] = (-a30*b05 + a32*b02 - a33*b01)*invDet; - dest[7] = (a20*b05 - a22*b02 + a23*b01)*invDet; - dest[8] = (a10*b10 - a11*b08 + a13*b06)*invDet; - dest[9] = (-a00*b10 + a01*b08 - a03*b06)*invDet; - dest[10] = (a30*b04 - a31*b02 + a33*b00)*invDet; - dest[11] = (-a20*b04 + a21*b02 - a23*b00)*invDet; - dest[12] = (-a10*b09 + a11*b07 - a12*b06)*invDet; - dest[13] = (a00*b09 - a01*b07 + a02*b06)*invDet; - dest[14] = (-a30*b03 + a31*b01 - a32*b00)*invDet; - dest[15] = (a20*b03 - a21*b01 + a22*b00)*invDet; - - return dest; +/** + * Transpose the values of a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.transpose = function(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a01 = a[1], a02 = a[2], a03 = a[3], + a12 = a[6], a13 = a[7], + a23 = a[11]; + + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a01; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a02; + out[9] = a12; + out[11] = a[14]; + out[12] = a03; + out[13] = a13; + out[14] = a23; + } else { + out[0] = a[0]; + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a[1]; + out[5] = a[5]; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a[2]; + out[9] = a[6]; + out[10] = a[10]; + out[11] = a[14]; + out[12] = a[3]; + out[13] = a[7]; + out[14] = a[11]; + out[15] = a[15]; + } + + return out; }; -/* - * mat4.toRotationMat - * Copies the upper 3x3 elements of a mat4 into another mat4 - * - * Params: - * mat - mat4 containing values to copy - * dest - Optional, mat4 receiving copied values - * - * Returns: - * dest is specified, a new mat4 otherwise - */ -mat4.toRotationMat = function(mat, dest) { - if(!dest) { dest = mat4.create(); } - - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[3]; - dest[4] = mat[4]; - dest[5] = mat[5]; - dest[6] = mat[6]; - dest[7] = mat[7]; - dest[8] = mat[8]; - dest[9] = mat[9]; - dest[10] = mat[10]; - dest[11] = mat[11]; - dest[12] = 0; - dest[13] = 0; - dest[14] = 0; - dest[15] = 1; - - return dest; +/** + * Inverts a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.invert = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, + + // Calculate the determinant + det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; + out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; + out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; + out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; + out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; + out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; + out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; + + return out; }; -/* - * mat4.toMat3 - * Copies the upper 3x3 elements of a mat4 into a mat3 - * - * Params: - * mat - mat4 containing values to copy - * dest - Optional, mat3 receiving copied values - * - * Returns: - * dest is specified, a new mat3 otherwise - */ -mat4.toMat3 = function(mat, dest) { - if(!dest) { dest = mat3.create(); } - - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[4]; - dest[4] = mat[5]; - dest[5] = mat[6]; - dest[6] = mat[8]; - dest[7] = mat[9]; - dest[8] = mat[10]; - - return dest; +/** + * Calculates the adjugate of a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.adjoint = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; + + out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); + out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); + out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); + out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); + out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); + out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); + out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); + out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); + out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); + out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); + out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); + out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); + out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); + out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); + out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); + out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); + return out; }; -/* - * mat4.toInverseMat3 - * Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3 - * The resulting matrix is useful for calculating transformed normals - * - * Params: - * mat - mat4 containing values to invert and copy - * dest - Optional, mat3 receiving values - * - * Returns: - * dest is specified, a new mat3 otherwise - */ -mat4.toInverseMat3 = function(mat, dest) { - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2]; - var a10 = mat[4], a11 = mat[5], a12 = mat[6]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10]; - - var b01 = a22*a11-a12*a21; - var b11 = -a22*a10+a12*a20; - var b21 = a21*a10-a11*a20; - - var d = a00*b01 + a01*b11 + a02*b21; - if (!d) { return null; } - var id = 1/d; - - if(!dest) { dest = mat3.create(); } - - dest[0] = b01*id; - dest[1] = (-a22*a01 + a02*a21)*id; - dest[2] = (a12*a01 - a02*a11)*id; - dest[3] = b11*id; - dest[4] = (a22*a00 - a02*a20)*id; - dest[5] = (-a12*a00 + a02*a10)*id; - dest[6] = b21*id; - dest[7] = (-a21*a00 + a01*a20)*id; - dest[8] = (a11*a00 - a01*a10)*id; - - return dest; +/** + * Calculates the determinant of a mat4 + * + * @param {mat4} a the source matrix + * @returns {Number} determinant of a + */ +mat4.determinant = function (a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; }; -/* - * mat4.multiply - * Performs a matrix multiplication - * - * Params: - * mat - mat4, first operand - * mat2 - mat4, second operand - * dest - Optional, mat4 receiving operation result. If not specified result is written to mat - * - * Returns: - * dest if specified, mat otherwise - */ -mat4.multiply = function(mat, mat2, dest) { - if(!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3]; - var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7]; - var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11]; - var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15]; - - dest[0] = b00*a00 + b01*a10 + b02*a20 + b03*a30; - dest[1] = b00*a01 + b01*a11 + b02*a21 + b03*a31; - dest[2] = b00*a02 + b01*a12 + b02*a22 + b03*a32; - dest[3] = b00*a03 + b01*a13 + b02*a23 + b03*a33; - dest[4] = b10*a00 + b11*a10 + b12*a20 + b13*a30; - dest[5] = b10*a01 + b11*a11 + b12*a21 + b13*a31; - dest[6] = b10*a02 + b11*a12 + b12*a22 + b13*a32; - dest[7] = b10*a03 + b11*a13 + b12*a23 + b13*a33; - dest[8] = b20*a00 + b21*a10 + b22*a20 + b23*a30; - dest[9] = b20*a01 + b21*a11 + b22*a21 + b23*a31; - dest[10] = b20*a02 + b21*a12 + b22*a22 + b23*a32; - dest[11] = b20*a03 + b21*a13 + b22*a23 + b23*a33; - dest[12] = b30*a00 + b31*a10 + b32*a20 + b33*a30; - dest[13] = b30*a01 + b31*a11 + b32*a21 + b33*a31; - dest[14] = b30*a02 + b31*a12 + b32*a22 + b33*a32; - dest[15] = b30*a03 + b31*a13 + b32*a23 + b33*a33; - - return dest; +/** + * Multiplies two mat4's + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the first operand + * @param {mat4} b the second operand + * @returns {mat4} out + */ +mat4.multiply = function (out, a, b) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; + + // Cache only the current line of the second matrix + var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; + out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; + out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; + out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + return out; }; -/* - * mat4.multiplyVec3 - * Transforms a vec3 with the given matrix - * 4th vector component is implicitly '1' - * - * Params: - * mat - mat4 to transform the vector with - * vec - vec3 to transform - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec +/** + * Alias for {@link mat4.multiply} + * @function + */ +mat4.mul = mat4.multiply; + +/** + * Translate a mat4 by the given vector * - * Returns: - * dest if specified, vec otherwise + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to translate + * @param {vec3} v vector to translate by + * @returns {mat4} out */ -mat4.multiplyVec3 = function(mat, vec, dest) { - if(!dest) { dest = vec; } - - var x = vec[0], y = vec[1], z = vec[2]; - - dest[0] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12]; - dest[1] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13]; - dest[2] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14]; - - return dest; +mat4.translate = function (out, a, v) { + var x = v[0], y = v[1], z = v[2], + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23; + + if (a === out) { + out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; + out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; + out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; + out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; + } else { + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; + + out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; + out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; + out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; + + out[12] = a00 * x + a10 * y + a20 * z + a[12]; + out[13] = a01 * x + a11 * y + a21 * z + a[13]; + out[14] = a02 * x + a12 * y + a22 * z + a[14]; + out[15] = a03 * x + a13 * y + a23 * z + a[15]; + } + + return out; }; -/* - * mat4.multiplyVec4 - * Transforms a vec4 with the given matrix - * - * Params: - * mat - mat4 to transform the vector with - * vec - vec4 to transform - * dest - Optional, vec4 receiving operation result. If not specified result is written to vec - * - * Returns: - * dest if specified, vec otherwise - */ -mat4.multiplyVec4 = function(mat, vec, dest) { - if(!dest) { dest = vec; } - - var x = vec[0], y = vec[1], z = vec[2], w = vec[3]; - - dest[0] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12]*w; - dest[1] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13]*w; - dest[2] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14]*w; - dest[3] = mat[3]*x + mat[7]*y + mat[11]*z + mat[15]*w; - - return dest; +/** + * Scales the mat4 by the dimensions in the given vec3 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to scale + * @param {vec3} v the vec3 to scale the matrix by + * @returns {mat4} out + **/ +mat4.scale = function(out, a, v) { + var x = v[0], y = v[1], z = v[2]; + + out[0] = a[0] * x; + out[1] = a[1] * x; + out[2] = a[2] * x; + out[3] = a[3] * x; + out[4] = a[4] * y; + out[5] = a[5] * y; + out[6] = a[6] * y; + out[7] = a[7] * y; + out[8] = a[8] * z; + out[9] = a[9] * z; + out[10] = a[10] * z; + out[11] = a[11] * z; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; }; -/* - * mat4.translate - * Translates a matrix by the given vector - * - * Params: - * mat - mat4 to translate - * vec - vec3 specifying the translation - * dest - Optional, mat4 receiving operation result. If not specified result is written to mat - * - * Returns: - * dest if specified, mat otherwise - */ -mat4.translate = function(mat, vec, dest) { - var x = vec[0], y = vec[1], z = vec[2]; - - if(!dest || mat == dest) { - mat[12] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12]; - mat[13] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13]; - mat[14] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14]; - mat[15] = mat[3]*x + mat[7]*y + mat[11]*z + mat[15]; - return mat; - } - - var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; - - dest[0] = a00; - dest[1] = a01; - dest[2] = a02; - dest[3] = a03; - dest[4] = a10; - dest[5] = a11; - dest[6] = a12; - dest[7] = a13; - dest[8] = a20; - dest[9] = a21; - dest[10] = a22; - dest[11] = a23; - - dest[12] = a00*x + a10*y + a20*z + mat[12]; - dest[13] = a01*x + a11*y + a21*z + mat[13]; - dest[14] = a02*x + a12*y + a22*z + mat[14]; - dest[15] = a03*x + a13*y + a23*z + mat[15]; - return dest; +/** + * Rotates a mat4 by the given angle + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @param {vec3} axis the axis to rotate around + * @returns {mat4} out + */ +mat4.rotate = function (out, a, rad, axis) { + var x = axis[0], y = axis[1], z = axis[2], + len = Math.sqrt(x * x + y * y + z * z), + s, c, t, + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23, + b00, b01, b02, + b10, b11, b12, + b20, b21, b22; + + if (Math.abs(len) < GLMAT_EPSILON) { return null; } + + len = 1 / len; + x *= len; + y *= len; + z *= len; + + s = Math.sin(rad); + c = Math.cos(rad); + t = 1 - c; + + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; + + // Construct the elements of the rotation matrix + b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; + b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; + b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; + + // Perform rotation-specific matrix multiplication + out[0] = a00 * b00 + a10 * b01 + a20 * b02; + out[1] = a01 * b00 + a11 * b01 + a21 * b02; + out[2] = a02 * b00 + a12 * b01 + a22 * b02; + out[3] = a03 * b00 + a13 * b01 + a23 * b02; + out[4] = a00 * b10 + a10 * b11 + a20 * b12; + out[5] = a01 * b10 + a11 * b11 + a21 * b12; + out[6] = a02 * b10 + a12 * b11 + a22 * b12; + out[7] = a03 * b10 + a13 * b11 + a23 * b12; + out[8] = a00 * b20 + a10 * b21 + a20 * b22; + out[9] = a01 * b20 + a11 * b21 + a21 * b22; + out[10] = a02 * b20 + a12 * b21 + a22 * b22; + out[11] = a03 * b20 + a13 * b21 + a23 * b22; + + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + return out; }; -/* - * mat4.scale - * Scales a matrix by the given vector - * - * Params: - * mat - mat4 to scale - * vec - vec3 specifying the scale for each axis - * dest - Optional, mat4 receiving operation result. If not specified result is written to mat - * - * Returns: - * dest if specified, mat otherwise - */ -mat4.scale = function(mat, vec, dest) { - var x = vec[0], y = vec[1], z = vec[2]; - - if(!dest || mat == dest) { - mat[0] *= x; - mat[1] *= x; - mat[2] *= x; - mat[3] *= x; - mat[4] *= y; - mat[5] *= y; - mat[6] *= y; - mat[7] *= y; - mat[8] *= z; - mat[9] *= z; - mat[10] *= z; - mat[11] *= z; - return mat; - } - - dest[0] = mat[0]*x; - dest[1] = mat[1]*x; - dest[2] = mat[2]*x; - dest[3] = mat[3]*x; - dest[4] = mat[4]*y; - dest[5] = mat[5]*y; - dest[6] = mat[6]*y; - dest[7] = mat[7]*y; - dest[8] = mat[8]*z; - dest[9] = mat[9]*z; - dest[10] = mat[10]*z; - dest[11] = mat[11]*z; - dest[12] = mat[12]; - dest[13] = mat[13]; - dest[14] = mat[14]; - dest[15] = mat[15]; - return dest; +/** + * Rotates a matrix by the given angle around the X axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +mat4.rotateX = function (out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[4] = a10 * c + a20 * s; + out[5] = a11 * c + a21 * s; + out[6] = a12 * c + a22 * s; + out[7] = a13 * c + a23 * s; + out[8] = a20 * c - a10 * s; + out[9] = a21 * c - a11 * s; + out[10] = a22 * c - a12 * s; + out[11] = a23 * c - a13 * s; + return out; }; -/* - * mat4.rotate - * Rotates a matrix by the given angle around the specified axis - * If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance - * - * Params: - * mat - mat4 to rotate - * angle - angle (in radians) to rotate - * axis - vec3 representing the axis to rotate around - * dest - Optional, mat4 receiving operation result. If not specified result is written to mat - * - * Returns: - * dest if specified, mat otherwise - */ -mat4.rotate = function(mat, angle, axis, dest) { - var x = axis[0], y = axis[1], z = axis[2]; - var len = Math.sqrt(x*x + y*y + z*z); - if (!len) { return null; } - if (len != 1) { - len = 1 / len; - x *= len; - y *= len; - z *= len; - } - - var s = Math.sin(angle); - var c = Math.cos(angle); - var t = 1-c; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; - - // Construct the elements of the rotation matrix - var b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s; - var b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s; - var b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c; - - if(!dest) { - dest = mat; - } else if(mat != dest) { // If the source and destination differ, copy the unchanged last row - dest[12] = mat[12]; - dest[13] = mat[13]; - dest[14] = mat[14]; - dest[15] = mat[15]; - } - - // Perform rotation-specific matrix multiplication - dest[0] = a00*b00 + a10*b01 + a20*b02; - dest[1] = a01*b00 + a11*b01 + a21*b02; - dest[2] = a02*b00 + a12*b01 + a22*b02; - dest[3] = a03*b00 + a13*b01 + a23*b02; - - dest[4] = a00*b10 + a10*b11 + a20*b12; - dest[5] = a01*b10 + a11*b11 + a21*b12; - dest[6] = a02*b10 + a12*b11 + a22*b12; - dest[7] = a03*b10 + a13*b11 + a23*b12; - - dest[8] = a00*b20 + a10*b21 + a20*b22; - dest[9] = a01*b20 + a11*b21 + a21*b22; - dest[10] = a02*b20 + a12*b21 + a22*b22; - dest[11] = a03*b20 + a13*b21 + a23*b22; - return dest; +/** + * Rotates a matrix by the given angle around the Y axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +mat4.rotateY = function (out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[0] = a00 * c - a20 * s; + out[1] = a01 * c - a21 * s; + out[2] = a02 * c - a22 * s; + out[3] = a03 * c - a23 * s; + out[8] = a00 * s + a20 * c; + out[9] = a01 * s + a21 * c; + out[10] = a02 * s + a22 * c; + out[11] = a03 * s + a23 * c; + return out; }; -/* - * mat4.rotateX - * Rotates a matrix by the given angle around the X axis +/** + * Rotates a matrix by the given angle around the Z axis * - * Params: - * mat - mat4 to rotate - * angle - angle (in radians) to rotate - * dest - Optional, mat4 receiving operation result. If not specified result is written to mat - * - * Returns: - * dest if specified, mat otherwise - */ -mat4.rotateX = function(mat, angle, dest) { - var s = Math.sin(angle); - var c = Math.cos(angle); - - // Cache the matrix values (makes for huge speed increases!) - var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; - - if(!dest) { - dest = mat; - } else if(mat != dest) { // If the source and destination differ, copy the unchanged rows - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[3]; - - dest[12] = mat[12]; - dest[13] = mat[13]; - dest[14] = mat[14]; - dest[15] = mat[15]; - } - - // Perform axis-specific matrix multiplication - dest[4] = a10*c + a20*s; - dest[5] = a11*c + a21*s; - dest[6] = a12*c + a22*s; - dest[7] = a13*c + a23*s; - - dest[8] = a10*-s + a20*c; - dest[9] = a11*-s + a21*c; - dest[10] = a12*-s + a22*c; - dest[11] = a13*-s + a23*c; - return dest; + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +mat4.rotateZ = function (out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7]; + + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[0] = a00 * c + a10 * s; + out[1] = a01 * c + a11 * s; + out[2] = a02 * c + a12 * s; + out[3] = a03 * c + a13 * s; + out[4] = a10 * c - a00 * s; + out[5] = a11 * c - a01 * s; + out[6] = a12 * c - a02 * s; + out[7] = a13 * c - a03 * s; + return out; }; -/* - * mat4.rotateY - * Rotates a matrix by the given angle around the Y axis +/** + * Creates a matrix from a quaternion rotation and vector translation + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * var quatMat = mat4.create(); + * quat4.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); * - * Params: - * mat - mat4 to rotate - * angle - angle (in radians) to rotate - * dest - Optional, mat4 receiving operation result. If not specified result is written to mat - * - * Returns: - * dest if specified, mat otherwise - */ -mat4.rotateY = function(mat, angle, dest) { - var s = Math.sin(angle); - var c = Math.cos(angle); - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; - - if(!dest) { - dest = mat; - } else if(mat != dest) { // If the source and destination differ, copy the unchanged rows - dest[4] = mat[4]; - dest[5] = mat[5]; - dest[6] = mat[6]; - dest[7] = mat[7]; - - dest[12] = mat[12]; - dest[13] = mat[13]; - dest[14] = mat[14]; - dest[15] = mat[15]; - } - - // Perform axis-specific matrix multiplication - dest[0] = a00*c + a20*-s; - dest[1] = a01*c + a21*-s; - dest[2] = a02*c + a22*-s; - dest[3] = a03*c + a23*-s; - - dest[8] = a00*s + a20*c; - dest[9] = a01*s + a21*c; - dest[10] = a02*s + a22*c; - dest[11] = a03*s + a23*c; - return dest; + * @param {mat4} out mat4 receiving operation result + * @param {quat4} q Rotation quaternion + * @param {vec3} v Translation vector + * @returns {mat4} out + */ +mat4.fromRotationTranslation = function (out, q, v) { + // Quaternion math + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - (yy + zz); + out[1] = xy + wz; + out[2] = xz - wy; + out[3] = 0; + out[4] = xy - wz; + out[5] = 1 - (xx + zz); + out[6] = yz + wx; + out[7] = 0; + out[8] = xz + wy; + out[9] = yz - wx; + out[10] = 1 - (xx + yy); + out[11] = 0; + out[12] = v[0]; + out[13] = v[1]; + out[14] = v[2]; + out[15] = 1; + + return out; }; -/* - * mat4.rotateZ - * Rotates a matrix by the given angle around the Z axis - * - * Params: - * mat - mat4 to rotate - * angle - angle (in radians) to rotate - * dest - Optional, mat4 receiving operation result. If not specified result is written to mat - * - * Returns: - * dest if specified, mat otherwise - */ -mat4.rotateZ = function(mat, angle, dest) { - var s = Math.sin(angle); - var c = Math.cos(angle); - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; - var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; - - if(!dest) { - dest = mat; - } else if(mat != dest) { // If the source and destination differ, copy the unchanged last row - dest[8] = mat[8]; - dest[9] = mat[9]; - dest[10] = mat[10]; - dest[11] = mat[11]; - - dest[12] = mat[12]; - dest[13] = mat[13]; - dest[14] = mat[14]; - dest[15] = mat[15]; - } - - // Perform axis-specific matrix multiplication - dest[0] = a00*c + a10*s; - dest[1] = a01*c + a11*s; - dest[2] = a02*c + a12*s; - dest[3] = a03*c + a13*s; - - dest[4] = a00*-s + a10*c; - dest[5] = a01*-s + a11*c; - dest[6] = a02*-s + a12*c; - dest[7] = a03*-s + a13*c; - - return dest; +/** +* Calculates a 4x4 matrix from the given quaternion +* +* @param {mat4} out mat4 receiving operation result +* @param {quat} q Quaternion to create matrix from +* +* @returns {mat4} out +*/ +mat4.fromQuat = function (out, q) { + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - (yy + zz); + out[1] = xy + wz; + out[2] = xz - wy; + out[3] = 0; + + out[4] = xy - wz; + out[5] = 1 - (xx + zz); + out[6] = yz + wx; + out[7] = 0; + + out[8] = xz + wy; + out[9] = yz - wx; + out[10] = 1 - (xx + yy); + out[11] = 0; + + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + + return out; }; -/* - * mat4.frustum +/** * Generates a frustum matrix with the given bounds * - * Params: - * left, right - scalar, left and right bounds of the frustum - * bottom, top - scalar, bottom and top bounds of the frustum - * near, far - scalar, near and far bounds of the frustum - * dest - Optional, mat4 frustum matrix will be written into - * - * Returns: - * dest if specified, a new mat4 otherwise - */ -mat4.frustum = function(left, right, bottom, top, near, far, dest) { - if(!dest) { dest = mat4.create(); } - var rl = (right - left); - var tb = (top - bottom); - var fn = (far - near); - dest[0] = (near*2) / rl; - dest[1] = 0; - dest[2] = 0; - dest[3] = 0; - dest[4] = 0; - dest[5] = (near*2) / tb; - dest[6] = 0; - dest[7] = 0; - dest[8] = (right + left) / rl; - dest[9] = (top + bottom) / tb; - dest[10] = -(far + near) / fn; - dest[11] = -1; - dest[12] = 0; - dest[13] = 0; - dest[14] = -(far*near*2) / fn; - dest[15] = 0; - return dest; + * @param {mat4} out mat4 frustum matrix will be written into + * @param {Number} left Left bound of the frustum + * @param {Number} right Right bound of the frustum + * @param {Number} bottom Bottom bound of the frustum + * @param {Number} top Top bound of the frustum + * @param {Number} near Near bound of the frustum + * @param {Number} far Far bound of the frustum + * @returns {mat4} out + */ +mat4.frustum = function (out, left, right, bottom, top, near, far) { + var rl = 1 / (right - left), + tb = 1 / (top - bottom), + nf = 1 / (near - far); + out[0] = (near * 2) * rl; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = (near * 2) * tb; + out[6] = 0; + out[7] = 0; + out[8] = (right + left) * rl; + out[9] = (top + bottom) * tb; + out[10] = (far + near) * nf; + out[11] = -1; + out[12] = 0; + out[13] = 0; + out[14] = (far * near * 2) * nf; + out[15] = 0; + return out; }; -/* - * mat4.perspective +/** * Generates a perspective projection matrix with the given bounds * - * Params: - * fovy - scalar, vertical field of view - * aspect - scalar, aspect ratio. typically viewport width/height - * near, far - scalar, near and far bounds of the frustum - * dest - Optional, mat4 frustum matrix will be written into - * - * Returns: - * dest if specified, a new mat4 otherwise + * @param {mat4} out mat4 frustum matrix will be written into + * @param {number} fovy Vertical field of view in radians + * @param {number} aspect Aspect ratio. typically viewport width/height + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @returns {mat4} out */ -mat4.perspective = function(fovy, aspect, near, far, dest) { - var top = near*Math.tan(fovy*Math.PI / 360.0); - var right = top*aspect; - return mat4.frustum(-right, right, -top, top, near, far, dest); +mat4.perspective = function (out, fovy, aspect, near, far) { + var f = 1.0 / Math.tan(fovy / 2), + nf = 1 / (near - far); + out[0] = f / aspect; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = f; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = (far + near) * nf; + out[11] = -1; + out[12] = 0; + out[13] = 0; + out[14] = (2 * far * near) * nf; + out[15] = 0; + return out; }; -/* - * mat4.ortho +/** * Generates a orthogonal projection matrix with the given bounds * - * Params: - * left, right - scalar, left and right bounds of the frustum - * bottom, top - scalar, bottom and top bounds of the frustum - * near, far - scalar, near and far bounds of the frustum - * dest - Optional, mat4 frustum matrix will be written into - * - * Returns: - * dest if specified, a new mat4 otherwise - */ -mat4.ortho = function(left, right, bottom, top, near, far, dest) { - if(!dest) { dest = mat4.create(); } - var rl = (right - left); - var tb = (top - bottom); - var fn = (far - near); - dest[0] = 2 / rl; - dest[1] = 0; - dest[2] = 0; - dest[3] = 0; - dest[4] = 0; - dest[5] = 2 / tb; - dest[6] = 0; - dest[7] = 0; - dest[8] = 0; - dest[9] = 0; - dest[10] = -2 / fn; - dest[11] = 0; - dest[12] = -(left + right) / rl; - dest[13] = -(top + bottom) / tb; - dest[14] = -(far + near) / fn; - dest[15] = 1; - return dest; + * @param {mat4} out mat4 frustum matrix will be written into + * @param {number} left Left bound of the frustum + * @param {number} right Right bound of the frustum + * @param {number} bottom Bottom bound of the frustum + * @param {number} top Top bound of the frustum + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @returns {mat4} out + */ +mat4.ortho = function (out, left, right, bottom, top, near, far) { + var lr = 1 / (left - right), + bt = 1 / (bottom - top), + nf = 1 / (near - far); + out[0] = -2 * lr; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = -2 * bt; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 2 * nf; + out[11] = 0; + out[12] = (left + right) * lr; + out[13] = (top + bottom) * bt; + out[14] = (far + near) * nf; + out[15] = 1; + return out; }; -/* - * mat4.ortho +/** * Generates a look-at matrix with the given eye position, focal point, and up axis * - * Params: - * eye - vec3, position of the viewer - * center - vec3, point the viewer is looking at - * up - vec3 pointing "up" - * dest - Optional, mat4 frustum matrix will be written into - * - * Returns: - * dest if specified, a new mat4 otherwise - */ -mat4.lookAt = function(eye, center, up, dest) { - if(!dest) { dest = mat4.create(); } - - var eyex = eye[0], - eyey = eye[1], - eyez = eye[2], - upx = up[0], - upy = up[1], - upz = up[2], - centerx = center[0], - centery = center[1], - centerz = center[2]; - - if (eyex == centerx && eyey == centery && eyez == centerz) { - return mat4.identity(dest); - } - - var z0,z1,z2,x0,x1,x2,y0,y1,y2,len; - - //vec3.direction(eye, center, z); - z0 = eyex - center[0]; - z1 = eyey - center[1]; - z2 = eyez - center[2]; - - // normalize (no check needed for 0 because of early return) - len = 1/Math.sqrt(z0*z0 + z1*z1 + z2*z2); - z0 *= len; - z1 *= len; - z2 *= len; - - //vec3.normalize(vec3.cross(up, z, x)); - x0 = upy*z2 - upz*z1; - x1 = upz*z0 - upx*z2; - x2 = upx*z1 - upy*z0; - len = Math.sqrt(x0*x0 + x1*x1 + x2*x2); - if (!len) { - x0 = 0; - x1 = 0; - x2 = 0; - } else { - len = 1/len; - x0 *= len; - x1 *= len; - x2 *= len; - }; - - //vec3.normalize(vec3.cross(z, x, y)); - y0 = z1*x2 - z2*x1; - y1 = z2*x0 - z0*x2; - y2 = z0*x1 - z1*x0; - - len = Math.sqrt(y0*y0 + y1*y1 + y2*y2); - if (!len) { - y0 = 0; - y1 = 0; - y2 = 0; - } else { - len = 1/len; - y0 *= len; - y1 *= len; - y2 *= len; - } - - dest[0] = x0; - dest[1] = y0; - dest[2] = z0; - dest[3] = 0; - dest[4] = x1; - dest[5] = y1; - dest[6] = z1; - dest[7] = 0; - dest[8] = x2; - dest[9] = y2; - dest[10] = z2; - dest[11] = 0; - dest[12] = -(x0*eyex + x1*eyey + x2*eyez); - dest[13] = -(y0*eyex + y1*eyey + y2*eyez); - dest[14] = -(z0*eyex + z1*eyey + z2*eyez); - dest[15] = 1; - - return dest; + * @param {mat4} out mat4 frustum matrix will be written into + * @param {vec3} eye Position of the viewer + * @param {vec3} center Point the viewer is looking at + * @param {vec3} up vec3 pointing up + * @returns {mat4} out + */ +mat4.lookAt = function (out, eye, center, up) { + var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, + eyex = eye[0], + eyey = eye[1], + eyez = eye[2], + upx = up[0], + upy = up[1], + upz = up[2], + centerx = center[0], + centery = center[1], + centerz = center[2]; + + if (Math.abs(eyex - centerx) < GLMAT_EPSILON && + Math.abs(eyey - centery) < GLMAT_EPSILON && + Math.abs(eyez - centerz) < GLMAT_EPSILON) { + return mat4.identity(out); + } + + z0 = eyex - centerx; + z1 = eyey - centery; + z2 = eyez - centerz; + + len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); + z0 *= len; + z1 *= len; + z2 *= len; + + x0 = upy * z2 - upz * z1; + x1 = upz * z0 - upx * z2; + x2 = upx * z1 - upy * z0; + len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); + if (!len) { + x0 = 0; + x1 = 0; + x2 = 0; + } else { + len = 1 / len; + x0 *= len; + x1 *= len; + x2 *= len; + } + + y0 = z1 * x2 - z2 * x1; + y1 = z2 * x0 - z0 * x2; + y2 = z0 * x1 - z1 * x0; + + len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); + if (!len) { + y0 = 0; + y1 = 0; + y2 = 0; + } else { + len = 1 / len; + y0 *= len; + y1 *= len; + y2 *= len; + } + + out[0] = x0; + out[1] = y0; + out[2] = z0; + out[3] = 0; + out[4] = x1; + out[5] = y1; + out[6] = z1; + out[7] = 0; + out[8] = x2; + out[9] = y2; + out[10] = z2; + out[11] = 0; + out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); + out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); + out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); + out[15] = 1; + + return out; }; -/* - * mat4.str +/** * Returns a string representation of a mat4 * - * Params: - * mat - mat4 to represent as a string - * - * Returns: - * string representation of mat + * @param {mat4} mat matrix to represent as a string + * @returns {String} string representation of the matrix */ -mat4.str = function(mat) { - return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] + - ',\n '+ mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] + - ',\n '+ mat[8] + ', ' + mat[9] + ', ' + mat[10] + ', ' + mat[11] + - ',\n '+ mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']'; +mat4.str = function (a) { + return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + + a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + + a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')'; }; -/* - * quat4 - Quaternions +if(typeof(exports) !== 'undefined') { + exports.mat4 = mat4; +} +; +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/** + * @class Quaternion + * @name quat */ -quat4 = {}; -/* - * quat4.create - * Creates a new instance of a quat4 using the default array type - * Any javascript array containing at least 4 numeric elements can serve as a quat4 - * - * Params: - * quat - Optional, quat4 containing values to initialize with - * - * Returns: - * New quat4 - */ -quat4.create = function(quat) { - var dest; - - if(quat) { - dest = new glMatrixArrayType(4); - dest[0] = quat[0]; - dest[1] = quat[1]; - dest[2] = quat[2]; - dest[3] = quat[3]; - } else { - if(glMatrixArrayType === Array) - dest = new glMatrixArrayType([0,0,0,0]); - else - dest = new glMatrixArrayType(4); - } - - return dest; -}; +var quat = {}; -/* - * quat4.set - * Copies the values of one quat4 to another - * - * Params: - * quat - quat4 containing values to copy - * dest - quat4 receiving copied values +var quatIdentity = new Float32Array([0, 0, 0, 1]); + +/** + * Creates a new identity quat * - * Returns: - * dest + * @returns {quat} a new quaternion */ -quat4.set = function(quat, dest) { - dest[0] = quat[0]; - dest[1] = quat[1]; - dest[2] = quat[2]; - dest[3] = quat[3]; - - return dest; +quat.create = function() { + var out = new GLMAT_ARRAY_TYPE(4); + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; }; -/* - * quat4.calculateW - * Calculates the W component of a quat4 from the X, Y, and Z components. - * Assumes that quaternion is 1 unit in length. - * Any existing W component will be ignored. - * - * Params: - * quat - quat4 to calculate W component of - * dest - Optional, quat4 receiving calculated values. If not specified result is written to quat +/** + * Creates a new quat initialized with values from an existing quaternion * - * Returns: - * dest if specified, quat otherwise + * @param {quat} a quaternion to clone + * @returns {quat} a new quaternion + * @function */ -quat4.calculateW = function(quat, dest) { - var x = quat[0], y = quat[1], z = quat[2]; +quat.clone = vec4.clone; - if(!dest || quat == dest) { - quat[3] = -Math.sqrt(Math.abs(1.0 - x*x - y*y - z*z)); - return quat; - } - dest[0] = x; - dest[1] = y; - dest[2] = z; - dest[3] = -Math.sqrt(Math.abs(1.0 - x*x - y*y - z*z)); - return dest; -}; +/** + * Creates a new quat initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {quat} a new quaternion + * @function + */ +quat.fromValues = vec4.fromValues; -/* - * quat4.inverse - * Calculates the inverse of a quat4 - * - * Params: - * quat - quat4 to calculate inverse of - * dest - Optional, quat4 receiving inverse values. If not specified result is written to quat - * - * Returns: - * dest if specified, quat otherwise - */ -quat4.inverse = function(quat, dest) { - if(!dest || quat == dest) { - quat[0] *= -1; - quat[1] *= -1; - quat[2] *= -1; - return quat; - } - dest[0] = -quat[0]; - dest[1] = -quat[1]; - dest[2] = -quat[2]; - dest[3] = quat[3]; - return dest; -}; +/** + * Copy the values from one quat to another + * + * @param {quat} out the receiving quaternion + * @param {quat} a the source quaternion + * @returns {quat} out + * @function + */ +quat.copy = vec4.copy; -/* - * quat4.length - * Calculates the length of a quat4 +/** + * Set the components of a quat to the given values * - * Params: - * quat - quat4 to calculate length of + * @param {quat} out the receiving quaternion + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {quat} out + * @function + */ +quat.set = vec4.set; + +/** + * Set a quat to the identity quaternion * - * Returns: - * Length of quat + * @param {quat} out the receiving quaternion + * @returns {quat} out */ -quat4.length = function(quat) { - var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; - return Math.sqrt(x*x + y*y + z*z + w*w); +quat.identity = function(out) { + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; }; -/* - * quat4.normalize - * Generates a unit quaternion of the same direction as the provided quat4 - * If quaternion length is 0, returns [0, 0, 0, 0] - * - * Params: - * quat - quat4 to normalize - * dest - Optional, quat4 receiving operation result. If not specified result is written to quat - * - * Returns: - * dest if specified, quat otherwise - */ -quat4.normalize = function(quat, dest) { - if(!dest) { dest = quat; } - - var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; - var len = Math.sqrt(x*x + y*y + z*z + w*w); - if(len == 0) { - dest[0] = 0; - dest[1] = 0; - dest[2] = 0; - dest[3] = 0; - return dest; - } - len = 1/len; - dest[0] = x * len; - dest[1] = y * len; - dest[2] = z * len; - dest[3] = w * len; - - return dest; +/** + * Sets a quat from the given angle and rotation axis, + * then returns it. + * + * @param {quat} out the receiving quaternion + * @param {vec3} axis the axis around which to rotate + * @param {Number} rad the angle in radians + * @returns {quat} out + **/ +quat.setAxisAngle = function(out, axis, rad) { + rad = rad * 0.5; + var s = Math.sin(rad); + out[0] = s * axis[0]; + out[1] = s * axis[1]; + out[2] = s * axis[2]; + out[3] = Math.cos(rad); + return out; }; -/* - * quat4.multiply - * Performs a quaternion multiplication - * - * Params: - * quat - quat4, first operand - * quat2 - quat4, second operand - * dest - Optional, quat4 receiving operation result. If not specified result is written to quat - * - * Returns: - * dest if specified, quat otherwise - */ -quat4.multiply = function(quat, quat2, dest) { - if(!dest) { dest = quat; } - - var qax = quat[0], qay = quat[1], qaz = quat[2], qaw = quat[3]; - var qbx = quat2[0], qby = quat2[1], qbz = quat2[2], qbw = quat2[3]; - - dest[0] = qax*qbw + qaw*qbx + qay*qbz - qaz*qby; - dest[1] = qay*qbw + qaw*qby + qaz*qbx - qax*qbz; - dest[2] = qaz*qbw + qaw*qbz + qax*qby - qay*qbx; - dest[3] = qaw*qbw - qax*qbx - qay*qby - qaz*qbz; - - return dest; -}; +/** + * Adds two quat's + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @returns {quat} out + * @function + */ +quat.add = vec4.add; -/* - * quat4.multiplyVec3 - * Transforms a vec3 with the given quaternion - * - * Params: - * quat - quat4 to transform the vector with - * vec - vec3 to transform - * dest - Optional, vec3 receiving operation result. If not specified result is written to vec - * - * Returns: - * dest if specified, vec otherwise - */ -quat4.multiplyVec3 = function(quat, vec, dest) { - if(!dest) { dest = vec; } - - var x = vec[0], y = vec[1], z = vec[2]; - var qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3]; - - // calculate quat * vec - var ix = qw*x + qy*z - qz*y; - var iy = qw*y + qz*x - qx*z; - var iz = qw*z + qx*y - qy*x; - var iw = -qx*x - qy*y - qz*z; - - // calculate result * inverse quat - dest[0] = ix*qw + iw*-qx + iy*-qz - iz*-qy; - dest[1] = iy*qw + iw*-qy + iz*-qx - ix*-qz; - dest[2] = iz*qw + iw*-qz + ix*-qy - iy*-qx; - - return dest; +/** + * Multiplies two quat's + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @returns {quat} out + */ +quat.multiply = function(out, a, b) { + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = b[0], by = b[1], bz = b[2], bw = b[3]; + + out[0] = ax * bw + aw * bx + ay * bz - az * by; + out[1] = ay * bw + aw * by + az * bx - ax * bz; + out[2] = az * bw + aw * bz + ax * by - ay * bx; + out[3] = aw * bw - ax * bx - ay * by - az * bz; + return out; }; -/* - * quat4.toMat3 - * Calculates a 3x3 matrix from the given quat4 +/** + * Alias for {@link quat.multiply} + * @function + */ +quat.mul = quat.multiply; + +/** + * Scales a quat by a scalar number * - * Params: - * quat - quat4 to create matrix from - * dest - Optional, mat3 receiving operation result + * @param {quat} out the receiving vector + * @param {quat} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {quat} out + * @function + */ +quat.scale = vec4.scale; + +/** + * Rotates a quaternion by the given angle around the X axis * - * Returns: - * dest if specified, a new mat3 otherwise + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out */ -quat4.toMat3 = function(quat, dest) { - if(!dest) { dest = mat3.create(); } - - var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; +quat.rotateX = function (out, a, rad) { + rad *= 0.5; + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = Math.sin(rad), bw = Math.cos(rad); - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; + out[0] = ax * bw + aw * bx; + out[1] = ay * bw + az * bx; + out[2] = az * bw - ay * bx; + out[3] = aw * bw - ax * bx; + return out; +}; - var xx = x*x2; - var xy = x*y2; - var xz = x*z2; +/** + * Rotates a quaternion by the given angle around the Y axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ +quat.rotateY = function (out, a, rad) { + rad *= 0.5; - var yy = y*y2; - var yz = y*z2; - var zz = z*z2; + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + by = Math.sin(rad), bw = Math.cos(rad); - var wx = w*x2; - var wy = w*y2; - var wz = w*z2; + out[0] = ax * bw - az * by; + out[1] = ay * bw + aw * by; + out[2] = az * bw + ax * by; + out[3] = aw * bw - ay * by; + return out; +}; - dest[0] = 1 - (yy + zz); - dest[1] = xy - wz; - dest[2] = xz + wy; +/** + * Rotates a quaternion by the given angle around the Z axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ +quat.rotateZ = function (out, a, rad) { + rad *= 0.5; - dest[3] = xy + wz; - dest[4] = 1 - (xx + zz); - dest[5] = yz - wx; + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bz = Math.sin(rad), bw = Math.cos(rad); - dest[6] = xz - wy; - dest[7] = yz + wx; - dest[8] = 1 - (xx + yy); - - return dest; + out[0] = ax * bw + ay * bz; + out[1] = ay * bw - ax * bz; + out[2] = az * bw + aw * bz; + out[3] = aw * bw - az * bz; + return out; }; -/* - * quat4.toMat4 - * Calculates a 4x4 matrix from the given quat4 - * - * Params: - * quat - quat4 to create matrix from - * dest - Optional, mat4 receiving operation result +/** + * Calculates the W component of a quat from the X, Y, and Z components. + * Assumes that quaternion is 1 unit in length. + * Any existing W component will be ignored. * - * Returns: - * dest if specified, a new mat4 otherwise + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate W component of + * @returns {quat} out */ -quat4.toMat4 = function(quat, dest) { - if(!dest) { dest = mat4.create(); } - - var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; +quat.calculateW = function (out, a) { + var x = a[0], y = a[1], z = a[2]; + + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); + return out; +}; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; +/** + * Calculates the dot product of two quat's + * + * @param {quat} a the first operand + * @param {quat} b the second operand + * @returns {Number} dot product of a and b + * @function + */ +quat.dot = vec4.dot; - var xx = x*x2; - var xy = x*y2; - var xz = x*z2; +/** + * Performs a linear interpolation between two quat's + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {quat} out + * @function + */ +quat.lerp = vec4.lerp; - var yy = y*y2; - var yz = y*z2; - var zz = z*z2; +/** + * Performs a spherical linear interpolation between two quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {quat} out + */ +quat.slerp = function (out, a, b, t) { + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = b[0], by = b[1], bz = b[2], bw = b[3]; + + var cosHalfTheta = ax * bx + ay * by + az * bz + aw * bw, + halfTheta, + sinHalfTheta, + ratioA, + ratioB; + + if (Math.abs(cosHalfTheta) >= 1.0) { + if (out !== a) { + out[0] = ax; + out[1] = ay; + out[2] = az; + out[3] = aw; + } + return out; + } - var wx = w*x2; - var wy = w*y2; - var wz = w*z2; + halfTheta = Math.acos(cosHalfTheta); + sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); - dest[0] = 1 - (yy + zz); - dest[1] = xy - wz; - dest[2] = xz + wy; - dest[3] = 0; + if (Math.abs(sinHalfTheta) < 0.001) { + out[0] = (ax * 0.5 + bx * 0.5); + out[1] = (ay * 0.5 + by * 0.5); + out[2] = (az * 0.5 + bz * 0.5); + out[3] = (aw * 0.5 + bw * 0.5); + return out; + } - dest[4] = xy + wz; - dest[5] = 1 - (xx + zz); - dest[6] = yz - wx; - dest[7] = 0; + ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta; + ratioB = Math.sin(t * halfTheta) / sinHalfTheta; - dest[8] = xz - wy; - dest[9] = yz + wx; - dest[10] = 1 - (xx + yy); - dest[11] = 0; + out[0] = (ax * ratioA + bx * ratioB); + out[1] = (ay * ratioA + by * ratioB); + out[2] = (az * ratioA + bz * ratioB); + out[3] = (aw * ratioA + bw * ratioB); - dest[12] = 0; - dest[13] = 0; - dest[14] = 0; - dest[15] = 1; - - return dest; + return out; }; -/* - * quat4.slerp - * Performs a spherical linear interpolation between two quat4 - * - * Params: - * quat - quat4, first quaternion - * quat2 - quat4, second quaternion - * slerp - interpolation amount between the two inputs - * dest - Optional, quat4 receiving operation result. If not specified result is written to quat +/** + * Calculates the inverse of a quat * - * Returns: - * dest if specified, quat otherwise + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate inverse of + * @returns {quat} out */ -quat4.slerp = function(quat, quat2, slerp, dest) { - if(!dest) { dest = quat; } +quat.invert = function(out, a) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + dot = a0*a0 + a1*a1 + a2*a2 + a3*a3, + invDot = dot ? 1.0/dot : 0; - var cosHalfTheta = quat[0]*quat2[0] + quat[1]*quat2[1] + quat[2]*quat2[2] + quat[3]*quat2[3]; - - if (Math.abs(cosHalfTheta) >= 1.0){ - if(dest != quat) { - dest[0] = quat[0]; - dest[1] = quat[1]; - dest[2] = quat[2]; - dest[3] = quat[3]; - } - return dest; - } - - var halfTheta = Math.acos(cosHalfTheta); - var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta*cosHalfTheta); - - if (Math.abs(sinHalfTheta) < 0.001){ - dest[0] = (quat[0]*0.5 + quat2[0]*0.5); - dest[1] = (quat[1]*0.5 + quat2[1]*0.5); - dest[2] = (quat[2]*0.5 + quat2[2]*0.5); - dest[3] = (quat[3]*0.5 + quat2[3]*0.5); - return dest; - } - - var ratioA = Math.sin((1 - slerp)*halfTheta) / sinHalfTheta; - var ratioB = Math.sin(slerp*halfTheta) / sinHalfTheta; - - dest[0] = (quat[0]*ratioA + quat2[0]*ratioB); - dest[1] = (quat[1]*ratioA + quat2[1]*ratioB); - dest[2] = (quat[2]*ratioA + quat2[2]*ratioB); - dest[3] = (quat[3]*ratioA + quat2[3]*ratioB); - - return dest; + // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 + + out[0] = -a0*invDot; + out[1] = -a1*invDot; + out[2] = -a2*invDot; + out[3] = a3*invDot; + return out; }; +/** + * Calculates the conjugate of a quat + * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. + * + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate conjugate of + * @returns {quat} out + */ +quat.conjugate = function (out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = a[3]; + return out; +}; -/* - * quat4.str - * Returns a string representation of a quaternion +/** + * Calculates the length of a quat * - * Params: - * quat - quat4 to represent as a string + * @param {quat} a vector to calculate length of + * @returns {Number} length of a + * @function + */ +quat.length = vec4.length; + +/** + * Alias for {@link quat.length} + * @function + */ +quat.len = quat.length; + +/** + * Calculates the squared length of a quat * - * Returns: - * string representation of quat + * @param {quat} a vector to calculate squared length of + * @returns {Number} squared length of a + * @function */ -quat4.str = function(quat) { - return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']'; -}; +quat.squaredLength = vec4.squaredLength; +/** + * Alias for {@link quat.squaredLength} + * @function + */ +quat.sqrLen = quat.squaredLength; -define("glMatrix", ["typedefs"], (function (global) { - return function () { - var ret, fn; - return ret || global.glMatrix; +/** + * Normalize a quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a quaternion to normalize + * @returns {quat} out + * @function + */ +quat.normalize = vec4.normalize; + +/** + * Creates a quaternion from the given 3x3 rotation matrix. + * + * @param {quat} out the receiving quaternion + * @param {mat3} m rotation matrix + * @returns {quat} out + * @function + */ +quat.fromMat3 = (function() { + var s_iNext = [1,2,0]; + return function(out, m) { + // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + // article "Quaternion Calculus and Fast Animation". + var fTrace = m[0] + m[4] + m[8]; + var fRoot; + + if ( fTrace > 0.0 ) { + // |w| > 1/2, may as well choose w > 1/2 + fRoot = Math.sqrt(fTrace + 1.0); // 2w + out[3] = 0.5 * fRoot; + fRoot = 0.5/fRoot; // 1/(4w) + out[0] = (m[7]-m[5])*fRoot; + out[1] = (m[2]-m[6])*fRoot; + out[2] = (m[3]-m[1])*fRoot; + } else { + // |w| <= 1/2 + var i = 0; + if ( m[4] > m[0] ) + i = 1; + if ( m[8] > m[i*3+i] ) + i = 2; + var j = s_iNext[i]; + var k = s_iNext[j]; + + fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0); + out[i] = 0.5 * fRoot; + fRoot = 0.5 / fRoot; + out[3] = (m[k*3+j] - m[j*3+k]) * fRoot; + out[j] = (m[j*3+i] + m[i*3+j]) * fRoot; + out[k] = (m[k*3+i] + m[i*3+k]) * fRoot; + } + + return out; }; -}(this))); +})(); -/* - * glMatrixAddon.js - * Extension to the glMatrix library. The original glMatrix library - * was created by Brandon Jones. - */ - - -mat4.xVec4 = function(mat, vec, dest){ - if(!dest) { dest = vec; } - var x = vec[0], y = vec[1], z = vec[2], w = vec[3]; - - dest[0] = mat[0]*x + mat[1]*y + mat[2]*z + mat[3]*w; - dest[1] = mat[4]*x + mat[5]*y + mat[6]*z + mat[7]*w; - dest[2] = mat[8]*x + mat[9]*y + mat[10]*z + mat[11]*w; - dest[3] = mat[12]*x + mat[13]*y + mat[14]*z + mat[15]*w; - - return dest; -}; - -mat3.scale = function(mat, scalar, dest){ - if(!dest || mat == dest) { - mat[0] *= scalar; - mat[1] *= scalar; - mat[2] *= scalar; - mat[3] *= scalar; - mat[4] *= scalar; - mat[5] *= scalar; - mat[6] *= scalar; - mat[7] *= scalar; - mat[8] *= scalar; - return mat; - } - dest = mat3.create(); - dest[0] = mat[0]*scalar; - dest[1] = mat[1]*scalar; - dest[2] = mat[2]*scalar; - dest[3] = mat[3]*scalar; - dest[4] = mat[4]*scalar; - dest[5] = mat[5]*scalar; - dest[6] = mat[6]*scalar; - dest[7] = mat[7]*scalar; - dest[8] = mat[8]*scalar; - return dest; -}; - -mat3.inverse = function(mat, dest){ - if(!dest) { dest = mat; } - - var ha00 = mat[0], ha01 = mat[1], ha02 = mat[2]; - var ha10 = mat[3], ha11 = mat[4], ha12 = mat[5]; - var ha20 = mat[6], ha21 = mat[7], ha22 = mat[8]; - - var invDetA = 1/(ha00*ha11*ha22 + ha01*ha12*ha20 + ha02*ha10*ha21 - ha02*ha11*ha20 - ha01*ha10*ha22 - ha00*ha12*ha21); - dest[0] = (ha11*ha22 - ha12*ha21)*invDetA; - dest[1] = (ha02*ha21 - ha01*ha22)*invDetA; - dest[2] = (ha01*ha12 - ha02*ha11)*invDetA; - dest[3] = (ha12*ha20 - ha10*ha22)*invDetA; - dest[4] = (ha00*ha22 - ha02*ha20)*invDetA; - dest[5] = (ha02*ha10 - ha00*ha12)*invDetA; - dest[6] = (ha10*ha21 - ha11*ha20)*invDetA; - dest[7] = (ha01*ha20 - ha00*ha21)*invDetA; - dest[8] = (ha00*ha11 - ha01*ha10)*invDetA; - return dest; -}; - -mat3.multiply = function(mat, mat2, dest) { - if(!dest) { dest = mat; } - - var ha00 = mat[0], ha01 = mat[1], ha02 = mat[2]; - var ha10 = mat[3], ha11 = mat[4], ha12 = mat[5]; - var ha20 = mat[6], ha21 = mat[7], ha22 = mat[8]; - - var hb00 = mat2[0], hb01 = mat2[1], hb02 = mat2[2]; - var hb10 = mat2[3], hb11 = mat2[4], hb12 = mat2[5]; - var hb20 = mat2[6], hb21 = mat2[7], hb22 = mat2[8]; - - dest[0] = ha00*hb00 + ha01*hb10 + ha02*hb20; - dest[1] = ha00*hb01 + ha01*hb11 + ha02*hb21; - dest[2] = ha00*hb02 + ha01*hb12 + ha02*hb22; - - dest[3] = ha10*hb00 + ha11*hb10 + ha12*hb20; - dest[4] = ha10*hb01 + ha11*hb11 + ha12*hb21; - dest[5] = ha10*hb02 + ha11*hb12 + ha12*hb22; - - dest[6] = ha20*hb00 + ha21*hb10 + ha22*hb20; - dest[7] = ha20*hb01 + ha21*hb11 + ha22*hb21; - dest[8] = ha20*hb02 + ha21*hb12 + ha22*hb22; - return dest; -}; - -mat3.xVec3 = function(mat, vec, dest){ - if(!dest) { dest = vec; } - var x = vec[0], y = vec[1], z = vec[2]; - - dest[0] = mat[0]*x + mat[1]*y + mat[2]*z; - dest[1] = mat[3]*x + mat[4]*y + mat[5]*z; - dest[2] = mat[6]*x + mat[7]*y + mat[8]*z; - - return dest; -}; - -var vec4={}; - -vec4.create = function(vec){ - var dest; - - if(vec) { - dest = new glMatrixArrayType(4); - dest[0] = vec[0]; - dest[1] = vec[1]; - dest[2] = vec[2]; - dest[3] = vec[3]; - } else { - if(glMatrixArrayType === Array) - dest = new glMatrixArrayType([0,0,0,0]); - else - dest = new glMatrixArrayType(4); - } - - return dest; -}; - -vec4.project = function(vec, dest){ - if(!dest) { dest = vec; } - - dest[0] = vec[0]/vec[3]; - dest[1] = vec[1]/vec[3]; - dest[2] = vec[2]/vec[3]; - return dest; -}; - -vec4.scale = function(vec, val, dest){ - if(!dest || vec == dest) { - vec[0] *= val; - vec[1] *= val; - vec[2] *= val; - vec[4] *= val; - return vec; - } - - dest[0] = vec[0]*val; - dest[1] = vec[1]*val; - dest[2] = vec[2]*val; - dest[3] = vec[3]*val; - return dest; -}; - -vec4.xMat4 = function(vec, mat, dest){ - if(!dest) { dest = vec; } - - var x = vec[0], y = vec[1], z = vec[2], w = vec[3]; - - dest[0] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12]*w; - dest[1] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13]*w; - dest[2] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14]*w; - dest[3] = mat[3]*x + mat[7]*y + mat[11]*z + mat[15]*w; - - return dest; +/** + * Returns a string representation of a quatenion + * + * @param {quat} vec vector to represent as a string + * @returns {String} string representation of the vector + */ +quat.str = function (a) { + return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; +if(typeof(exports) !== 'undefined') { + exports.quat = quat; +} +; -var mat2 = {}; -mat2.create = function(mat){ - var dest; - - if(mat) { - dest = new glMatrixArrayType(4); - dest[0] = mat[0]; - dest[1] = mat[1]; - dest[2] = mat[2]; - dest[3] = mat[3]; - } else { - if(glMatrixArrayType === Array) - dest = new glMatrixArrayType([0,0,0,0]); - else - dest = new glMatrixArrayType(4); - } - - return dest; -}; - -mat2.xVec2 = function(mat, vec, dest){ - if(!dest) { dest = vec; } - var x = vec[0], y = vec[1]; - - dest[0] = mat[0]*x + mat[1]*y; - dest[1] = mat[2]*x + mat[3]*y; - - return dest; -}; - -mat2.scale = function(mat, scale, dest){ - if(!dest || mat == dest) { - mat[0] *= scale; - mat[1] *= scale; - mat[2] *= scale; - mat[3] *= scale; - return mat; - } - - dest[0] = mat[0]*scale; - dest[1] = mat[1]*scale; - dest[2] = mat[2]*scale; - dest[3] = mat[3]*scale; - return dest; -}; - -mat2.determinant = function(mat){ - return mat[0]*mat[3] - mat[1]*mat[2]; -}; - -mat2.inverse = function(mat){ - var scale = 1/(mat2.determinant(mat)); - var a = mat[3]*scale, - b = -mat[1]*scale, - c = -mat[2]*scale, - d = mat[0]; - mat[0] = a; - mat[1] = b; - mat[2] = c; - mat[3] = d; - return mat; -}; -var vec2 = {}; -vec2.create = function(vec){ - var dest; - - if(vec) { - dest = new glMatrixArrayType(2); - dest[0] = vec[0]; - dest[1] = vec[1]; - } else { - if(glMatrixArrayType === Array) - dest = new glMatrixArrayType([0,0]); - else - dest = new glMatrixArrayType(2); - } - - return dest; -}; - -vec2.subtract = function(vec, vec2, dest) { - if(!dest || vec == dest) { - vec[0] -= vec2[0]; - vec[1] -= vec2[1]; - return vec; - } - - dest[0] = vec[0] - vec2[0]; - dest[1] = vec[1] - vec2[1]; - return dest; -}; - -vec2.add = function(vec, vec2, dest) { - if(!dest || vec == dest) { - vec[0] += vec2[0]; - vec[1] += vec2[1]; - return vec; - } - - dest[0] = vec[0] + vec2[0]; - dest[1] = vec[1] + vec2[1]; - return dest; -}; - -vec2.scale = function(vec, val, dest) { - if(!dest || vec == dest) { - vec[0] *= val; - vec[1] *= val; - return vec; - } - - dest[0] = vec[0]*val; - dest[1] = vec[1]*val; - return dest; -}; - -vec2.normalize = function(vec, dest) { - if(!dest) { dest = vec; } - - var x = vec[0], y = vec[1]; - var len = Math.sqrt(x*x + y*y); - - if (!len) { - dest[0] = 0; - dest[1] = 0; - return dest; - } else if (len == 1) { - dest[0] = x; - dest[1] = y; - return dest; - } - - len = 1 / len; - dest[0] = x*len; - dest[1] = y*len; - return dest; -}; -vec2.dot = function(vec, vec2){ - return vec[0]*vec2[0] + vec[1]*vec2[1]; -}; -vec2.multiply = function(vec, vec2, dest){ - if(!dest) { dest = vec; } - - dest[0] = vec[0]*vec2[0]; - dest[1] = vec[1]*vec2[1]; - return dest; -}; - -/** - * @param vec vec2 to be unprojected [x,y] -> [x,y,1] - * @returns vec3 unprojected vector - */ -vec2.unproject = function(vec){ - return vec3.create([vec[0], vec[1], 1]); -}; - -vec2.length = function(vec){ - return Math.sqrt(vec[0]*vec[0] + vec[1]*vec[1]); -}; - -vec2.perspectiveProject = function(vec){ - var result = vec2.create(vec); - return vec2.scale(result, 1/vec[2]); -}; - -/** - * @param vec vec3 to be projected [x,y,z] -> [x/z,y/z] - * @returns vec2 projected vector - */ -vec3.project = function(vec){ - return vec2.scale(vec2.create(vec), 1/vec[2]); -}; - -var vec6 = {}; -vec6.scale = function(vec, val, dest){ - if(!dest || vec == dest) { - vec[0] *= val; - vec[1] *= val; - vec[2] *= val; - vec[3] *= val; - vec[4] *= val; - vec[5] *= val; - return vec; - } - - dest[0] = vec[0]*val; - dest[1] = vec[1]*val; - dest[2] = vec[2]*val; - dest[3] = vec[3]*val; - dest[4] = vec[4]*val; - dest[5] = vec[5]*val; - return dest; -}; - -vec6.subtract = function(vec, vec2, dest){ - if(!dest || vec == dest) { - vec[0] -= vec2[0]; - vec[1] -= vec2[1]; - vec[2] -= vec2[2]; - vec[3] -= vec2[3]; - vec[4] -= vec2[4]; - vec[5] -= vec2[5]; - return vec; - } - - dest[0] = vec[0] - vec2[0]; - dest[1] = vec[1] - vec2[1]; - dest[2] = vec[2] - vec2[2]; - dest[3] = vec[3] - vec2[3]; - dest[4] = vec[4] - vec2[4]; - dest[5] = vec[5] - vec2[5]; - return dest; -}; - -vec6.dot = function(vec, vec2){ - return vec[0]*vec2[0] + vec[1]*vec2[1] + vec[2]*vec2[2] + vec[3]*vec2[3] + vec[4]*vec2[4] + vec[5]*vec2[5]; -}; - -var mat6 = {}; -mat6.xVec6 = function(mat, vec, dest){ - if(!dest) { dest = vec; } - var x = vec[0], y = vec[1], z = vec[2], u = vec[3], w = vec[4], v = vec[5]; - - dest[0] = mat[0]*x + mat[1]*y + mat[2]*z + mat[3]*u + mat[4]*w + mat[5]*v; - dest[1] = mat[6]*x + mat[7]*y + mat[8]*z + mat[9]*u + mat[10]*w + mat[11]*v; - dest[2] = mat[12]*x + mat[13]*y + mat[14]*z + mat[15]*u + mat[16]*w + mat[17]*v; - dest[3] = mat[18]*x + mat[19]*y + mat[20]*z + mat[21]*u + mat[22]*w + mat[23]*v; - dest[4] = mat[24]*x + mat[25]*y + mat[26]*z + mat[27]*u + mat[28]*w + mat[29]*v; - dest[5] = mat[30]*x + mat[31]*y + mat[32]*z + mat[33]*u + mat[34]*w + mat[35]*v; - - return dest; -}; - -mat3.xVec3 = function(mat, vec, dest){ - if(!dest) { dest = vec; } - var x = vec[0], y = vec[1], z = vec[2]; - - dest[0] = mat[0]*x + mat[1]*y + mat[2]*z; - dest[1] = mat[3]*x + mat[4]*y + mat[5]*z; - dest[2] = mat[6]*x + mat[7]*y + mat[8]*z; - - return dest; -}; -define("glMatrixAddon", ["glMatrix"], (function (global) { - return function () { - var ret, fn; - return ret || global.glMatrixAddon; + + + + + + + + + })(shim.exports); +})(); + +/* jshint undef: true, unused: true, browser:true, devel: true */ +/* global define */ + +define('cluster',["gl-matrix"], function(glMatrix) { + + + var vec2 = glMatrix.vec2; + /** + * Creates a cluster for grouping similar orientations of datapoints + */ + var Cluster = { + create : function(point, threshold) { + var points = [], center = { + rad : 0, + vec : vec2.clone([0, 0]) + }, pointMap = {}; + + function init() { + add(point); + updateCenter(); + } + + function add(point) { + pointMap[point.id] = point; + points.push(point); + } + + function updateCenter() { + var i, sum = 0; + for ( i = 0; i < points.length; i++) { + sum += points[i].rad; + } + center.rad = sum / points.length; + center.vec = vec2.clone([Math.cos(center.rad), Math.sin(center.rad)]); + } + + init(); + + return { + add : function(point) { + if (!pointMap[point.id]) { + add(point); + updateCenter(); + } + }, + fits : function(point) { + // check cosine similarity to center-angle + var similarity = Math.abs(vec2.dot(point.point.vec, center.vec)); + if (similarity > threshold) { + return true; + } + return false; + }, + getPoints : function() { + return points; + }, + getCenter : function() { + return center; + } + }; + }, + createPoint : function(point, id, property) { + return { + rad : point[property], + point : point, + id : id + }; + } }; -}(this))); + + return (Cluster); +}); /* jshint undef: true, unused: true, browser:true, devel: true */ /* global define */ @@ -4307,9 +5907,9 @@ define('array_helper',[],function() { }; }); /* jshint undef: true, unused: true, browser:true, devel: true */ -/* global define, vec2, vec3 */ +/* global define */ -define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrixAddon, ArrayHelper) { +define('cv_utils',['cluster', "array_helper", "gl-matrix"], function(Cluster2, ArrayHelper, glMatrix) { /* @@ -4322,7 +5922,9 @@ define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster * @class Represents a collection of useful CV algorithms/functions */ - var CVUtils = {}; + var CVUtils = {}, + vec2 = glMatrix.vec2, + vec3 = glMatrix.vec3; /** * @param x x-coordinate @@ -4334,10 +5936,10 @@ define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster x : x, y : y, toVec2 : function() { - return vec2.create([this.x, this.y]); + return vec2.clone([this.x, this.y]); }, toVec3 : function() { - return vec3.create([this.x, this.y, 1]); + return vec3.clone([this.x, this.y, 1]); }, round : function() { this.x = this.x > 0.0 ? Math.floor(this.x + 0.5) : Math.floor(this.x - 0.5); @@ -4976,16 +6578,19 @@ define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster /* jshint undef: true, unused: true, browser:true, devel: true */ -/* global define, vec2, mat2 */ +/* global define */ define('image_wrapper',[ "subImage", "cv_utils", - "array_helper" + "array_helper", + "gl-matrix" ], - function(SubImage, CVUtils, ArrayHelper) { + function(SubImage, CVUtils, ArrayHelper, glMatrix) { + var vec2 = glMatrix.vec2, + mat2 = glMatrix.mat2; /** * Represents a basic image combining the data and size. @@ -5039,11 +6644,11 @@ define('image_wrapper',[ */ ImageWrapper.transform = function(inImg, outImg, M, inOrig, outOrig) { var w = outImg.size.x, h = outImg.size.y, iw = inImg.size.x, ih = inImg.size.y; - var across = vec2.create([M[0], M[2]]); - var down = vec2.create([M[1], M[3]]); + var across = vec2.clone([M[0], M[2]]); + var down = vec2.clone([M[1], M[3]]); var defaultValue = 0; - var p0 = vec2.subtract(inOrig, mat2.xVec2(M, outOrig, vec2.create()), vec2.create()); + var p0 = vec2.subtract(inOrig, mat2.xVec2(M, outOrig, vec2.clone()), vec2.clone()); var min_x = p0[0], min_y = p0[1]; var max_x = min_x, max_y = min_y; @@ -5071,7 +6676,7 @@ define('image_wrapper',[ else max_y += h * down[1]; - var carrigeReturn = vec2.subtract(down, vec2.scale(across, w, vec2.create()), vec2.create()); + var carrigeReturn = vec2.subtract(down, vec2.scale(across, w, vec2.clone()), vec2.clone()); if (min_x >= 0 && min_y >= 0 && max_x < iw - 1 && max_y < ih - 1) { p = p0; @@ -5323,7 +6928,7 @@ define('image_wrapper',[ label.theta += 180; } label.rad = tmp > PI ? tmp - PI : tmp; - label.vec = vec2.create([Math.cos(tmp), Math.sin(tmp)]); + label.vec = vec2.clone([Math.cos(tmp), Math.sin(tmp)]); result.push(label); } } @@ -5713,6 +7318,16 @@ define('rasterizer',["tracer"], function(Tracer) { define('skeletonizer',[],function() { + Math.imul = Math.imul || function(a, b) { + var ah = (a >>> 16) & 0xffff; + var al = a & 0xffff; + var bh = (b >>> 16) & 0xffff; + var bl = b & 0xffff; + // the shift by 0 fixes the sign on the high part + // the final |0 converts the unsigned value into a signed value + return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0); + }; + /* @preserve ASM BEGIN */ function Skeletonizer(stdlib, foreign, buffer) { "use asm"; @@ -5943,10 +7558,10 @@ define('image_debug',[],function() { }); /* jshint undef: true, unused: true, browser:true, devel: true */ -/* global define, mat2, vec2 */ +/* global define */ -define("barcode_locator", ["image_wrapper", "cv_utils", "rasterizer", "tracer", "skeletonizer", "array_helper", "image_debug"], -function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, ImageDebug) { +define("barcode_locator", ["image_wrapper", "cv_utils", "rasterizer", "tracer", "skeletonizer", "array_helper", "image_debug", "gl-matrix"], +function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, ImageDebug, glMatrix) { var _config, _currentImageWrapper, @@ -5969,6 +7584,8 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I _numPatches = {x: 0, y: 0}, _inputImageWrapper, _skeletonizer, + vec2 = glMatrix.vec2, + mat2 = glMatrix.mat2, self = this; function initBuffers() { @@ -6044,15 +7661,14 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I overAvg += 180; } - //console.log(overAvg); overAvg = (180 - overAvg) * Math.PI / 180; - transMat = mat2.create([Math.cos(overAvg), -Math.sin(overAvg), Math.sin(overAvg), Math.cos(overAvg)]); + transMat = mat2.clone([Math.cos(overAvg), Math.sin(overAvg), -Math.sin(overAvg), Math.cos(overAvg)]); // iterate over patches and rotate by angle for ( i = 0; i < patches.length; i++) { patch = patches[i]; for ( j = 0; j < 4; j++) { - mat2.xVec2(transMat, patch.box[j]); + vec2.transformMat2(patch.box[j], patch.box[j], transMat); } if (_config.boxFromPatches.showTransformed) { @@ -6087,9 +7703,9 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I scale = _config.halfSample ? 2 : 1; // reverse rotation; - transMat = mat2.inverse(transMat); + transMat = mat2.invert(transMat, transMat); for ( j = 0; j < 4; j++) { - mat2.xVec2(transMat, box[j]); + vec2.transformMat2(box[j], box[j], transMat); } if (_config.boxFromPatches.showBB) { @@ -6097,7 +7713,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I } for ( j = 0; j < 4; j++) { - vec2.scale(box[j], scale); + vec2.scale(box[j], box[j], scale); } return box; @@ -6321,10 +7937,10 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I x : x, y : y }, - box : [vec2.create([x, y]), vec2.create([x + _subImageWrapper.size.x, y]), vec2.create([x + _subImageWrapper.size.x, y + _subImageWrapper.size.y]), vec2.create([x, y + _subImageWrapper.size.y])], + box : [vec2.clone([x, y]), vec2.clone([x + _subImageWrapper.size.x, y]), vec2.clone([x + _subImageWrapper.size.x, y + _subImageWrapper.size.y]), vec2.clone([x, y + _subImageWrapper.size.y])], moments : matchingMoments, rad : avg, - vec : vec2.create([Math.cos(avg), Math.sin(avg)]) + vec : vec2.clone([Math.cos(avg), Math.sin(avg)]) }; patchesFound.push(patch); } @@ -8158,7 +9774,7 @@ define('camera_access',["html_utils"], function(HtmlUtils) { }); /* jshint undef: true, unused: true, browser:true, devel: true, evil: true */ -/* global define, vec2 */ +/* global define */ define('quagga',[ @@ -8174,7 +9790,8 @@ define('quagga',[ "events", "camera_access", "image_debug", - "cv_utils"], + "cv_utils", + "gl-matrix"], function(Code128Reader, EANReader, InputStream, @@ -8187,7 +9804,8 @@ function(Code128Reader, Events, CameraAccess, ImageDebug, - CVUtils) { + CVUtils, + glMatrix) { var _inputStream, @@ -8207,7 +9825,8 @@ function(Code128Reader, _boxSize, _decoder, _workerPool = [], - _onUIThread = true; + _onUIThread = true, + vec2 = glMatrix.vec2; function initializeData(imageWrapper) { initBuffers(imageWrapper); @@ -8215,20 +9834,22 @@ function(Code128Reader, } function initConfig() { - var vis = [{ - node : document.querySelector("div[data-controls]"), - prop : _config.controls - }, { - node : _canvasContainer.dom.overlay, - prop : _config.visual.show - }]; - - for (var i = 0; i < vis.length; i++) { - if (vis[i].node) { - if (vis[i].prop === true) { - vis[i].node.style.display = "block"; - } else { - vis[i].node.style.display = "none"; + if (typeof document !== "undefined") { + var vis = [{ + node: document.querySelector("div[data-controls]"), + prop: _config.controls + }, { + node: _canvasContainer.dom.overlay, + prop: _config.visual.show + }]; + + for (var i = 0; i < vis.length; i++) { + if (vis[i].node) { + if (vis[i].prop === true) { + vis[i].node.style.display = "block"; + } else { + vis[i].node.style.display = "none"; + } } } } @@ -8320,35 +9941,37 @@ function(Code128Reader, } function initCanvas() { - var $viewport = document.querySelector("#interactive.viewport"); - _canvasContainer.dom.image = document.querySelector("canvas.imgBuffer"); - if (!_canvasContainer.dom.image) { - _canvasContainer.dom.image = document.createElement("canvas"); - _canvasContainer.dom.image.className = "imgBuffer"; - if($viewport && _config.inputStream.type == "ImageStream") { - $viewport.appendChild(_canvasContainer.dom.image); - } - } - _canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d"); - _canvasContainer.dom.image.width = _inputStream.getWidth(); - _canvasContainer.dom.image.height = _inputStream.getHeight(); - - _canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer"); - if (!_canvasContainer.dom.overlay) { - _canvasContainer.dom.overlay = document.createElement("canvas"); - _canvasContainer.dom.overlay.className = "drawingBuffer"; - if($viewport) { - $viewport.appendChild(_canvasContainer.dom.overlay); - } - var clearFix = document.createElement("br"); - clearFix.setAttribute("clear", "all"); - if($viewport) { - $viewport.appendChild(clearFix); - } - } - _canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d"); - _canvasContainer.dom.overlay.width = _inputStream.getWidth(); - _canvasContainer.dom.overlay.height = _inputStream.getHeight(); + if (typeof document !== "undefined") { + var $viewport = document.querySelector("#interactive.viewport"); + _canvasContainer.dom.image = document.querySelector("canvas.imgBuffer"); + if (!_canvasContainer.dom.image) { + _canvasContainer.dom.image = document.createElement("canvas"); + _canvasContainer.dom.image.className = "imgBuffer"; + if ($viewport && _config.inputStream.type == "ImageStream") { + $viewport.appendChild(_canvasContainer.dom.image); + } + } + _canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d"); + _canvasContainer.dom.image.width = _inputStream.getWidth(); + _canvasContainer.dom.image.height = _inputStream.getHeight(); + + _canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer"); + if (!_canvasContainer.dom.overlay) { + _canvasContainer.dom.overlay = document.createElement("canvas"); + _canvasContainer.dom.overlay.className = "drawingBuffer"; + if ($viewport) { + $viewport.appendChild(_canvasContainer.dom.overlay); + } + var clearFix = document.createElement("br"); + clearFix.setAttribute("clear", "all"); + if ($viewport) { + $viewport.appendChild(clearFix); + } + } + _canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d"); + _canvasContainer.dom.overlay.width = _inputStream.getWidth(); + _canvasContainer.dom.overlay.height = _inputStream.getHeight(); + } } function initBuffers(imageWrapper) { @@ -8363,10 +9986,10 @@ function(Code128Reader, console.log(_inputImageWrapper.size); _boxSize = [ - vec2.create([20, _inputImageWrapper.size.y / 2 - 100]), - vec2.create([20, _inputImageWrapper.size.y / 2 + 100]), - vec2.create([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 + 100]), - vec2.create([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 - 100]) + vec2.clone([20, _inputImageWrapper.size.y / 2 - 100]), + vec2.clone([20, _inputImageWrapper.size.y / 2 + 100]), + vec2.clone([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 + 100]), + vec2.clone([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 - 100]) ]; BarcodeLocator.init(_inputImageWrapper, _config.locator); } diff --git a/dist/quagga.min.js b/dist/quagga.min.js index 70f3b86..8c98b46 100644 --- a/dist/quagga.min.js +++ b/dist/quagga.min.js @@ -1,9 +1,9 @@ -/*! quagga 2015-05-28 */ +/*! quagga 2015-06-07 */ !function(a,b){var c=b.toString();"undefined"!=typeof module?module.exports=b(c):a.Quagga=b(c)}(this,function(a){/** * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/jrburke/almond for details */ -var b,c,d;!function(a){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(n=n.slice(0,n.length-1),a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.concat(a),k=0;k