aboutsummaryrefslogtreecommitdiff
path: root/demos/webgl/glge_math.js
diff options
context:
space:
mode:
authorAlon Zakai <azakai@mozilla.com>2010-11-07 16:07:47 -0800
committerAlon Zakai <azakai@mozilla.com>2010-11-07 16:07:47 -0800
commit98a9576c6e3c357960bd7741f9e0ad964f206e29 (patch)
treea12dd6801c7fce111584a8c18cf1692c7a731c68 /demos/webgl/glge_math.js
parent54b3d3ec052aac293524da742000167cd0be5067 (diff)
wip bullet/webgl demo
Diffstat (limited to 'demos/webgl/glge_math.js')
-rw-r--r--demos/webgl/glge_math.js1158
1 files changed, 1158 insertions, 0 deletions
diff --git a/demos/webgl/glge_math.js b/demos/webgl/glge_math.js
new file mode 100644
index 00000000..99df54c8
--- /dev/null
+++ b/demos/webgl/glge_math.js
@@ -0,0 +1,1158 @@
+/*
+GLGE WebGL Graphics Engine
+Copyright (c) 2010, Paul Brunt
+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.
+ * Neither the name of GLGE nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+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 PAUL BRUNT 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.
+*/
+
+/**
+ * @fileOverview
+ * @name GLGE_math.js
+ */
+
+ if(!window["GLGE"]){
+ /**
+ * @namespace Holds the functionality of the library
+ */
+ window["GLGE"]={};
+}
+
+(function(GLGE){
+
+GLGE.Vec=function(array) {
+ return array.slice(0);
+}
+
+/**
+* The Vec3 Class creates a vector
+* @param {Array} array An array of 3 floats
+*/
+GLGE.Vec3=function(x,y,z){
+ return [x,y,z];
+}
+
+/**
+* The Vec4 Class creates a vector
+* @param {Array} array An array of 4 floats
+*/
+GLGE.Vec4=function(x,y,z,w){
+ return [x,y,z,w];
+}
+
+/**
+* Gets the nth element (1 indexed) from the array
+* @param {Array} v A vector with 4 elements
+* @param {number} i The index from one
+*/
+GLGE.get1basedVec4=function(v,i){
+ return v[i-1];
+};
+/**
+* Gets the nth element (1 indexed) from the array
+* @param {Array} v A vector with 3 elements
+* @param {number} i The index from one
+*/
+GLGE.get1basedVec3=function(v,i){
+ return v[i-1];
+};
+
+/**
+* Gets the nth element (1 indexed) from the array
+* @param {Array} v A vector with 4 elements
+* @param {number} i The index from one
+*/
+GLGE.getVec4=function(v,i){
+ return v[i];
+};
+/**
+* Gets the nth element (1 indexed) from the array
+* @param {Array} v A vector with 3 elements
+* @param {number} i The index from one
+*/
+GLGE.getVec3=function(v,i){
+ return v[i];
+};
+
+
+
+/**
+* Adds a GLGE.Vec4 to this Vec4
+* @param {Array} a The first value to add
+* * @param {Array} b The second value to add
+*/
+GLGE.addVec4=function(a,b) {
+ return [a[0]+b[0],a[1]+b[1],a[2]+b[2],a[3]+b[3]];
+}
+/**
+* Adds a GLGE.Vec3 to this GLGE.Vec3
+* @param {Array} a The first value to add
+* @param {Array} b The second value to add
+*/
+GLGE.addVec3=function(a,b) {
+ return [a[0]+b[0],a[1]+b[1],a[2]+b[2]];
+}
+
+
+/**
+* Adds a GLGE.Vec4 to this Vec4
+* @param {Array} a The first value
+* * @param {Array} b The second value to subtract from the first
+*/
+GLGE.subVec4=function(a,b) {
+ return [a[0]-b[0],a[1]-b[1],a[2]-b[2],a[3]-b[3]];
+}
+/**
+* Adds a GLGE.Vec3 to this GLGE.Vec3
+* @param {Array} a The first value
+* @param {Array} b The second value to subtract from the first
+*/
+GLGE.subVec3=function(a,b) {
+ return [a[0]-b[0],a[1]-b[1],a[2]-b[2]];
+}
+
+
+/**
+* Gets the dot product between this and the input vector
+* @param {Array} a the first value to dot
+* @param {Array} b the second value to dot
+*/
+GLGE.dotVec3=function(a,b) {
+ return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
+}
+
+
+/**
+* Gets the dot product between this and the input vector
+* @param {Array} a the first value to dot
+* @param {Array} b the second value to dot
+*/
+GLGE.dotVec4=function(a,b) {
+ return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3];
+}
+
+/**
+* Gets the dot product between this and the input vector
+* @param {Array} a the vector to scale
+* @param {Number} b the scalar
+*/
+GLGE.scaleVec4=function(a,b) {
+ return [a[0]*b,a[1]*b,a[2]*b,a[3]*b];
+}
+
+/**
+* Gets the dot product between this and the input vector
+* @param {Array} a the vector to scale
+* @param {Number} b the scalar
+*/
+GLGE.scaleVec3=function(a,b) {
+ return [a[0]*b,a[1]*b,a[2]*b];
+}
+
+
+/**
+* Gets the cross product between this and the input vector
+* @param {Array} a the first value to dot
+* @param {Array} b the second value to dot
+*/
+GLGE.crossVec3=function(a,b) {
+ return [a[1]*b[2]-a[2]*b[1],
+ a[2]*b[0]-a[0]*b[2],
+ a[0]*b[1]-a[1]*b[0]];
+}
+
+/**
+* Returns a unitized version of the input vector3
+* @param {Array} a the vector3 to be unitized
+*/
+GLGE.toUnitVec3=function(a) {
+ var sq=a[0]*a[0]+a[1]*a[1]+a[2]*a[2];
+ var f=1.0;
+ if (sq>0) {
+ f=Math.pow(sq,0.5);
+ }
+ return [a[0]/f,a[1]/f,a[2]/f];
+};
+
+/**
+* Returns a unitized version of the input vector4
+* @param {Array} a the vector4 to be unitized
+*/
+GLGE.toUnitVec4=function(a) {
+ var sq=a[0]*a[0]+a[1]*a[1]+a[2]*a[2]+a[3]*a[3];
+ var f=1.0;
+ if (sq>0) {
+ f=Math.pow(sq,0.5);
+ }
+ return [a[0]/f,a[1]/f,a[2]/f,a[3]/f];
+};
+
+
+/**
+* Returns the length of a vector3
+* @param {Array} a the vector to be measured
+*/
+GLGE.lengthVec3=function(a) {
+ return Math.pow(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],0.5);
+};
+
+/**
+* Returns the distance between 2 vector3s
+* @param {Array} a the first vector
+* @param {Array} b the second vector
+*/
+GLGE.distanceVec3=function(a,b){
+ return GLGE.lengthVec3(GLGE.subVec3(a,b));
+};
+
+/**
+* Returns the length of a vector3
+* @param {Array} a the vector to be measured
+*/
+GLGE.lengthVec4=function(a,b) {
+ return Math.pow(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]+a[3]*a[3],0.5);
+};
+
+/**
+* Returns the distance between 2 vector4s
+* @param {Array} a the first vector
+* @param {Array} b the second vector
+*/
+GLGE.distanceVec4=function(a,b){
+ return GLGE.lengthVec4(GLGE.subVec4(a,b));
+};
+
+
+/**
+* Returns the angle between 2 vector3s in radians
+* @param {Array} a the first vector
+* @param {Array} b the second vector
+*/
+GLGE.angleVec3=function(a,b){
+ a=GLGE.toUnitVec3(a);
+ b=GLGE.toUnitVec3(b);
+ d=GLGE.dotVec3(a,b);
+ if (d<-1)
+ d=-1;
+ if (d>1)
+ d=1;
+ return Math.acos(d);
+};
+
+/**
+* Returns the angle between 2 vector4s in radians
+* @param {Array} a the first vector
+* @param {Array} b the second vector
+*/
+GLGE.angleVec4=function(a,b){
+ a=GLGE.toUnitVec4(a);
+ b=GLGE.toUnitVec4(b);
+ d=GLGE.dotVec4(a,b);
+ if (d<-1)
+ d=-1;
+ if (d>1)
+ d=1;
+ return Math.acos(d);
+};
+
+GLGE_math_use_webgl_float=false;
+
+/**
+* The Mat class creates a matrix from an array
+* @param {Array} array An array of 9 or 16 floats
+*/
+GLGE.Mat3=GLGE_math_use_webgl_float?function(array) {
+ if (array.length==9) {
+ return new Float32Array(array);
+ }else if (array.length==16) {
+ return new Float32Array([array[0],array[1],array[2],array[4],array[5],array[6],array[8],array[9],array[10]]);
+ }else {
+ throw "invalid matrix length";
+ }
+}:function(array) {
+ var retval;
+ if (array.length==9) {
+ retval=array.slice(0);
+ }else if (array.length==16) {
+ retval=[array[0],array[1],array[2],array[4],array[5],array[6],array[8],array[9],array[10]];
+ }else {
+ throw "invalid matrix length";
+ }
+ retval.get=function(i){return this[i];};
+ return retval;
+};
+GLGE.Mat=GLGE_math_use_webgl_float?function(array) {
+ return new Float32Array(array);
+}:function(array){
+ var retval=array.slice(0);
+ retval.get=function(i){return this[i];};
+ return retval;
+};
+GLGE.Mat4=function(array) {
+ var retval;
+ if (array.length==9) {
+ retval=[array[0],array[1],array[2],0,array[3],array[4],array[5],0,array[6],array[7],array[8],0,0,0,0,1];
+ }else if (array.length==16) {
+ retval=array.slice(0);
+ }else {
+ throw "invalid matrix length";
+ }
+ retval.get=function(i){return this[i];};
+ return retval;
+};
+/**
+* Finds the determinate of the matrix
+* @returns {number} the determinate
+*/
+GLGE.determinantMat4=function(m) {
+ return m[12] * m[9] * m[6] * m[3] - m[8] * m[13] * m[6] * m[3] - m[12] * m[5] * m[10] * m[3] + m[4] * m[13] * m[10] * m[3] + m[8] * m[5] * m[14] * m[3] - m[4] * m[9] * m[14] * m[3] - m[12] * m[9] * m[2] * m[7] + m[8] * m[13] * m[2] * m[7] + m[12] * m[1] * m[10] * m[7] - m[0] * m[13] * m[10] * m[7] - m[8] * m[1] * m[14] * m[7] + m[0] * m[9] * m[14] * m[7] + m[12] * m[5] * m[2] * m[11] - m[4] * m[13] * m[2] * m[11] - m[12] * m[1] * m[6] * m[11] + m[0] * m[13] * m[6] * m[11] + m[4] * m[1] * m[14] * m[11] - m[0] * m[5] * m[14] * m[11] - m[8] * m[5] * m[2] * m[15] + m[4] * m[9] * m[2] * m[15] + m[8] * m[1] * m[6] * m[15] - m[0] * m[9] * m[6] * m[15] - m[4] * m[1] * m[10] * m[15] + m[0] * m[5] * m[10] * m[15];
+};
+
+/**
+* Finds the inverse of the matrix
+* @returns {GLGE.Mat} the inverse
+*/
+GLGE.inverseMat4=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];
+
+ var d = 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;
+
+ return [ (a21*a32*a13 - a31*a22*a13 + a31*a12*a23 - a11*a32*a23 - a21*a12*a33 + a11*a22*a33)/d,
+ (a31*a22*a03 - a21*a32*a03 - a31*a02*a23 + a01*a32*a23 + a21*a02*a33 - a01*a22*a33)/d,
+ (a11*a32*a03 - a31*a12*a03 + a31*a02*a13 - a01*a32*a13 - a11*a02*a33 + a01*a12*a33)/d,
+ (a21*a12*a03 - a11*a22*a03 - a21*a02*a13 + a01*a22*a13 + a11*a02*a23 - a01*a12*a23)/d,
+ (a30*a22*a13 - a20*a32*a13 - a30*a12*a23 + a10*a32*a23 + a20*a12*a33 - a10*a22*a33)/d,
+ (a20*a32*a03 - a30*a22*a03 + a30*a02*a23 - a00*a32*a23 - a20*a02*a33 + a00*a22*a33)/d,
+ (a30*a12*a03 - a10*a32*a03 - a30*a02*a13 + a00*a32*a13 + a10*a02*a33 - a00*a12*a33)/d,
+ (a10*a22*a03 - a20*a12*a03 + a20*a02*a13 - a00*a22*a13 - a10*a02*a23 + a00*a12*a23)/d,
+ (a20*a31*a13 - a30*a21*a13 + a30*a11*a23 - a10*a31*a23 - a20*a11*a33 + a10*a21*a33)/d,
+ (a30*a21*a03 - a20*a31*a03 - a30*a01*a23 + a00*a31*a23 + a20*a01*a33 - a00*a21*a33)/d,
+ (a10*a31*a03 - a30*a11*a03 + a30*a01*a13 - a00*a31*a13 - a10*a01*a33 + a00*a11*a33)/d,
+ (a20*a11*a03 - a10*a21*a03 - a20*a01*a13 + a00*a21*a13 + a10*a01*a23 - a00*a11*a23)/d,
+ (a30*a21*a12 - a20*a31*a12 - a30*a11*a22 + a10*a31*a22 + a20*a11*a32 - a10*a21*a32)/d,
+ (a20*a31*a02 - a30*a21*a02 + a30*a01*a22 - a00*a31*a22 - a20*a01*a32 + a00*a21*a32)/d,
+ (a30*a11*a02 - a10*a31*a02 - a30*a01*a12 + a00*a31*a12 + a10*a01*a32 - a00*a11*a32)/d,
+ (a10*a21*a02 - a20*a11*a02 + a20*a01*a12 - a00*a21*a12 - a10*a01*a22 + a00*a11*a22)/d]
+};
+
+/**
+* multiplies two mat4's
+* @returns {GLGE.Mat} the matrix multiplication of the matrices
+*/
+GLGE.mulMat4Vec4=function(mat1,vec2){
+ return GLGE.Vec4(mat1[0]*vec2[0]+mat1[1]*vec2[1]+mat1[2]*vec2[2]+mat1[3]*vec2[3],
+ mat1[4]*vec2[0]+mat1[5]*vec2[1]+mat1[6]*vec2[2]+mat1[7]*vec2[3],
+ mat1[8]*vec2[0]+mat1[9]*vec2[1]+mat1[10]*vec2[2]+mat1[11]*vec2[3],
+ mat1[12]*vec2[0]+mat1[13]*vec2[1]+mat1[14]*vec2[2]+mat1[15]*vec2[3]);
+};
+
+/**
+* multiplies a Mat4 by a scalar value
+* @returns {GLGE.Mat} the matrix multiplication of the matrices
+*/
+GLGE.scaleMat4=function(m,value) {
+ return GLGE.Mat([m[0]*value,m[1]*value,m[2]*value,m[3]*value,
+ m[4]*value,m[5]*value,m[6]*value,m[7]*value,
+ m[8]*value,m[9]*value,m[10]*value,m[11]*value,
+ m[12]*value,m[13]*value,m[14]*value,m[15]*value]);
+};
+/**
+* multiplies a Mat4 by a scalar value in place without allocation
+* @returns {GLGE.Mat} the input matrix, modified
+*/
+GLGE.scaleInPlaceMat4=function(m,value) {
+ m.set(0,m[0]*value);
+ m.set(1,m[1]*value);
+ m.set(2,m[2]*value);
+ m.set(3,m[3]*value);
+ m.set(4,m[4]*value);
+ m.set(5,m[5]*value);
+ m.set(6,m[6]*value);
+ m.set(7,m[7]*value);
+ m.set(8,m[8]*value);
+ m.set(9,m[9]*value);
+ m.set(10,m[10]*value);
+ m.set(11,m[11]*value);
+ m.set(12,m[12]*value);
+ m.set(13,m[13]*value);
+ m.set(14,m[14]*value);
+ m.set(15,m[15]*value);
+ return m;
+};
+
+/**
+* adds a Mat4 to another Mat4 in place without allocation
+* @returns {GLGE.Mat} the first input matrix, modified to be added
+*/
+GLGE.addInPlaceMat4=function(m,value) {
+ m.set(0,m[0]+value[0]);
+ m.set(1,m[1]+value[1]);
+ m.set(2,m[2]+value[2]);
+ m.set(3,m[3]+value[3]);
+ m.set(4,m[4]+value[4]);
+ m.set(5,m[5]+value[5]);
+ m.set(6,m[6]+value[6]);
+ m.set(7,m[7]+value[7]);
+ m.set(8,m[8]+value[8]);
+ m.set(9,m[9]+value[9]);
+ m.set(10,m[10]+value[10]);
+ m.set(11,m[11]+value[11]);
+ m.set(12,m[12]+value[12]);
+ m.set(13,m[13]+value[13]);
+ m.set(14,m[14]+value[14]);
+ m.set(15,m[15]+value[15]);
+ return m;
+};
+
+
+
+/**
+* adds two Mat4 together
+* @returns {GLGE.Mat} a new, added Mat4
+*/
+GLGE.addMat4=function(m,value) {
+return GLGE.Mat([m[0]+value[0],
+ m[1]+value[1],
+ m[2]+value[2],
+ m[3]+value[3],
+ m[4]+value[4],
+ m[5]+value[5],
+ m[6]+value[6],
+ m[7]+value[7],
+ m[8]+value[8],
+ m[9]+value[9],
+ m[10]+value[10],
+ m[11]+value[11],
+ m[12]+value[12],
+ m[13]+value[13],
+ m[14]+value[14],
+ m[15]+value[15]]);
+ return m;
+};
+
+
+
+/**
+* subs a Mat4 from another Mat4 in place without allocation
+* @returns {GLGE.Mat} the first input matrix, modified to have the second subtacted
+*/
+GLGE.subInPlaceMat4=function(m,value) {
+ m.set(0,m[0]-value[0]);
+ m.set(1,m[1]-value[1]);
+ m.set(2,m[2]-value[2]);
+ m.set(3,m[3]-value[3]);
+ m.set(4,m[4]-value[4]);
+ m.set(5,m[5]-value[5]);
+ m.set(6,m[6]-value[6]);
+ m.set(7,m[7]-value[7]);
+ m.set(8,m[8]-value[8]);
+ m.set(9,m[9]-value[9]);
+ m.set(10,m[10]-value[10]);
+ m.set(11,m[11]-value[11]);
+ m.set(12,m[12]-value[12]);
+ m.set(13,m[13]-value[13]);
+ m.set(14,m[14]-value[14]);
+ m.set(15,m[15]-value[15]);
+ return m;
+};
+
+
+
+/**
+* subtracts the second matrix from the first
+* @returns {GLGE.Mat} a new, subed Mat4
+*/
+GLGE.subMat4=function(m,value) {
+return GLGE.Mat([m[0]-value[0],
+ m[1]-value[1],
+ m[2]-value[2],
+ m[3]-value[3],
+ m[4]-value[4],
+ m[5]-value[5],
+ m[6]-value[6],
+ m[7]-value[7],
+ m[8]-value[8],
+ m[9]-value[9],
+ m[10]-value[10],
+ m[11]-value[11],
+ m[12]-value[12],
+ m[13]-value[13],
+ m[14]-value[14],
+ m[15]-value[15]]);
+ return m;
+};
+
+
+/**
+* Finds the matrix multiplication with another GLGE.Mat or GLGE.vec or an Array of length 3-4
+* @param {object} value An GLGE.Mat, GLGE.vec or Array
+* @returns {GLGE.Mat|GLGE.Vec}
+*/
+GLGE.mulMat4=function(mat2,mat1){
+
+ var a00 = mat1[0], a01 = mat1[1], a02 = mat1[2], a03 = mat1[3];
+ var a10 = mat1[4], a11 = mat1[5], a12 = mat1[6], a13 = mat1[7];
+ var a20 = mat1[8], a21 = mat1[9], a22 = mat1[10], a23 = mat1[11];
+ var a30 = mat1[12], a31 = mat1[13], a32 = mat1[14], a33 = mat1[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];
+ return [b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30,
+ b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31,
+ b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32,
+ b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33,
+
+ b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30,
+ b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31,
+ b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32,
+ b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33,
+
+ b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30,
+ b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31,
+ b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32,
+ b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33,
+
+ b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30,
+ b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31,
+ b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32,
+ b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33];
+};
+
+GLGE.transposeInPlaceMat4=function(m) {
+ var v=m[1];
+ m.set(1,m[4]);
+ m.set(4,v);
+
+
+ v=m[8];
+ m.set(8,m[2]);
+ m.set(2,v);
+
+
+ v=m[3];
+ m.set(3,m[12]);
+ m.set(12,v);
+
+ v=m[9];
+ m.set(9,m[6]);
+ m.set(6,v);
+
+ v=m[13];
+ m.set(13,m[7]);
+ m.set(7,v);
+
+ v=m[14];
+ m.set(14,m[11]);
+ m.set(11,v);
+
+};
+
+/**
+* Builds the transpose of the matrix
+* @returns {GLGE.Mat} the transposed matrix
+*/
+GLGE.transposeMat4=function(m) {
+ return GLGE.Mat4([m[0],m[4],m[8],m[12],
+ m[1],m[5],m[9],m[13],
+ m[2],m[6],m[10],m[14],
+ m[3],m[7],m[11],m[15]]);
+};
+
+/**
+* copys a js array into a webglarray
+* @param {array} mat the source array
+* @param {webglarray} glarray the destination array
+*/
+GLGE.mat4gl=function(mat,glarray){
+ glarray[0]=mat[0];
+ glarray[1]=mat[1];
+ glarray[2]=mat[2];
+ glarray[3]=mat[3];
+ glarray[4]=mat[4];
+ glarray[5]=mat[5];
+ glarray[6]=mat[6];
+ glarray[7]=mat[7];
+ glarray[8]=mat[8];
+ glarray[9]=mat[9];
+ glarray[10]=mat[10];
+ glarray[11]=mat[11];
+ glarray[12]=mat[12];
+ glarray[13]=mat[13];
+ glarray[14]=mat[14];
+ glarray[15]=mat[15];
+};
+
+/**
+* Sets the value at the specified index
+* @param {number} i the first index 1 offset
+* @param {number} j the second index 1 offset
+* @param {number} value the value to set
+*/
+GLGE.set1basedMat4=function(m,i,j,value){
+ m[(i-1)*4+(j-1)]=value;
+ if(m.glData!==undefined){
+ delete m.glData;
+ }
+};
+
+/**
+* Sets the value at the specified index
+* @param {number} i the first index from zero
+* @param {number} j the second index from zero
+* @param {number} value the value to set
+*/
+GLGE.setMat4=function(m,i,j,value){
+ m[i*4+j]=value;
+ if(m.glData!==undefined){
+ delete m.glData;
+ }
+};
+
+/**
+* Gets the value at the specified index
+* @param {number} i the first index from one
+* @param {number} j the second index from one
+* @returns {number} the value at the given index
+*/
+GLGE.get1basedMat4=function(m,i,j){
+ return m.get((i-1)*4+(j-1));
+};
+
+/**
+* Gets the value at the specified index
+* @param {number} i the first index from zero
+* @param {number} j the second index from zero
+* @returns {number} the value at the given index
+*/
+GLGE.getMat4=function(m,i,j){
+ return m[i*4+j];
+};
+/**
+* gets the a webgl float array for this Matrix, once generated it will cache it so it doesn't need to recreate everytime
+* @returns {Float32Array} the webgl array for this Matrix
+* @private
+*/
+GLGE.glDataMat4=function(m) {
+ m.glArray=new Float32Array(m);
+ return m.glArray;
+};
+/**
+ * Creates an identity matrix
+ * @returns {GLGE.Mat} the identity matrix
+ */
+GLGE.identMatrix=function(){
+ return GLGE.Mat([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
+};
+/**
+ * Creates a translation matrix
+ * @returns {Array} value an array GLGE.Vec or 3 paramters
+ * @returns {GLGE.Mat} the translation matrix
+ */
+GLGE.translateMatrix=function(value){
+ var x;
+ var y;
+ var z;
+ if(arguments.length==3){
+ x=arguments[0];
+ y=arguments[1];
+ z=arguments[2];
+ }
+ else if(value.data){
+ x=value.data[0];
+ y=value.data[1];
+ z=value.data[2];
+ }
+ else if(value instanceof Array){
+ x=value[0];
+ y=value[1];
+ z=value[2];
+ }
+ return GLGE.Mat([
+ 1,0,0,x,
+ 0,1,0,y,
+ 0,0,1,z,
+ 0,0,0,1
+ ]);
+};
+/**
+ * Creates a scale matrix
+ * @returns {Array} value an array GLGE.Vec or 3 paramters
+ * @returns {GLGE.Mat} the scale matrix
+ */
+GLGE.scaleMatrix=function(value){
+ var x;
+ var y;
+ var z;
+ if(arguments.length==3){
+ x=arguments[0];
+ y=arguments[1];
+ z=arguments[2];
+ }
+ else if(value.data){
+ x=value.data[0];
+ y=value.data[1];
+ z=value.data[2];
+ }
+ else if(value instanceof Array){
+ x=value[0];
+ y=value[1];
+ z=value[2];
+ }
+ return GLGE.Mat([
+ x,0,0,0,
+ 0,y,0,0,
+ 0,0,z,0,
+ 0,0,0,1
+ ]);
+}
+/**
+* @constant
+* @description Enum for XYZ rotation order
+*/
+GLGE.ROT_XYZ=1;
+/**
+* @constant
+* @description Enum for XZY rotation order
+*/
+GLGE.ROT_XZY=2;
+/**
+* @constant
+* @description Enum for YXZ rotation order
+*/
+GLGE.ROT_YXZ=3;
+/**
+* @constant
+* @description Enum for YZX rotation order
+*/
+GLGE.ROT_YZX=4;
+/**
+* @constant
+* @description Enum for ZXY rotation order
+*/
+GLGE.ROT_ZXY=5;
+/**
+* @constant
+* @description Enum for ZYX rotation order
+*/
+GLGE.ROT_ZYX=6;
+/**
+ * Creates a rotation matrix
+ * @returns {Array} value an array GLGE.Vec or 3 paramters
+ * @returns {GLGE.Mat} the rotation matrix
+ */
+GLGE.rotateMatrix=function(value,type) {
+ var x;
+ var y;
+ var z;
+ if(arguments.length>2){
+ x=arguments[0];
+ y=arguments[1];
+ z=arguments[2];
+ type=arguments[3];
+ }
+ else if(value.data){
+ x=value.data[0];
+ y=value.data[1];
+ z=value.data[2];
+ }
+ else if(value instanceof Array){
+ x=value[0];
+ y=value[1];
+ z=value[2];
+ }
+ if(!type) type=GLGE.ROT_XYZ;
+ var cosx=Math.cos(x);
+ var sinx=Math.sin(x);
+ var cosy=Math.cos(y);
+ var siny=Math.sin(y);
+ var cosz=Math.cos(z);
+ var sinz=Math.sin(z);
+ var rotx=GLGE.Mat([1,0,0,0,0,cosx,-sinx,0,0,sinx,cosx,0,0,0,0,1]);
+ var roty=GLGE.Mat([cosy,0,siny,0,0,1,0,0,-siny,0,cosy,0,0,0,0,1]);
+ var rotz=GLGE.Mat([cosz,-sinz,0,0,sinz,cosz,0,0,0,0,1,0,0,0,0,1]);
+ switch(type){
+ case GLGE.ROT_XYZ:
+ return GLGE.mulMat4(rotx,GLGE.mulMat4(roty,rotz));
+ break;
+ case GLGE.ROT_XZY:
+ return GLGE.mulMat4(rotx,GLGE.mulMat4(rotz,roty));
+ break;
+ case GLGE.ROT_YXZ:
+ return GLGE.mulMat4(roty,GLGE.mulMat4(rotx,rotz));
+ break;
+ case GLGE.ROT_YZX:
+ return GLGE.mulMat4(roty,GLGE.mulMat4(rotz,rotx));
+ break;
+ case GLGE.ROT_ZXY:
+ return GLGE.mulMat4(rotz,GLGE.mulMat4(rotx,roty));
+ break;
+ case GLGE.ROT_ZYX:
+ return GLGE.mulMat4(rotz,GLGE.mulMat4(roty,rotx));
+ break;
+ }
+}
+
+
+GLGE.angleAxis=function(angle, axis) {
+ var xmx,ymy,zmz,xmy,ymz,zmx,xms,yms,zms;
+ axis=[axis[0],axis[1],axis[2],0];
+
+ var x = axis[0];
+ var y = axis[1];
+ var z = axis[2];
+
+
+ var cos = Math.cos(angle);
+ var cosi = 1.0 - cos;
+ var sin = Math.sin(angle);
+
+ xms = x * sin;yms = y * sin;zms = z * sin;
+ xmx = x * x;ymy = y * y;zmz = z * z;
+ xmy = x * y;ymz = y * z;zmx = z * x;
+
+ var matrix = [(cosi * xmx) + cos,(cosi * xmy) - zms,(cosi * zmx) + yms,0,
+ (cosi * xmy) + zms,(cosi * ymy) + cos,(cosi * ymz) - xms,0,
+ (cosi * zmx) - yms,(cosi * ymz) + xms,(cosi * zmz) + cos,0,
+ 0,0,0,1];
+
+ return GLGE.Mat(matrix);
+};
+
+GLGE.quatRotation=function(qx,qy,qz,qw){
+ return GLGE.Mat([
+ 1 - 2*qy*qy - 2*qz*qz,2*qx*qy - 2*qz*qw,2*qx*qz + 2*qy*qw,0,
+ 2*qx*qy + 2*qz*qw,1 - 2*qx*qx - 2*qz*qz,2*qy*qz - 2*qx*qw,0,
+ 2*qx*qz - 2*qy*qw,2*qy*qz + 2*qx*qw,1 - 2*qx*qx - 2*qy*qy,0,
+ 0,0,0,1
+ ]);
+};
+
+GLGE.makeOrtho=function(left,right,bottom,top,near,far){
+ var x = -(right+left)/(right-left);
+ var y = -(top+bottom)/(top-bottom);
+ var z = -(far+near)/(far-near);
+
+ return GLGE.Mat([2/(right-left), 0, 0, x,
+ 0, 2/(top-bottom), 0, y,
+ 0, 0, -2/(far-near), z,
+ 0, 0, 0, 1]);
+};
+
+GLGE.makeFrustum=function(left,right,bottom,top,near,far){
+ var x = 2*near/(right-left);
+ var y = 2*near/(top-bottom);
+ var a = (right+left)/(right-left);
+ var b = (top+bottom)/(top-bottom);
+ var c = -(far+near)/(far-near);
+ var d = -2*far*near/(far-near);
+ return GLGE.Mat([x, 0, a, 0,
+ 0, y, b, 0,
+ 0, 0, c, d,
+ 0, 0, -1, 0]);
+};
+
+GLGE.makePerspective=function(fovy, aspect, near, far){
+ var ymax = near * Math.tan(fovy * 0.00872664625972);
+ var ymin = -ymax;
+ var xmin = ymin * aspect;
+ var xmax = ymax * aspect;
+ return GLGE.makeFrustum(xmin, xmax, ymin, ymax, near, far);
+};
+
+GLGE.matrix2Scale=function(m){
+ var m1=m[0];
+ var m2=m[1];
+ var m3=m[2];
+ var m4=m[4];
+ var m5=m[5];
+ var m6=m[6];
+ var m7=m[8];
+ var m8=m[9];
+ var m9=m[10];
+ var scaleX=Math.sqrt(m1*m1+m2*m2+m3*m3);
+ var scaleY=Math.sqrt(m4*m4+m5*m5+m6*m6);
+ var scaleZ=Math.sqrt(m7*m7+m8*m8+m9*m9);
+ return [scaleX,scaleY,scaleZ]
+}
+
+
+GLGE.rotationMatrix2Quat=function(m){
+ var tr = m[0] + m[5] + m[10]+1.0;
+ var S,x,y,z,w;
+
+ if (tr > 0) {
+ S = 0.5/Math.sqrt(tr);
+ w = 0.25 / S;
+ x = (m[9] - m[6]) * S;
+ y = (m[2] - m[8]) * S;
+ z = (m[4] - m[1]) * S;
+ } else if ((m[0] > m[5])&&(m[0] > m[10])) {
+ S = Math.sqrt(1.0 + m[0] - m[5] - m[10]) * 2;
+ w = (m[9] - m[6]) / S;
+ x = 0.25 / S;
+ y = (m[1] + m[4]) / S;
+ z = (m[2] + m[8]) / S;
+ } else if (m[5] > m[10]) {
+ S = Math.sqrt(1.0 + m[5] - m[0] - m[10]) * 2;
+ w = (m[2] - m[8]) / S;
+ x = (m[1] + m[4]) / S;
+ y = 0.25 / S;
+ z = (m[6] + m[9]) / S;
+ } else {
+ S = Math.sqrt(1.0 + m[10] - m[0] - m[5]) * 2;
+ w = (m[4] - m[1]) / S;
+ x = (m[2] + m[8]) / S;
+ y = (m[6] + m[9]) / S;
+ z = 0.25 / S;
+ }
+ var N=Math.sqrt(x*x+y*y+z*z+w*w)
+
+ return [x/N,y/N,z/N,w/N];
+}
+
+
+
+//returns plane as array [X,Y,Z,D]
+GLGE.rayToPlane=function(origin,dir){
+ var dirnorm=GLGE.toUnitVec3(dir);
+ return [dirnorm[0],dirnorm[1],dirnorm[2],GLGE.dotVec3(origin,dirnorm)];
+}
+
+GLGE.rayIntersectPlane=function(origin,dir,plane){
+ var planeN=[plane[0],plane[1],plane[2]];
+ var planeD=plane[3];
+ var vdir=GLGE.dotVec3(planeN,dir);
+ if(vdir<=0){
+ //ray in wrong direction
+ return false;
+ }
+ var vo=-(GLGE.dotVec3(planeN,origin)+planeD);
+ var t=vo/vdir;
+ if(t<=0){
+ return false;
+ }
+ return GLGE.addVec3(origin,GLGE.scaleVec3(dir,t));
+}
+//assumes perspective projection
+GLGE.screenToDirection=function(x,y,width,height,proj){
+ xcoord = -( ( ( 2 * x ) / width ) - 1 ) / proj[0];
+ ycoord =( ( ( 2 * y ) / height ) - 1 ) / proj[5];
+ zcoord = 1;
+ return GLGE.toUnitVec3([xcoord,ycoord,zcoord]);
+}
+
+GLGE.BoundingVolume=function(minX,maxX,minY,maxY,minZ,maxZ){
+ var dims=[maxX-minX,maxY-minY,maxZ-minZ];
+ this.dims=dims;
+ this.center=[dims[0]/2+minX,dims[1]/2+minY,dims[2]/2+minZ];
+}
+
+//returns the center of the bounding area
+GLGE.BoundingVolume.prototype.getCenter=function(matrix){
+ return GLGE.mulMat4Vec4(matrix,this.center);
+}
+
+//returns box point
+GLGE.BoundingVolume.prototype.getBoxPoint=function(matrix,point){
+ var coord=[this.dims[0]/2*point[0]+this.center[0],this.dims[1]/2*point[1]+this.center[1],this.dims[2]/2*point[2]+this.center[2]];
+ return GLGE.mulMat4Vec4(matrix,coord);
+}
+
+//returns the radius of a bounding sphere
+GLGE.BoundingVolume.prototype.getSphereRadius=function(){
+ return Math.pow((this.dims[0]*this.dims[0]+this.dims[1]*this.dims[1]+this.dims[2]*this.dims[2])/4,0.5);
+}
+
+//adds an additional bounding volume to resize the current and returns the result
+GLGE.BoundingVolume.prototype.addBoundingVolume=function(vol){
+ var minX=Math.min(this.center[0]-this.dims[0]/2,vol.center[0]-vol.dims[0]/2);
+ var maxX=Math.max(this.center[0]+this.dims[0]/2,vol.center[0]+vol.dims[0]/2);
+ var minY=Math.min(this.center[1]-this.dims[1]/2,vol.center[1]-vol.dims[1]/2);
+ var maxY=Math.max(this.center[1]+this.dims[1]/2,vol.center[1]+vol.dims[1]/2);
+ var minZ=Math.min(this.center[2]-this.dims[2]/2,vol.center[2]-vol.dims[2]/2);
+ var maxZ=Math.max(this.center[2]+this.dims[2]/2,vol.center[2]+vol.dims[2]/2);
+ var dims=[maxX-minX,maxY-minY,maxZ-minZ];
+ this.dims=dims;
+ this.center=[dims[0]/2+minX,dims[1]/2+minY,dims[2]/2+minZ];
+}
+
+//scales a volume based on a transform matrix
+GLGE.BoundingVolume.prototype.applyMatrixScale=function(matrix){
+ var scaleX=GLGE.lengthVec3([matrix[0],matrix[4],matrix[8]]);
+ var scaleY=GLGE.lengthVec3([matrix[1],matrix[5],matrix[9]]);
+ var scaleZ=GLGE.lengthVec3([matrix[2],matrix[6],matrix[10]]);
+ var minX=(this.center[0]-this.dims[0]/2)*scaleX;
+ var maxX=(this.center[0]+this.dims[0]/2)*scaleX;
+ var minY=(this.center[1]-this.dims[1]/2)*scaleY;
+ var maxY=(this.center[1]+this.dims[1]/2)*scaleY;
+ var minZ=(this.center[2]-this.dims[2]/2)*scaleZ;
+ var maxZ=(this.center[2]+this.dims[2]/2)*scaleZ;
+ var dims=[maxX-minX,maxY-minY,maxZ-minZ];
+ this.dims=dims;
+ this.center=[dims[0]/2+minX,dims[1]/2+minY,dims[2]/2+minZ];
+}
+
+GLGE.BoundingVolume.prototype.clone=function(){
+ var minX=this.center[0]-this.dims[0]/2;
+ var maxX=this.center[0]+this.dims[0]/2;
+ var minY=this.center[1]-this.dims[1]/2;
+ var maxY=this.center[1]+this.dims[1]/2;
+ var minZ=this.center[2]-this.dims[2]/2;
+ var maxZ=this.center[2]+this.dims[2]/2;
+ return new GLGE.BoundingVolume(minX,maxX,minY,maxY,minZ,maxZ);
+}
+
+GLGE.BoundingVolume.prototype.toString=function(){
+ var minX=this.center[0]-this.dims[0]/2;
+ var maxX=this.center[0]+this.dims[0]/2;
+ var minY=this.center[1]-this.dims[1]/2;
+ var maxY=this.center[1]+this.dims[1]/2;
+ var minZ=this.center[2]-this.dims[2]/2;
+ var maxZ=this.center[2]+this.dims[2]/2;
+ return [minX,maxX,minY,maxY,minZ,maxZ].toString();
+}
+
+
+function GLGE_mathUnitTest() {
+ var a=GLGE.Vec([1,2,3,4]);
+ var b=GLGE.Vec4(GLGE.getVec4(a,3),
+ GLGE.get1basedVec4(a,3),
+ GLGE.getVec4(a,1),
+ GLGE.getVec4(a,0));
+ var c=GLGE.identMatrix();
+ var d=GLGE.mulMat4Vec4(c,b);
+ if (GLGE.getVec4(d,0)!=4||
+ GLGE.getVec4(d,1)!=3||
+ GLGE.getVec4(d,2)!=2||
+ GLGE.getVec4(d,3)!=1) {
+ throw "Unit Test 1 failed MatVecMul "+d;
+ }
+ var m=GLGE.Mat4([3,4,5,0,.5,.75,0,0,.75,.5,0,0,.25,.25,1,1]);
+ var m1=GLGE.Mat4([2,1,8,2,1,4,3,2,1,.5,6.5,2,8,3,1,.25]);
+ var mm1=GLGE.mulMat4(m,m1);
+ var am1=GLGE.Mat4([15,21.5,68.5,24,
+ 1.75,3.5,6.25,2.5,
+ 2,2.75,7.5,2.5,
+ 9.75,4.75,10.25,3.25]);
+ for (var i=0;i<4;++i) {
+ for (var j=0;j<4;++j) {
+ var diff=GLGE.getMat4(mm1,i,j)-GLGE.getMat4(am1,i,j);
+ if (diff<.000001&&diff>-.000001) {
+
+ }else {
+ throw "Unit Test 1 failed Multiplication "+GLGE.getMat4(mm1,i,j)+" != "+GLGE.getMat4(am1,i,j);
+ }
+ }
+ }
+ var inv = GLGE.inverseMat4(m);
+ var k = GLGE.mulMat4(m,inv);
+ var l = GLGE.mulMat4(inv,m);
+ for (var i=0;i<4;++i) {
+ for (var j=0;j<4;++j) {
+ var diff=GLGE.getMat4(k,i,j)-GLGE.getMat4(c,i,j);
+ if (diff<.0001&&diff>-.0001) {
+ }else {
+ throw "Unit Test 1 failed Inverse "+GLGE.getMat4(k,i,j)+" != "+GLGE.getMat4(c,i,j);
+ }
+ }
+ }
+}
+GLGE_mathUnitTest() ;
+
+
+//Closure Export
+GLGE["Vec3"]=GLGE.Vec3;
+GLGE["Vec4"]=GLGE.Vec4;
+GLGE["get1basedVec4"]=GLGE.get1basedVec4;
+GLGE["get1basedVec3"]=GLGE.get1basedVec3;
+GLGE["getVec4"]=GLGE.getVec4;
+GLGE["getVec3"]=GLGE.getVec3;
+GLGE["addVec4"]=GLGE.addVec4;
+GLGE["addVec3"]=GLGE.addVec3;
+GLGE["subVec4"]=GLGE.subVec4;
+GLGE["subVec3"]=GLGE.subVec3;
+GLGE["dotVec3"]=GLGE.dotVec3;
+GLGE["dotVec4"]=GLGE.dotVec4;
+GLGE["scaleVec4"]=GLGE.scaleVec4;
+GLGE["scaleVec3"]=GLGE.scaleVec3;
+GLGE["crossVec3"]=GLGE.crossVec3;
+GLGE["toUnitVec3"]=GLGE.toUnitVec3;
+GLGE["toUnitVec4"]=GLGE.toUnitVec4;
+GLGE["lengthVec3"]=GLGE.lengthVec3;
+GLGE["distanceVec3"]=GLGE.distanceVec3;
+GLGE["lengthVec4"]=GLGE.lengthVec4;
+GLGE["distanceVec4"]=GLGE.distanceVec4;
+GLGE["angleVec3"]=GLGE.angleVec3;
+GLGE["angleVec4"]=GLGE.angleVec4;
+GLGE["Mat3"]=GLGE.Mat3;
+GLGE["Mat"]=GLGE.Mat;
+GLGE["Mat4"]=GLGE.Mat4;
+GLGE["determinantMat4"]=GLGE.determinantMat4;
+GLGE["inverseMat4"]=GLGE.inverseMat4;
+GLGE["mulMat4Vec4"]=GLGE.mulMat4Vec4;
+GLGE["scaleMat4"]=GLGE.scaleMat4;
+GLGE["scaleInPlaceMat4"]=GLGE.scaleInPlaceMat4;
+GLGE["addInPlaceMat4"]=GLGE.addInPlaceMat4;
+GLGE["addMat4"]=GLGE.addMat4;
+GLGE