# HG changeset patch # User # Date 1295107073 -32400 # Node ID 87850fc554450c6ebeef86aa838ec88c62f71849 # Parent d322eed6e1c7deaceeaf3a7498a1efda577aaf56 save diff -r d322eed6e1c7 -r 87850fc55445 Pants_FPS/resources/#J3DIMath.js# --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pants_FPS/resources/#J3DIMath.js# Sun Jan 16 00:57:53 2011 +0900 @@ -0,0 +1,1078 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. ``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 APPLE INC. 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. + */ + + // J3DI (Jedi) - A support library for WebGL. + +/* + J3DI Math Classes. Currently includes: + + J3DIMatrix4 - A 4x4 Matrix +*/ + +/* + J3DIMatrix4 class + + This class implements a 4x4 matrix. It has functions which duplicate the + functionality of the OpenGL matrix stack and glut functions. On browsers + that support it, CSSMatrix is used to accelerate operations. + + IDL: + + [ + Constructor(in J3DIMatrix4 matrix), // copy passed matrix into new J3DIMatrix4 + Constructor(in sequence array) // create new J3DIMatrix4 with 16 floats (row major) + Constructor() // create new J3DIMatrix4 with identity matrix + ] + interface J3DIMatrix4 { + void load(in J3DIMatrix4 matrix); // copy the values from the passed matrix + void load(in sequence array); // copy 16 floats into the matrix + sequence getAsArray(); // return the matrix as an array of 16 floats + Float32Array getAsFloat32Array(); // return the matrix as a Float32Array with 16 values + void setUniform(in WebGLRenderingContext ctx, // Send the matrix to the passed uniform location in the passed context + in WebGLUniformLocation loc, + in boolean transpose); + void makeIdentity(); // replace the matrix with identity + void transpose(); // replace the matrix with its transpose + void invert(); // replace the matrix with its inverse + + void translate(in float x, in float y, in float z); // multiply the matrix by passed translation values on the right + void translate(in J3DVector3 v); // multiply the matrix by passed translation values on the right + void scale(in float x, in float y, in float z); // multiply the matrix by passed scale values on the right + void scale(in J3DVector3 v); // multiply the matrix by passed scale values on the right + void rotate(in float angle, // multiply the matrix by passed rotation values on the right + in float x, in float y, in float z); // (angle is in degrees) + void rotate(in float angle, in J3DVector3 v); // multiply the matrix by passed rotation values on the right + // (angle is in degrees) + void multiply(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the right + void divide(in float divisor); // divide the matrix by the passed divisor + void ortho(in float left, in float right, // multiply the matrix by the passed ortho values on the right + in float bottom, in float top, + in float near, in float far); + void frustum(in float left, in float right, // multiply the matrix by the passed frustum values on the right + in float bottom, in float top, + in float near, in float far); + void perspective(in float fovy, in float aspect, // multiply the matrix by the passed perspective values on the right + in float zNear, in float zFar); + void lookat(in J3DVector3 eye, // multiply the matrix by the passed lookat + in J3DVector3 center, in J3DVector3 up); // values on the right + bool decompose(in J3DVector3 translate, // decompose the matrix into the passed vector + in J3DVector3 rotate, + in J3DVector3 scale, + in J3DVector3 skew, + in sequence perspective); + } + + [ + Constructor(in J3DVector3 vector), // copy passed vector into new J3DVector3 + Constructor(in sequence array) // create new J3DVector3 with 3 floats from array + Constructor(in float x, in float y, in float z) // create new J3DVector3 with 3 floats + Constructor() // create new J3DVector3 with (0,0,0) + ] + interface J3DVector3 { + void load(in J3DVector3 vector); // copy the values from the passed vector + void load(in sequence array); // copy 3 floats into the vector from array + void load(in float x, in float y, in float z); // copy 3 floats into the vector + sequence getAsArray(); // return the vector as an array of 3 floats + Float32Array getAsFloat32Array(); // return the matrix as a Float32Array with 16 values + void multMatrix(in J3DIMatrix4 matrix); // multiply the vector by the passed matrix (on the right) + float vectorLength(); // return the length of the vector + float dot(); // return the dot product of the vector + void cross(in J3DVector3 v); // replace the vector with vector x v + void divide(in float divisor); // divide the vector by the passed divisor + } +*/ + +J3DIHasCSSMatrix = false; +J3DIHasCSSMatrixCopy = false; +/* +if ("WebKitCSSMatrix" in window && ("media" in window && window.media.matchMedium("(-webkit-transform-3d)")) || + ("styleMedia" in window && window.styleMedia.matchMedium("(-webkit-transform-3d)"))) { + J3DIHasCSSMatrix = true; + if ("copy" in WebKitCSSMatrix.prototype) + J3DIHasCSSMatrixCopy = true; +} +*/ + +// console.log("J3DIHasCSSMatrix="+J3DIHasCSSMatrix); +// console.log("J3DIHasCSSMatrixCopy="+J3DIHasCSSMatrixCopy); + +// +// J3DIMatrix4 +// +J3DIMatrix4 = function(m) +{ + if (J3DIHasCSSMatrix) + this.$matrix = new WebKitCSSMatrix; + else + this.$matrix = new Object; + + if (typeof m == 'object') { + if ("length" in m && m.length >= 16) { + this.load(m); + return; + } + else if (m instanceof J3DIMatrix4) { + this.load(m); + return; + } + } + this.makeIdentity(); +} + +J3DIMatrix4.prototype.load = function() +{ + if (arguments.length == 1 && typeof arguments[0] == 'object') { + var matrix; + + if (arguments[0] instanceof J3DIMatrix4) { + matrix = arguments[0].$matrix; + + this.$matrix.m11 = matrix.m11; + this.$matrix.m12 = matrix.m12; + this.$matrix.m13 = matrix.m13; + this.$matrix.m14 = matrix.m14; + + this.$matrix.m21 = matrix.m21; + this.$matrix.m22 = matrix.m22; + this.$matrix.m23 = matrix.m23; + this.$matrix.m24 = matrix.m24; + + this.$matrix.m31 = matrix.m31; + this.$matrix.m32 = matrix.m32; + this.$matrix.m33 = matrix.m33; + this.$matrix.m34 = matrix.m34; + + this.$matrix.m41 = matrix.m41; + this.$matrix.m42 = matrix.m42; + this.$matrix.m43 = matrix.m43; + this.$matrix.m44 = matrix.m44; + return; + } + else + matrix = arguments[0]; + + if ("length" in matrix && matrix.length >= 16) { + this.$matrix.m11 = matrix[0]; + this.$matrix.m12 = matrix[1]; + this.$matrix.m13 = matrix[2]; + this.$matrix.m14 = matrix[3]; + + this.$matrix.m21 = matrix[4]; + this.$matrix.m22 = matrix[5]; + this.$matrix.m23 = matrix[6]; + this.$matrix.m24 = matrix[7]; + + this.$matrix.m31 = matrix[8]; + this.$matrix.m32 = matrix[9]; + this.$matrix.m33 = matrix[10]; + this.$matrix.m34 = matrix[11]; + + this.$matrix.m41 = matrix[12]; + this.$matrix.m42 = matrix[13]; + this.$matrix.m43 = matrix[14]; + this.$matrix.m44 = matrix[15]; + return; + } + } + + this.makeIdentity(); +} + +J3DIMatrix4.prototype.getAsArray = function() +{ + return [ + this.$matrix.m11, this.$matrix.m12, this.$matrix.m13, this.$matrix.m14, + this.$matrix.m21, this.$matrix.m22, this.$matrix.m23, this.$matrix.m24, + this.$matrix.m31, this.$matrix.m32, this.$matrix.m33, this.$matrix.m34, + this.$matrix.m41, this.$matrix.m42, this.$matrix.m43, this.$matrix.m44 + ]; +} + + :q +J3DIMatrix4.prototype.getAsArrayMatrix = function(mat) +{ + mat.m11 = this.$matrix.m11; mat.m12 = this.$matrix.m12; + mat.m13 = this.$matrix.m13; mat.m14 = this.$matrix.m14, + mat.m21 = this.$matrix.m21; mat.m22 = this.$matrix.m22; + mat.m23 = this.$matrix.m23; mat.m25 = this.$matrix.m24; + mat.m31 = this.$matrix.m31; mat.m32 = this.$matrix.m32; + mat.m33 = this.$matrix.m33; mat.m34 = this.$matrix.m34; + mat.m41 = this.$matrix.m41; mat.m42 = this.$matrix.m42; + mat.m43 = this.$matrix.m43; mat.m44 = this.$matrix.m44; +} + +J3DIMatrix4.prototype.getAsFloat32Array = function() +{ + if (J3DIHasCSSMatrixCopy) { + var array = new Float32Array(16); + this.$matrix.copy(array); + return array; + } + return new Float32Array(this.getAsArray()); +} + +J3DIMatrix4.prototype.setUniform = function(ctx, loc, transpose) +{ + if (J3DIMatrix4.setUniformArray == undefined) { + J3DIMatrix4.setUniformWebGLArray = new Float32Array(16); + J3DIMatrix4.setUniformArray = new Array(16); + } + + if (J3DIHasCSSMatrixCopy) + this.$matrix.copy(J3DIMatrix4.setUniformWebGLArray); + else { + J3DIMatrix4.setUniformArray[0] = this.$matrix.m11; + J3DIMatrix4.setUniformArray[1] = this.$matrix.m12; + J3DIMatrix4.setUniformArray[2] = this.$matrix.m13; + J3DIMatrix4.setUniformArray[3] = this.$matrix.m14; + J3DIMatrix4.setUniformArray[4] = this.$matrix.m21; + J3DIMatrix4.setUniformArray[5] = this.$matrix.m22; + J3DIMatrix4.setUniformArray[6] = this.$matrix.m23; + J3DIMatrix4.setUniformArray[7] = this.$matrix.m24; + J3DIMatrix4.setUniformArray[8] = this.$matrix.m31; + J3DIMatrix4.setUniformArray[9] = this.$matrix.m32; + J3DIMatrix4.setUniformArray[10] = this.$matrix.m33; + J3DIMatrix4.setUniformArray[11] = this.$matrix.m34; + J3DIMatrix4.setUniformArray[12] = this.$matrix.m41; + J3DIMatrix4.setUniformArray[13] = this.$matrix.m42; + J3DIMatrix4.setUniformArray[14] = this.$matrix.m43; + J3DIMatrix4.setUniformArray[15] = this.$matrix.m44; + + J3DIMatrix4.setUniformWebGLArray.set(J3DIMatrix4.setUniformArray); + } + + ctx.uniformMatrix4fv(loc, transpose, J3DIMatrix4.setUniformWebGLArray); +} + +J3DIMatrix4.prototype.makeIdentity = function() +{ + this.$matrix.m11 = 1; + this.$matrix.m12 = 0; + this.$matrix.m13 = 0; + this.$matrix.m14 = 0; + + this.$matrix.m21 = 0; + this.$matrix.m22 = 1; + this.$matrix.m23 = 0; + this.$matrix.m24 = 0; + + this.$matrix.m31 = 0; + this.$matrix.m32 = 0; + this.$matrix.m33 = 1; + this.$matrix.m34 = 0; + + this.$matrix.m41 = 0; + this.$matrix.m42 = 0; + this.$matrix.m43 = 0; + this.$matrix.m44 = 1; +} + +J3DIMatrix4.prototype.transpose = function() +{ + var tmp = this.$matrix.m12; + this.$matrix.m12 = this.$matrix.m21; + this.$matrix.m21 = tmp; + + tmp = this.$matrix.m13; + this.$matrix.m13 = this.$matrix.m31; + this.$matrix.m31 = tmp; + + tmp = this.$matrix.m14; + this.$matrix.m14 = this.$matrix.m41; + this.$matrix.m41 = tmp; + + tmp = this.$matrix.m23; + this.$matrix.m23 = this.$matrix.m32; + this.$matrix.m32 = tmp; + + tmp = this.$matrix.m24; + this.$matrix.m24 = this.$matrix.m42; + this.$matrix.m42 = tmp; + + tmp = this.$matrix.m34; + this.$matrix.m34 = this.$matrix.m43; + this.$matrix.m43 = tmp; +} + +J3DIMatrix4.prototype.invert = function() +{ + if (J3DIHasCSSMatrix) { + this.$matrix = this.$matrix.inverse(); + return; + } + + // Calculate the 4x4 determinant + // If the determinant is zero, + // then the inverse matrix is not unique. + var det = this._determinant4x4(); + + if (Math.abs(det) < 1e-8) + return null; + + this._makeAdjoint(); + + // Scale the adjoint matrix to get the inverse + this.$matrix.m11 /= det; + this.$matrix.m12 /= det; + this.$matrix.m13 /= det; + this.$matrix.m14 /= det; + + this.$matrix.m21 /= det; + this.$matrix.m22 /= det; + this.$matrix.m23 /= det; + this.$matrix.m24 /= det; + + this.$matrix.m31 /= det; + this.$matrix.m32 /= det; + this.$matrix.m33 /= det; + this.$matrix.m34 /= det; + + this.$matrix.m41 /= det; + this.$matrix.m42 /= det; + this.$matrix.m43 /= det; + this.$matrix.m44 /= det; +} + +J3DIMatrix4.prototype.translate = function(x,y,z) +{ + if (typeof x == 'object' && "length" in x) { + var t = x; + x = t[0]; + y = t[1]; + z = t[2]; + } + else { + if (x == undefined) + x = 0; + if (y == undefined) + y = 0; + if (z == undefined) + z = 0; + } + + if (J3DIHasCSSMatrix) { + this.$matrix = this.$matrix.translate(x, y, z); + return; + } + + var matrix = new J3DIMatrix4(); + matrix.$matrix.m41 = x; + matrix.$matrix.m42 = y; + matrix.$matrix.m43 = z; + + this.multiply(matrix); +} + +J3DIMatrix4.prototype.scale = function(x,y,z) +{ + if (typeof x == 'object' && "length" in x) { + var t = x; + x = t[0]; + y = t[1]; + z = t[2]; + } + else { + if (x == undefined) + x = 1; + if (z == undefined) { + if (y == undefined) { + y = x; + z = x; + } + else + z = 1; + } + else if (y == undefined) + y = x; + } + + if (J3DIHasCSSMatrix) { + this.$matrix = this.$matrix.scale(x, y, z); + return; + } + + var matrix = new J3DIMatrix4(); + matrix.$matrix.m11 = x; + matrix.$matrix.m22 = y; + matrix.$matrix.m33 = z; + + this.multiply(matrix); +} + +J3DIMatrix4.prototype.rotate = function(angle,x,y,z) +{ + // Forms are (angle, x,y,z), (angle,vector), (angleX, angleY, angleZ), (angle) + if (typeof x == 'object' && "length" in x) { + var t = x; + x = t[0]; + y = t[1]; + z = t[2]; + } + else { + if (arguments.length == 1) { + x = 0; + y = 0; + z = 1; + } + else if (arguments.length == 3) { + this.rotate(angle, 1,0,0); // about X axis + this.rotate(x, 0,1,0); // about Y axis + this.rotate(y, 0,0,1); // about Z axis + return; + } + } + + if (J3DIHasCSSMatrix) { + this.$matrix = this.$matrix.rotateAxisAngle(x, y, z, angle); + return; + } + + // angles are in degrees. Switch to radians + angle = angle / 180 * Math.PI; + + angle /= 2; + var sinA = Math.sin(angle); + var cosA = Math.cos(angle); + var sinA2 = sinA * sinA; + + // normalize + var len = Math.sqrt(x * x + y * y + z * z); + if (len == 0) { + // bad vector, just use something reasonable + x = 0; + y = 0; + z = 1; + } else if (len != 1) { + x /= len; + y /= len; + z /= len; + } + + var mat = new J3DIMatrix4(); + + // optimize case where axis is along major axis + if (x == 1 && y == 0 && z == 0) { + mat.$matrix.m11 = 1; + mat.$matrix.m12 = 0; + mat.$matrix.m13 = 0; + mat.$matrix.m21 = 0; + mat.$matrix.m22 = 1 - 2 * sinA2; + mat.$matrix.m23 = 2 * sinA * cosA; + mat.$matrix.m31 = 0; + mat.$matrix.m32 = -2 * sinA * cosA; + mat.$matrix.m33 = 1 - 2 * sinA2; + mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0; + mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0; + mat.$matrix.m44 = 1; + } else if (x == 0 && y == 1 && z == 0) { + mat.$matrix.m11 = 1 - 2 * sinA2; + mat.$matrix.m12 = 0; + mat.$matrix.m13 = -2 * sinA * cosA; + mat.$matrix.m21 = 0; + mat.$matrix.m22 = 1; + mat.$matrix.m23 = 0; + mat.$matrix.m31 = 2 * sinA * cosA; + mat.$matrix.m32 = 0; + mat.$matrix.m33 = 1 - 2 * sinA2; + mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0; + mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0; + mat.$matrix.m44 = 1; + } else if (x == 0 && y == 0 && z == 1) { + mat.$matrix.m11 = 1 - 2 * sinA2; + mat.$matrix.m12 = 2 * sinA * cosA; + mat.$matrix.m13 = 0; + mat.$matrix.m21 = -2 * sinA * cosA; + mat.$matrix.m22 = 1 - 2 * sinA2; + mat.$matrix.m23 = 0; + mat.$matrix.m31 = 0; + mat.$matrix.m32 = 0; + mat.$matrix.m33 = 1; + mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0; + mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0; + mat.$matrix.m44 = 1; + } else { + var x2 = x*x; + var y2 = y*y; + var z2 = z*z; + + mat.$matrix.m11 = 1 - 2 * (y2 + z2) * sinA2; + mat.$matrix.m12 = 2 * (x * y * sinA2 + z * sinA * cosA); + mat.$matrix.m13 = 2 * (x * z * sinA2 - y * sinA * cosA); + mat.$matrix.m21 = 2 * (y * x * sinA2 - z * sinA * cosA); + mat.$matrix.m22 = 1 - 2 * (z2 + x2) * sinA2; + mat.$matrix.m23 = 2 * (y * z * sinA2 + x * sinA * cosA); + mat.$matrix.m31 = 2 * (z * x * sinA2 + y * sinA * cosA); + mat.$matrix.m32 = 2 * (z * y * sinA2 - x * sinA * cosA); + mat.$matrix.m33 = 1 - 2 * (x2 + y2) * sinA2; + mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0; + mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0; + mat.$matrix.m44 = 1; + } + this.multiply(mat); +} + +J3DIMatrix4.prototype.multiply = function(mat) +{ + if (J3DIHasCSSMatrix) { + this.$matrix = this.$matrix.multiply(mat.$matrix); + return; + } + + var m11 = (mat.$matrix.m11 * this.$matrix.m11 + mat.$matrix.m12 * this.$matrix.m21 + + mat.$matrix.m13 * this.$matrix.m31 + mat.$matrix.m14 * this.$matrix.m41); + var m12 = (mat.$matrix.m11 * this.$matrix.m12 + mat.$matrix.m12 * this.$matrix.m22 + + mat.$matrix.m13 * this.$matrix.m32 + mat.$matrix.m14 * this.$matrix.m42); + var m13 = (mat.$matrix.m11 * this.$matrix.m13 + mat.$matrix.m12 * this.$matrix.m23 + + mat.$matrix.m13 * this.$matrix.m33 + mat.$matrix.m14 * this.$matrix.m43); + var m14 = (mat.$matrix.m11 * this.$matrix.m14 + mat.$matrix.m12 * this.$matrix.m24 + + mat.$matrix.m13 * this.$matrix.m34 + mat.$matrix.m14 * this.$matrix.m44); + + var m21 = (mat.$matrix.m21 * this.$matrix.m11 + mat.$matrix.m22 * this.$matrix.m21 + + mat.$matrix.m23 * this.$matrix.m31 + mat.$matrix.m24 * this.$matrix.m41); + var m22 = (mat.$matrix.m21 * this.$matrix.m12 + mat.$matrix.m22 * this.$matrix.m22 + + mat.$matrix.m23 * this.$matrix.m32 + mat.$matrix.m24 * this.$matrix.m42); + var m23 = (mat.$matrix.m21 * this.$matrix.m13 + mat.$matrix.m22 * this.$matrix.m23 + + mat.$matrix.m23 * this.$matrix.m33 + mat.$matrix.m24 * this.$matrix.m43); + var m24 = (mat.$matrix.m21 * this.$matrix.m14 + mat.$matrix.m22 * this.$matrix.m24 + + mat.$matrix.m23 * this.$matrix.m34 + mat.$matrix.m24 * this.$matrix.m44); + + var m31 = (mat.$matrix.m31 * this.$matrix.m11 + mat.$matrix.m32 * this.$matrix.m21 + + mat.$matrix.m33 * this.$matrix.m31 + mat.$matrix.m34 * this.$matrix.m41); + var m32 = (mat.$matrix.m31 * this.$matrix.m12 + mat.$matrix.m32 * this.$matrix.m22 + + mat.$matrix.m33 * this.$matrix.m32 + mat.$matrix.m34 * this.$matrix.m42); + var m33 = (mat.$matrix.m31 * this.$matrix.m13 + mat.$matrix.m32 * this.$matrix.m23 + + mat.$matrix.m33 * this.$matrix.m33 + mat.$matrix.m34 * this.$matrix.m43); + var m34 = (mat.$matrix.m31 * this.$matrix.m14 + mat.$matrix.m32 * this.$matrix.m24 + + mat.$matrix.m33 * this.$matrix.m34 + mat.$matrix.m34 * this.$matrix.m44); + + var m41 = (mat.$matrix.m41 * this.$matrix.m11 + mat.$matrix.m42 * this.$matrix.m21 + + mat.$matrix.m43 * this.$matrix.m31 + mat.$matrix.m44 * this.$matrix.m41); + var m42 = (mat.$matrix.m41 * this.$matrix.m12 + mat.$matrix.m42 * this.$matrix.m22 + + mat.$matrix.m43 * this.$matrix.m32 + mat.$matrix.m44 * this.$matrix.m42); + var m43 = (mat.$matrix.m41 * this.$matrix.m13 + mat.$matrix.m42 * this.$matrix.m23 + + mat.$matrix.m43 * this.$matrix.m33 + mat.$matrix.m44 * this.$matrix.m43); + var m44 = (mat.$matrix.m41 * this.$matrix.m14 + mat.$matrix.m42 * this.$matrix.m24 + + mat.$matrix.m43 * this.$matrix.m34 + mat.$matrix.m44 * this.$matrix.m44); + + this.$matrix.m11 = m11; + this.$matrix.m12 = m12; + this.$matrix.m13 = m13; + this.$matrix.m14 = m14; + + this.$matrix.m21 = m21; + this.$matrix.m22 = m22; + this.$matrix.m23 = m23; + this.$matrix.m24 = m24; + + this.$matrix.m31 = m31; + this.$matrix.m32 = m32; + this.$matrix.m33 = m33; + this.$matrix.m34 = m34; + + this.$matrix.m41 = m41; + this.$matrix.m42 = m42; + this.$matrix.m43 = m43; + this.$matrix.m44 = m44; + +} + +J3DIMatrix4.prototype.divide = function(divisor) +{ + this.$matrix.m11 /= divisor; + this.$matrix.m12 /= divisor; + this.$matrix.m13 /= divisor; + this.$matrix.m14 /= divisor; + + this.$matrix.m21 /= divisor; + this.$matrix.m22 /= divisor; + this.$matrix.m23 /= divisor; + this.$matrix.m24 /= divisor; + + this.$matrix.m31 /= divisor; + this.$matrix.m32 /= divisor; + this.$matrix.m33 /= divisor; + this.$matrix.m34 /= divisor; + + this.$matrix.m41 /= divisor; + this.$matrix.m42 /= divisor; + this.$matrix.m43 /= divisor; + this.$matrix.m44 /= divisor; + +} + +J3DIMatrix4.prototype.ortho = function(left, right, bottom, top, near, far) +{ + var tx = (left + right) / (left - right); + var ty = (top + bottom) / (top - bottom); + var tz = (far + near) / (far - near); + + var matrix = new J3DIMatrix4(); + matrix.$matrix.m11 = 2 / (left - right); + matrix.$matrix.m12 = 0; + matrix.$matrix.m13 = 0; + matrix.$matrix.m14 = 0; + matrix.$matrix.m21 = 0; + matrix.$matrix.m22 = 2 / (top - bottom); + matrix.$matrix.m23 = 0; + matrix.$matrix.m24 = 0; + matrix.$matrix.m31 = 0; + matrix.$matrix.m32 = 0; + matrix.$matrix.m33 = -2 / (far - near); + matrix.$matrix.m34 = 0; + matrix.$matrix.m41 = tx; + matrix.$matrix.m42 = ty; + matrix.$matrix.m43 = tz; + matrix.$matrix.m44 = 1; + + this.multiply(matrix); +} + +J3DIMatrix4.prototype.frustum = function(left, right, bottom, top, near, far) +{ + var matrix = new J3DIMatrix4(); + 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); + + matrix.$matrix.m11 = (2 * near) / (right - left); + matrix.$matrix.m12 = 0; + matrix.$matrix.m13 = 0; + matrix.$matrix.m14 = 0; + + matrix.$matrix.m21 = 0; + matrix.$matrix.m22 = 2 * near / (top - bottom); + matrix.$matrix.m23 = 0; + matrix.$matrix.m24 = 0; + + matrix.$matrix.m31 = A; + matrix.$matrix.m32 = B; + matrix.$matrix.m33 = C; + matrix.$matrix.m34 = -1; + + matrix.$matrix.m41 = 0; + matrix.$matrix.m42 = 0; + matrix.$matrix.m43 = D; + matrix.$matrix.m44 = 0; + + this.multiply(matrix); +} + +J3DIMatrix4.prototype.perspective = function(fovy, aspect, zNear, zFar) +{ + var top = Math.tan(fovy * Math.PI / 360) * zNear; + var bottom = -top; + var left = aspect * bottom; + var right = aspect * top; + this.frustum(left, right, bottom, top, zNear, zFar); +} + +J3DIMatrix4.prototype.lookat = function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz) +{ + if (typeof eyez == 'object' && "length" in eyez) { + var t = eyez; + upx = t[0]; + upy = t[1]; + upz = t[2]; + + t = eyey; + centerx = t[0]; + centery = t[1]; + centerz = t[2]; + + t = eyex; + eyex = t[0]; + eyey = t[1]; + eyez = t[2]; + } + + var matrix = new J3DIMatrix4(); + + // Make rotation matrix + + // Z vector + var zx = eyex - centerx; + var zy = eyey - centery; + var zz = eyez - centerz; + var mag = Math.sqrt(zx * zx + zy * zy + zz * zz); + if (mag) { + zx /= mag; + zy /= mag; + zz /= mag; + } + // Y vector + var yx = upx; + var yy = upy; + var yz = upz; + + // X vector = Y cross Z + xx = yy * zz - yz * zy; + xy = -yx * zz + yz * zx; + xz = yx * zy - yy * zx; + + // Recompute Y = Z cross X + yx = zy * xz - zz * xy; + yy = -zx * xz + zz * xx; + yx = zx * xy - zy * xx; + + // cross product gives area of parallelogram, which is < 1.0 for + // non-perpendicular unit-length vectors; so normalize x, y here + + mag = Math.sqrt(xx * xx + xy * xy + xz * xz); + if (mag) { + xx /= mag; + xy /= mag; + xz /= mag; + } + + mag = Math.sqrt(yx * yx + yy * yy + yz * yz); + if (mag) { + yx /= mag; + yy /= mag; + yz /= mag; + } + + matrix.$matrix.m11 = xx; + matrix.$matrix.m12 = xy; + matrix.$matrix.m13 = xz; + matrix.$matrix.m14 = 0; + + matrix.$matrix.m21 = yx; + matrix.$matrix.m22 = yy; + matrix.$matrix.m23 = yz; + matrix.$matrix.m24 = 0; + + matrix.$matrix.m31 = zx; + matrix.$matrix.m32 = zy; + matrix.$matrix.m33 = zz; + matrix.$matrix.m34 = 0; + + matrix.$matrix.m41 = 0; + matrix.$matrix.m42 = 0; + matrix.$matrix.m43 = 0; + matrix.$matrix.m44 = 1; + matrix.translate(-eyex, -eyey, -eyez); + + this.multiply(matrix); +} + +// Returns true on success, false otherwise. All params are Array objects +J3DIMatrix4.prototype.decompose = function(_translate, _rotate, _scale, _skew, _perspective) +{ + // Normalize the matrix. + if (this.$matrix.m44 == 0) + return false; + + // Gather the params + var translate, rotate, scale, skew, perspective; + + var translate = (_translate == undefined || !("length" in _translate)) ? new J3DIVector3 : _translate; + var rotate = (_rotate == undefined || !("length" in _rotate)) ? new J3DIVector3 : _rotate; + var scale = (_scale == undefined || !("length" in _scale)) ? new J3DIVector3 : _scale; + var skew = (_skew == undefined || !("length" in _skew)) ? new J3DIVector3 : _skew; + var perspective = (_perspective == undefined || !("length" in _perspective)) ? new Array(4) : _perspective; + + var matrix = new J3DIMatrix4(this); + + matrix.divide(matrix.$matrix.m44); + + // perspectiveMatrix is used to solve for perspective, but it also provides + // an easy way to test for singularity of the upper 3x3 component. + var perspectiveMatrix = new J3DIMatrix4(matrix); + + perspectiveMatrix.$matrix.m14 = 0; + perspectiveMatrix.$matrix.m24 = 0; + perspectiveMatrix.$matrix.m34 = 0; + perspectiveMatrix.$matrix.m44 = 1; + + if (perspectiveMatrix._determinant4x4() == 0) + return false; + + // First, isolate perspective. + if (matrix.$matrix.m14 != 0 || matrix.$matrix.m24 != 0 || matrix.$matrix.m34 != 0) { + // rightHandSide is the right hand side of the equation. + var rightHandSide = [ matrix.$matrix.m14, matrix.$matrix.m24, matrix.$matrix.m34, matrix.$matrix.m44 ]; + + // Solve the equation by inverting perspectiveMatrix and multiplying + // rightHandSide by the inverse. + var inversePerspectiveMatrix = new J3DIMatrix4(perspectiveMatrix); + inversePerspectiveMatrix.invert(); + var transposedInversePerspectiveMatrix = new J3DIMatrix4(inversePerspectiveMatrix); + transposedInversePerspectiveMatrix.transpose(); + transposedInversePerspectiveMatrix.multVecMatrix(perspective, rightHandSide); + + // Clear the perspective partition + matrix.$matrix.m14 = matrix.$matrix.m24 = matrix.$matrix.m34 = 0 + matrix.$matrix.m44 = 1; + } + else { + // No perspective. + perspective[0] = perspective[1] = perspective[2] = 0; + perspective[3] = 1; + } + + // Next take care of translation + translate[0] = matrix.$matrix.m41 + matrix.$matrix.m41 = 0 + translate[1] = matrix.$matrix.m42 + matrix.$matrix.m42 = 0 + translate[2] = matrix.$matrix.m43 + matrix.$matrix.m43 = 0 + + // Now get scale and shear. 'row' is a 3 element array of 3 component vectors + var row0 = new J3DIVector3(matrix.$matrix.m11, matrix.$matrix.m12, matrix.$matrix.m13); + var row1 = new J3DIVector3(matrix.$matrix.m21, matrix.$matrix.m22, matrix.$matrix.m23); + var row2 = new J3DIVector3(matrix.$matrix.m31, matrix.$matrix.m32, matrix.$matrix.m33); + + // Compute X scale factor and normalize first row. + scale[0] = row0.vectorLength(); + row0.divide(scale[0]); + + // Compute XY shear factor and make 2nd row orthogonal to 1st. + skew[0] = row0.dot(row1); + row1.combine(row0, 1.0, -skew[0]); + + // Now, compute Y scale and normalize 2nd row. + scale[1] = row1.vectorLength(); + row1.divide(scale[1]); + skew[0] /= scale[1]; + + // Compute XZ and YZ shears, orthogonalize 3rd row + skew[1] = row1.dot(row2); + row2.combine(row0, 1.0, -skew[1]); + skew[2] = row1.dot(row2); + row2.combine(row1, 1.0, -skew[2]);