1e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang/*
2e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * Copyright (C) 2009 Apple Inc. All Rights Reserved.
3e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang *
4e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * Redistribution and use in source and binary forms, with or without
5e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * modification, are permitted provided that the following conditions
6e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * are met:
7e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * 1. Redistributions of source code must retain the above copyright
8e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang *    notice, this list of conditions and the following disclaimer.
9e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * 2. Redistributions in binary form must reproduce the above copyright
10e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang *    notice, this list of conditions and the following disclaimer in the
11e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang *    documentation and/or other materials provided with the distribution.
12e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang *
13e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang */
25e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
26e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang // J3DI (Jedi) - A support library for WebGL.
27e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
28e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang/*
29e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    J3DI Math Classes. Currently includes:
30e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
31e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4 - A 4x4 Matrix
32e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang*/
33e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
34e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang/*
35e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    J3DIMatrix4 class
36e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
37e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    This class implements a 4x4 matrix. It has functions which duplicate the
38e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    functionality of the OpenGL matrix stack and glut functions. On browsers
39e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    that support it, CSSMatrix is used to accelerate operations.
40e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
41e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    IDL:
42e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
43e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    [
44e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Constructor(in J3DIMatrix4 matrix),                 // copy passed matrix into new J3DIMatrix4
45e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Constructor(in sequence<float> array)               // create new J3DIMatrix4 with 16 floats (row major)
46e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Constructor()                                       // create new J3DIMatrix4 with identity matrix
47e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    ]
48e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    interface J3DIMatrix4 {
49e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void load(in J3DIMatrix4 matrix);                   // copy the values from the passed matrix
50e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void load(in sequence<float> array);                // copy 16 floats into the matrix
51e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        sequence<float> getAsArray();                       // return the matrix as an array of 16 floats
52e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Float32Array getAsFloat32Array();             // return the matrix as a Float32Array with 16 values
53e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void setUniform(in WebGLRenderingContext ctx,       // Send the matrix to the passed uniform location in the passed context
54e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                        in WebGLUniformLocation loc,
55e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                        in boolean transpose);
56e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void makeIdentity();                                // replace the matrix with identity
57e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void transpose();                                   // replace the matrix with its transpose
58e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void invert();                                      // replace the matrix with its inverse
59e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
60e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void translate(in float x, in float y, in float z); // multiply the matrix by passed translation values on the right
61e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void translate(in J3DVector3 v);                    // multiply the matrix by passed translation values on the right
62e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void scale(in float x, in float y, in float z);     // multiply the matrix by passed scale values on the right
63e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void scale(in J3DVector3 v);                        // multiply the matrix by passed scale values on the right
64e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void rotate(in float angle,                         // multiply the matrix by passed rotation values on the right
65e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                    in float x, in float y, in float z);    // (angle is in degrees)
66e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void rotate(in float angle, in J3DVector3 v);       // multiply the matrix by passed rotation values on the right
67e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                                                            // (angle is in degrees)
68e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void multiply(in CanvasMatrix matrix);              // multiply the matrix by the passed matrix on the right
69e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void divide(in float divisor);                      // divide the matrix by the passed divisor
70e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void ortho(in float left, in float right,           // multiply the matrix by the passed ortho values on the right
71e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                   in float bottom, in float top,
72e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                   in float near, in float far);
73e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void frustum(in float left, in float right,         // multiply the matrix by the passed frustum values on the right
74e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                     in float bottom, in float top,
75e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                     in float near, in float far);
76e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void perspective(in float fovy, in float aspect,    // multiply the matrix by the passed perspective values on the right
77e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                         in float zNear, in float zFar);
78e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void lookat(in J3DVector3 eye,                      // multiply the matrix by the passed lookat
79e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                in J3DVector3 center,  in J3DVector3 up);   // values on the right
80e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang         bool decompose(in J3DVector3 translate,            // decompose the matrix into the passed vector
81e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                        in J3DVector3 rotate,
82e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                        in J3DVector3 scale,
83e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                        in J3DVector3 skew,
84e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                        in sequence<float> perspective);
85e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
86e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
87e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    [
88e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Constructor(in J3DVector3 vector),                  // copy passed vector into new J3DVector3
89e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Constructor(in sequence<float> array)               // create new J3DVector3 with 3 floats from array
90e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Constructor(in float x, in float y, in float z)     // create new J3DVector3 with 3 floats
91e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Constructor()                                       // create new J3DVector3 with (0,0,0)
92e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    ]
93e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    interface J3DVector3 {
94e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void load(in J3DVector3 vector);                    // copy the values from the passed vector
95e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void load(in sequence<float> array);                // copy 3 floats into the vector from array
96e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void load(in float x, in float y, in float z);      // copy 3 floats into the vector
97e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        sequence<float> getAsArray();                       // return the vector as an array of 3 floats
98e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        Float32Array getAsFloat32Array();             // return the matrix as a Float32Array with 16 values
99e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void multMatrix(in J3DIMatrix4 matrix);             // multiply the vector by the passed matrix (on the right)
100e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        float vectorLength();                               // return the length of the vector
101e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        float dot();                                        // return the dot product of the vector
102e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void cross(in J3DVector3 v);                        // replace the vector with vector x v
103e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        void divide(in float divisor);                      // divide the vector by the passed divisor
104e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
105e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang*/
106e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
107e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIHasCSSMatrix = false;
108e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIHasCSSMatrixCopy = false;
109e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang/*
110e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liangif ("WebKitCSSMatrix" in window && ("media" in window && window.media.matchMedium("(-webkit-transform-3d)")) ||
111e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                                   ("styleMedia" in window && window.styleMedia.matchMedium("(-webkit-transform-3d)"))) {
112e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    J3DIHasCSSMatrix = true;
113e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if ("copy" in WebKitCSSMatrix.prototype)
114e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIHasCSSMatrixCopy = true;
115e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
116e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang*/
117e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
118e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang//  console.log("J3DIHasCSSMatrix="+J3DIHasCSSMatrix);
119e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang//  console.log("J3DIHasCSSMatrixCopy="+J3DIHasCSSMatrixCopy);
120e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
121e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang//
122e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang// J3DIMatrix4
123e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang//
124e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4 = function(m)
125e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
126e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrix)
127e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix = new WebKitCSSMatrix;
128e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else
129e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix = new Object;
130e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
131e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (typeof m == 'object') {
132e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if ("length" in m && m.length >= 16) {
133e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.load(m);
134e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            return;
135e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
136e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        else if (m instanceof J3DIMatrix4) {
137e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.load(m);
138e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            return;
139e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
140e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
141e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.makeIdentity();
142e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
143e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
144e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.load = function()
145e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
146e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (arguments.length == 1 && typeof arguments[0] == 'object') {
147e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var matrix;
148e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
149e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if (arguments[0] instanceof J3DIMatrix4) {
150e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            matrix = arguments[0].$matrix;
151e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
152e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m11 = matrix.m11;
153e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m12 = matrix.m12;
154e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m13 = matrix.m13;
155e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m14 = matrix.m14;
156e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
157e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m21 = matrix.m21;
158e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m22 = matrix.m22;
159e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m23 = matrix.m23;
160e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m24 = matrix.m24;
161e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
162e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m31 = matrix.m31;
163e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m32 = matrix.m32;
164e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m33 = matrix.m33;
165e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m34 = matrix.m34;
166e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
167e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m41 = matrix.m41;
168e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m42 = matrix.m42;
169e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m43 = matrix.m43;
170e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m44 = matrix.m44;
171e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            return;
172e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
173e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        else
174e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            matrix = arguments[0];
175e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
176e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if ("length" in matrix && matrix.length >= 16) {
177e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m11 = matrix[0];
178e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m12 = matrix[1];
179e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m13 = matrix[2];
180e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m14 = matrix[3];
181e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
182e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m21 = matrix[4];
183e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m22 = matrix[5];
184e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m23 = matrix[6];
185e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m24 = matrix[7];
186e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
187e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m31 = matrix[8];
188e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m32 = matrix[9];
189e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m33 = matrix[10];
190e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m34 = matrix[11];
191e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
192e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m41 = matrix[12];
193e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m42 = matrix[13];
194e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m43 = matrix[14];
195e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.$matrix.m44 = matrix[15];
196e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            return;
197e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
198e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
199e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
200e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.makeIdentity();
201e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
202e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
203e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.getAsArray = function()
204e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
205e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return [
206e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix.m11, this.$matrix.m12, this.$matrix.m13, this.$matrix.m14,
207e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix.m21, this.$matrix.m22, this.$matrix.m23, this.$matrix.m24,
208e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix.m31, this.$matrix.m32, this.$matrix.m33, this.$matrix.m34,
209e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix.m41, this.$matrix.m42, this.$matrix.m43, this.$matrix.m44
210e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    ];
211e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
212e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
213e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.getAsFloat32Array = function()
214e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
215e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrixCopy) {
216e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var array = new Float32Array(16);
217e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix.copy(array);
218e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return array;
219e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
220e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return new Float32Array(this.getAsArray());
221e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
222e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
223e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.setUniform = function(ctx, loc, transpose)
224e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
225e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIMatrix4.setUniformArray == undefined) {
226e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformWebGLArray = new Float32Array(16);
227e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray = new Array(16);
228e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
229e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
230e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrixCopy)
231e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix.copy(J3DIMatrix4.setUniformWebGLArray);
232e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else {
233e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[0] = this.$matrix.m11;
234e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[1] = this.$matrix.m12;
235e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[2] = this.$matrix.m13;
236e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[3] = this.$matrix.m14;
237e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[4] = this.$matrix.m21;
238e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[5] = this.$matrix.m22;
239e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[6] = this.$matrix.m23;
240e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[7] = this.$matrix.m24;
241e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[8] = this.$matrix.m31;
242e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[9] = this.$matrix.m32;
243e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[10] = this.$matrix.m33;
244e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[11] = this.$matrix.m34;
245e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[12] = this.$matrix.m41;
246e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[13] = this.$matrix.m42;
247e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[14] = this.$matrix.m43;
248e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformArray[15] = this.$matrix.m44;
249e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
250e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        J3DIMatrix4.setUniformWebGLArray.set(J3DIMatrix4.setUniformArray);
251e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
252e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
253e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    ctx.uniformMatrix4fv(loc, transpose, J3DIMatrix4.setUniformWebGLArray);
254e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
255e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
256e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.makeIdentity = function()
257e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
258e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m11 = 1;
259e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m12 = 0;
260e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m13 = 0;
261e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m14 = 0;
262e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
263e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m21 = 0;
264e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m22 = 1;
265e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m23 = 0;
266e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m24 = 0;
267e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
268e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m31 = 0;
269e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m32 = 0;
270e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m33 = 1;
271e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m34 = 0;
272e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
273e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m41 = 0;
274e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m42 = 0;
275e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m43 = 0;
276e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m44 = 1;
277e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
278e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
279e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.transpose = function()
280e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
281e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var tmp = this.$matrix.m12;
282e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m12 = this.$matrix.m21;
283e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m21 = tmp;
284e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
285e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    tmp = this.$matrix.m13;
286e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m13 = this.$matrix.m31;
287e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m31 = tmp;
288e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
289e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    tmp = this.$matrix.m14;
290e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m14 = this.$matrix.m41;
291e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m41 = tmp;
292e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
293e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    tmp = this.$matrix.m23;
294e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m23 = this.$matrix.m32;
295e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m32 = tmp;
296e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
297e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    tmp = this.$matrix.m24;
298e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m24 = this.$matrix.m42;
299e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m42 = tmp;
300e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
301e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    tmp = this.$matrix.m34;
302e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m34 = this.$matrix.m43;
303e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m43 = tmp;
304e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
305e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
306e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.invert = function()
307e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
308e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrix) {
309e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix = this.$matrix.inverse();
310e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return;
311e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
312e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
313e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Calculate the 4x4 determinant
314e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // If the determinant is zero,
315e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // then the inverse matrix is not unique.
316e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var det = this._determinant4x4();
317e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
318e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (Math.abs(det) < 1e-8)
319e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return null;
320e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
321e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this._makeAdjoint();
322e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
323e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Scale the adjoint matrix to get the inverse
324e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m11 /= det;
325e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m12 /= det;
326e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m13 /= det;
327e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m14 /= det;
328e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
329e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m21 /= det;
330e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m22 /= det;
331e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m23 /= det;
332e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m24 /= det;
333e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
334e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m31 /= det;
335e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m32 /= det;
336e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m33 /= det;
337e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m34 /= det;
338e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
339e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m41 /= det;
340e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m42 /= det;
341e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m43 /= det;
342e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m44 /= det;
343e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
344e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
345e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.translate = function(x,y,z)
346e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
347e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (typeof x == 'object' && "length" in x) {
348e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var t = x;
349e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        x = t[0];
350e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        y = t[1];
351e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        z = t[2];
352e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
353e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else {
354e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if (x == undefined)
355e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            x = 0;
356e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if (y == undefined)
357e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            y = 0;
358e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if (z == undefined)
359e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            z = 0;
360e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
361e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
362e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrix) {
363e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix = this.$matrix.translate(x, y, z);
364e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return;
365e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
366e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
367e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var matrix = new J3DIMatrix4();
368e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m41 = x;
369e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m42 = y;
370e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m43 = z;
371e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
372e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.multiply(matrix);
373e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
374e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
375e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.scale = function(x,y,z)
376e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
377e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (typeof x == 'object' && "length" in x) {
378e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var t = x;
379e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        x = t[0];
380e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        y = t[1];
381e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        z = t[2];
382e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
383e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else {
384e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if (x == undefined)
385e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            x = 1;
386e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if (z == undefined) {
387e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            if (y == undefined) {
388e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                y = x;
389e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                z = x;
390e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            }
391e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            else
392e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang                z = 1;
393e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
394e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        else if (y == undefined)
395e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            y = x;
396e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
397e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
398e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrix) {
399e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix = this.$matrix.scale(x, y, z);
400e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return;
401e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
402e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
403e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var matrix = new J3DIMatrix4();
404e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m11 = x;
405e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m22 = y;
406e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m33 = z;
407e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
408e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.multiply(matrix);
409e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
410e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
411e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.rotate = function(angle,x,y,z)
412e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
413e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Forms are (angle, x,y,z), (angle,vector), (angleX, angleY, angleZ), (angle)
414e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (typeof x == 'object' && "length" in x) {
415e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var t = x;
416e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        x = t[0];
417e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        y = t[1];
418e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        z = t[2];
419e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
420e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else {
421e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        if (arguments.length == 1) {
422e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            x = 0;
423e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            y = 0;
424e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            z = 1;
425e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
426e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        else if (arguments.length == 3) {
427e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.rotate(angle, 1,0,0); // about X axis
428e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.rotate(x, 0,1,0); // about Y axis
429e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            this.rotate(y, 0,0,1); // about Z axis
430e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            return;
431e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
432e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
433e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
434e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrix) {
435e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix = this.$matrix.rotateAxisAngle(x, y, z, angle);
436e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return;
437e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
438e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
439e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // angles are in degrees. Switch to radians
440e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    angle = angle / 180 * Math.PI;
441e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
442e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    angle /= 2;
443e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var sinA = Math.sin(angle);
444e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var cosA = Math.cos(angle);
445e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var sinA2 = sinA * sinA;
446e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
447e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // normalize
448e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var len = Math.sqrt(x * x + y * y + z * z);
449e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (len == 0) {
450e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        // bad vector, just use something reasonable
451e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        x = 0;
452e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        y = 0;
453e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        z = 1;
454e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    } else if (len != 1) {
455e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        x /= len;
456e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        y /= len;
457e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        z /= len;
458e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
459e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
460e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var mat = new J3DIMatrix4();
461e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
462e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // optimize case where axis is along major axis
463e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (x == 1 && y == 0 && z == 0) {
464e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m11 = 1;
465e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m12 = 0;
466e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m13 = 0;
467e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m21 = 0;
468e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m22 = 1 - 2 * sinA2;
469e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m23 = 2 * sinA * cosA;
470e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m31 = 0;
471e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m32 = -2 * sinA * cosA;
472e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m33 = 1 - 2 * sinA2;
473e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
474e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
475e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m44 = 1;
476e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    } else if (x == 0 && y == 1 && z == 0) {
477e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m11 = 1 - 2 * sinA2;
478e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m12 = 0;
479e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m13 = -2 * sinA * cosA;
480e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m21 = 0;
481e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m22 = 1;
482e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m23 = 0;
483e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m31 = 2 * sinA * cosA;
484e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m32 = 0;
485e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m33 = 1 - 2 * sinA2;
486e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
487e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
488e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m44 = 1;
489e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    } else if (x == 0 && y == 0 && z == 1) {
490e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m11 = 1 - 2 * sinA2;
491e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m12 = 2 * sinA * cosA;
492e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m13 = 0;
493e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m21 = -2 * sinA * cosA;
494e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m22 = 1 - 2 * sinA2;
495e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m23 = 0;
496e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m31 = 0;
497e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m32 = 0;
498e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m33 = 1;
499e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
500e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
501e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m44 = 1;
502e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    } else {
503e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var x2 = x*x;
504e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var y2 = y*y;
505e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var z2 = z*z;
506e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
507e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m11 = 1 - 2 * (y2 + z2) * sinA2;
508e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m12 = 2 * (x * y * sinA2 + z * sinA * cosA);
509e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m13 = 2 * (x * z * sinA2 - y * sinA * cosA);
510e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m21 = 2 * (y * x * sinA2 - z * sinA * cosA);
511e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m22 = 1 - 2 * (z2 + x2) * sinA2;
512e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m23 = 2 * (y * z * sinA2 + x * sinA * cosA);
513e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m31 = 2 * (z * x * sinA2 + y * sinA * cosA);
514e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m32 = 2 * (z * y * sinA2 - x * sinA * cosA);
515e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m33 = 1 - 2 * (x2 + y2) * sinA2;
516e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
517e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
518e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        mat.$matrix.m44 = 1;
519e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
520e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.multiply(mat);
521e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
522e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
523e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.multiply = function(mat)
524e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
525e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (J3DIHasCSSMatrix) {
526e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this.$matrix = this.$matrix.multiply(mat.$matrix);
527e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return;
528e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
529e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
530e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m11 = (mat.$matrix.m11 * this.$matrix.m11 + mat.$matrix.m12 * this.$matrix.m21
531e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m13 * this.$matrix.m31 + mat.$matrix.m14 * this.$matrix.m41);
532e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m12 = (mat.$matrix.m11 * this.$matrix.m12 + mat.$matrix.m12 * this.$matrix.m22
533e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m13 * this.$matrix.m32 + mat.$matrix.m14 * this.$matrix.m42);
534e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m13 = (mat.$matrix.m11 * this.$matrix.m13 + mat.$matrix.m12 * this.$matrix.m23
535e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m13 * this.$matrix.m33 + mat.$matrix.m14 * this.$matrix.m43);
536e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m14 = (mat.$matrix.m11 * this.$matrix.m14 + mat.$matrix.m12 * this.$matrix.m24
537e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m13 * this.$matrix.m34 + mat.$matrix.m14 * this.$matrix.m44);
538e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
539e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m21 = (mat.$matrix.m21 * this.$matrix.m11 + mat.$matrix.m22 * this.$matrix.m21
540e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m23 * this.$matrix.m31 + mat.$matrix.m24 * this.$matrix.m41);
541e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m22 = (mat.$matrix.m21 * this.$matrix.m12 + mat.$matrix.m22 * this.$matrix.m22
542e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m23 * this.$matrix.m32 + mat.$matrix.m24 * this.$matrix.m42);
543e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m23 = (mat.$matrix.m21 * this.$matrix.m13 + mat.$matrix.m22 * this.$matrix.m23
544e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m23 * this.$matrix.m33 + mat.$matrix.m24 * this.$matrix.m43);
545e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m24 = (mat.$matrix.m21 * this.$matrix.m14 + mat.$matrix.m22 * this.$matrix.m24
546e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m23 * this.$matrix.m34 + mat.$matrix.m24 * this.$matrix.m44);
547e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
548e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m31 = (mat.$matrix.m31 * this.$matrix.m11 + mat.$matrix.m32 * this.$matrix.m21
549e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m33 * this.$matrix.m31 + mat.$matrix.m34 * this.$matrix.m41);
550e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m32 = (mat.$matrix.m31 * this.$matrix.m12 + mat.$matrix.m32 * this.$matrix.m22
551e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m33 * this.$matrix.m32 + mat.$matrix.m34 * this.$matrix.m42);
552e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m33 = (mat.$matrix.m31 * this.$matrix.m13 + mat.$matrix.m32 * this.$matrix.m23
553e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m33 * this.$matrix.m33 + mat.$matrix.m34 * this.$matrix.m43);
554e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m34 = (mat.$matrix.m31 * this.$matrix.m14 + mat.$matrix.m32 * this.$matrix.m24
555e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m33 * this.$matrix.m34 + mat.$matrix.m34 * this.$matrix.m44);
556e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
557e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m41 = (mat.$matrix.m41 * this.$matrix.m11 + mat.$matrix.m42 * this.$matrix.m21
558e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m43 * this.$matrix.m31 + mat.$matrix.m44 * this.$matrix.m41);
559e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m42 = (mat.$matrix.m41 * this.$matrix.m12 + mat.$matrix.m42 * this.$matrix.m22
560e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m43 * this.$matrix.m32 + mat.$matrix.m44 * this.$matrix.m42);
561e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m43 = (mat.$matrix.m41 * this.$matrix.m13 + mat.$matrix.m42 * this.$matrix.m23
562e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m43 * this.$matrix.m33 + mat.$matrix.m44 * this.$matrix.m43);
563e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var m44 = (mat.$matrix.m41 * this.$matrix.m14 + mat.$matrix.m42 * this.$matrix.m24
564e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang               + mat.$matrix.m43 * this.$matrix.m34 + mat.$matrix.m44 * this.$matrix.m44);
565e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
566e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m11 = m11;
567e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m12 = m12;
568e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m13 = m13;
569e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m14 = m14;
570e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
571e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m21 = m21;
572e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m22 = m22;
573e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m23 = m23;
574e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m24 = m24;
575e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
576e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m31 = m31;
577e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m32 = m32;
578e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m33 = m33;
579e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m34 = m34;
580e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
581e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m41 = m41;
582e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m42 = m42;
583e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m43 = m43;
584e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m44 = m44;
585e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
586e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
587e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.divide = function(divisor)
588e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
589e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m11 /= divisor;
590e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m12 /= divisor;
591e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m13 /= divisor;
592e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m14 /= divisor;
593e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
594e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m21 /= divisor;
595e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m22 /= divisor;
596e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m23 /= divisor;
597e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m24 /= divisor;
598e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
599e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m31 /= divisor;
600e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m32 /= divisor;
601e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m33 /= divisor;
602e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m34 /= divisor;
603e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
604e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m41 /= divisor;
605e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m42 /= divisor;
606e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m43 /= divisor;
607e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m44 /= divisor;
608e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
609e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
610e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
611e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.ortho = function(left, right, bottom, top, near, far)
612e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
613e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var tx = (left + right) / (left - right);
614e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var ty = (top + bottom) / (top - bottom);
615e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var tz = (far + near) / (far - near);
616e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
617e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var matrix = new J3DIMatrix4();
618e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m11 = 2 / (left - right);
619e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m12 = 0;
620e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m13 = 0;
621e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m14 = 0;
622e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m21 = 0;
623e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m22 = 2 / (top - bottom);
624e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m23 = 0;
625e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m24 = 0;
626e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m31 = 0;
627e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m32 = 0;
628e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m33 = -2 / (far - near);
629e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m34 = 0;
630e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m41 = tx;
631e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m42 = ty;
632e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m43 = tz;
633e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m44 = 1;
634e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
635e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.multiply(matrix);
636e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
637e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
638e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.frustum = function(left, right, bottom, top, near, far)
639e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
640e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var matrix = new J3DIMatrix4();
641e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var A = (right + left) / (right - left);
642e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var B = (top + bottom) / (top - bottom);
643e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var C = -(far + near) / (far - near);
644e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var D = -(2 * far * near) / (far - near);
645e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
646e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m11 = (2 * near) / (right - left);
647e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m12 = 0;
648e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m13 = 0;
649e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m14 = 0;
650e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
651e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m21 = 0;
652e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m22 = 2 * near / (top - bottom);
653e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m23 = 0;
654e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m24 = 0;
655e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
656e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m31 = A;
657e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m32 = B;
658e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m33 = C;
659e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m34 = -1;
660e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
661e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m41 = 0;
662e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m42 = 0;
663e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m43 = D;
664e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m44 = 0;
665e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
666e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.multiply(matrix);
667e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
668e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
669e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.perspective = function(fovy, aspect, zNear, zFar)
670e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
671e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var top = Math.tan(fovy * Math.PI / 360) * zNear;
672e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var bottom = -top;
673e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var left = aspect * bottom;
674e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var right = aspect * top;
675e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.frustum(left, right, bottom, top, zNear, zFar);
676e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
677e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
678e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.lookat = function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
679e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
680e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (typeof eyez == 'object' && "length" in eyez) {
681e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var t = eyez;
682e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        upx = t[0];
683e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        upy = t[1];
684e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        upz = t[2];
685e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
686e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        t = eyey;
687e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        centerx = t[0];
688e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        centery = t[1];
689e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        centerz = t[2];
690e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
691e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        t = eyex;
692e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        eyex = t[0];
693e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        eyey = t[1];
694e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        eyez = t[2];
695e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
696e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
697e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var matrix = new J3DIMatrix4();
698e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
699e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Make rotation matrix
700e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
701e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Z vector
702e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var zx = eyex - centerx;
703e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var zy = eyey - centery;
704e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var zz = eyez - centerz;
705e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var mag = Math.sqrt(zx * zx + zy * zy + zz * zz);
706e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (mag) {
707e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        zx /= mag;
708e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        zy /= mag;
709e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        zz /= mag;
710e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
711e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
712e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Y vector
713e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var yx = upx;
714e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var yy = upy;
715e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var yz = upz;
716e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
717e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // X vector = Y cross Z
718e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    xx =  yy * zz - yz * zy;
719e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    xy = -yx * zz + yz * zx;
720e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    xz =  yx * zy - yy * zx;
721e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
722e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Recompute Y = Z cross X
723e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    yx = zy * xz - zz * xy;
724e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    yy = -zx * xz + zz * xx;
725e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    yx = zx * xy - zy * xx;
726e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
727e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // cross product gives area of parallelogram, which is < 1.0 for
728e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // non-perpendicular unit-length vectors; so normalize x, y here
729e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
730e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    mag = Math.sqrt(xx * xx + xy * xy + xz * xz);
731e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (mag) {
732e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        xx /= mag;
733e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        xy /= mag;
734e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        xz /= mag;
735e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
736e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
737e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    mag = Math.sqrt(yx * yx + yy * yy + yz * yz);
738e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (mag) {
739e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        yx /= mag;
740e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        yy /= mag;
741e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        yz /= mag;
742e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
743e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
744e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m11 = xx;
745e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m12 = xy;
746e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m13 = xz;
747e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m14 = 0;
748e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
749e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m21 = yx;
750e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m22 = yy;
751e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m23 = yz;
752e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m24 = 0;
753e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
754e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m31 = zx;
755e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m32 = zy;
756e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m33 = zz;
757e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m34 = 0;
758e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
759e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m41 = 0;
760e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m42 = 0;
761e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m43 = 0;
762e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m44 = 1;
763e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.translate(-eyex, -eyey, -eyez);
764e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
765e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.multiply(matrix);
766e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
767e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
768e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang// Returns true on success, false otherwise. All params are Array objects
769e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype.decompose = function(_translate, _rotate, _scale, _skew, _perspective)
770e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
771e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Normalize the matrix.
772e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (this.$matrix.m44 == 0)
773e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return false;
774e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
775e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Gather the params
776e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var translate, rotate, scale, skew, perspective;
777e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
778e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var translate = (_translate == undefined || !("length" in _translate)) ? new J3DIVector3 : _translate;
779e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var rotate = (_rotate == undefined || !("length" in _rotate)) ? new J3DIVector3 : _rotate;
780e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var scale = (_scale == undefined || !("length" in _scale)) ? new J3DIVector3 : _scale;
781e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var skew = (_skew == undefined || !("length" in _skew)) ? new J3DIVector3 : _skew;
782e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var perspective = (_perspective == undefined || !("length" in _perspective)) ? new Array(4) : _perspective;
783e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
784e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var matrix = new J3DIMatrix4(this);
785e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
786e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.divide(matrix.$matrix.m44);
787e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
788e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // perspectiveMatrix is used to solve for perspective, but it also provides
789e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // an easy way to test for singularity of the upper 3x3 component.
790e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var perspectiveMatrix = new J3DIMatrix4(matrix);
791e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
792e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    perspectiveMatrix.$matrix.m14 = 0;
793e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    perspectiveMatrix.$matrix.m24 = 0;
794e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    perspectiveMatrix.$matrix.m34 = 0;
795e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    perspectiveMatrix.$matrix.m44 = 1;
796e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
797e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (perspectiveMatrix._determinant4x4() == 0)
798e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        return false;
799e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
800e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // First, isolate perspective.
801e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (matrix.$matrix.m14 != 0 || matrix.$matrix.m24 != 0 || matrix.$matrix.m34 != 0) {
802e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        // rightHandSide is the right hand side of the equation.
803e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var rightHandSide = [ matrix.$matrix.m14, matrix.$matrix.m24, matrix.$matrix.m34, matrix.$matrix.m44 ];
804e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
805e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        // Solve the equation by inverting perspectiveMatrix and multiplying
806e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        // rightHandSide by the inverse.
807e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var inversePerspectiveMatrix = new J3DIMatrix4(perspectiveMatrix);
808e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        inversePerspectiveMatrix.invert();
809e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        var transposedInversePerspectiveMatrix = new J3DIMatrix4(inversePerspectiveMatrix);
810e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        transposedInversePerspectiveMatrix.transpose();
811e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        transposedInversePerspectiveMatrix.multVecMatrix(perspective, rightHandSide);
812e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
813e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        // Clear the perspective partition
814e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        matrix.$matrix.m14 = matrix.$matrix.m24 = matrix.$matrix.m34 = 0
815e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        matrix.$matrix.m44 = 1;
816e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
817e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else {
818e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        // No perspective.
819e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        perspective[0] = perspective[1] = perspective[2] = 0;
820e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        perspective[3] = 1;
821e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
822e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
823e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Next take care of translation
824e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    translate[0] = matrix.$matrix.m41
825e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m41 = 0
826e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    translate[1] = matrix.$matrix.m42
827e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m42 = 0
828e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    translate[2] = matrix.$matrix.m43
829e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    matrix.$matrix.m43 = 0
830e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
831e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Now get scale and shear. 'row' is a 3 element array of 3 component vectors
832e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var row0 = new J3DIVector3(matrix.$matrix.m11, matrix.$matrix.m12, matrix.$matrix.m13);
833e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var row1 = new J3DIVector3(matrix.$matrix.m21, matrix.$matrix.m22, matrix.$matrix.m23);
834e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var row2 = new J3DIVector3(matrix.$matrix.m31, matrix.$matrix.m32, matrix.$matrix.m33);
835e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
836e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Compute X scale factor and normalize first row.
837e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    scale[0] = row0.vectorLength();
838e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    row0.divide(scale[0]);
839e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
840e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Compute XY shear factor and make 2nd row orthogonal to 1st.
841e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    skew[0] = row0.dot(row1);
842e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    row1.combine(row0, 1.0, -skew[0]);
843e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
844e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Now, compute Y scale and normalize 2nd row.
845e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    scale[1] = row1.vectorLength();
846e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    row1.divide(scale[1]);
847e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    skew[0] /= scale[1];
848e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
849e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Compute XZ and YZ shears, orthogonalize 3rd row
850e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    skew[1] = row1.dot(row2);
851e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    row2.combine(row0, 1.0, -skew[1]);
852e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    skew[2] = row1.dot(row2);
853e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    row2.combine(row1, 1.0, -skew[2]);
854e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
855e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Next, get Z scale and normalize 3rd row.
856e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    scale[2] = row2.vectorLength();
857e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    row2.divide(scale[2]);
858e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    skew[1] /= scale[2];
859e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    skew[2] /= scale[2];
860e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
861e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // At this point, the matrix (in rows) is orthonormal.
862e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Check for a coordinate system flip.  If the determinant
863e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // is -1, then negate the matrix and the scaling factors.
864e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var pdum3 = new J3DIVector3(row1);
865e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    pdum3.cross(row2);
866e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (row0.dot(pdum3) < 0) {
867e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        for (i = 0; i < 3; i++) {
868e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            scale[i] *= -1;
869e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            row[0][i] *= -1;
870e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            row[1][i] *= -1;
871e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang            row[2][i] *= -1;
872e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        }
873e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
874e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
875e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Now, get the rotations out
876e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    rotate[1] = Math.asin(-row0[2]);
877e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (Math.cos(rotate[1]) != 0) {
878e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        rotate[0] = Math.atan2(row1[2], row2[2]);
879e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        rotate[2] = Math.atan2(row0[1], row0[0]);
880e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
881e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else {
882e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        rotate[0] = Math.atan2(-row2[0], row1[1]);
883e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        rotate[2] = 0;
884e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
885e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
886e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Convert rotations to degrees
887e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var rad2deg = 180 / Math.PI;
888e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    rotate[0] *= rad2deg;
889e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    rotate[1] *= rad2deg;
890e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    rotate[2] *= rad2deg;
891e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
892e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return true;
893e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
894e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
895e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype._determinant2x2 = function(a, b, c, d)
896e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
897e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return a * d - b * c;
898e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
899e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
900e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype._determinant3x3 = function(a1, a2, a3, b1, b2, b3, c1, c2, c3)
901e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
902e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return a1 * this._determinant2x2(b2, b3, c2, c3)
903e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang         - b1 * this._determinant2x2(a2, a3, c2, c3)
904e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang         + c1 * this._determinant2x2(a2, a3, b2, b3);
905e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
906e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
907e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype._determinant4x4 = function()
908e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
909e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a1 = this.$matrix.m11;
910e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b1 = this.$matrix.m12;
911e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c1 = this.$matrix.m13;
912e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d1 = this.$matrix.m14;
913e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
914e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a2 = this.$matrix.m21;
915e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b2 = this.$matrix.m22;
916e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c2 = this.$matrix.m23;
917e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d2 = this.$matrix.m24;
918e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
919e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a3 = this.$matrix.m31;
920e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b3 = this.$matrix.m32;
921e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c3 = this.$matrix.m33;
922e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d3 = this.$matrix.m34;
923e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
924e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a4 = this.$matrix.m41;
925e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b4 = this.$matrix.m42;
926e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c4 = this.$matrix.m43;
927e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d4 = this.$matrix.m44;
928e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
929e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return a1 * this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)
930e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang         - b1 * this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)
931e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang         + c1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)
932e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang         - d1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
933e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
934e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
935e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIMatrix4.prototype._makeAdjoint = function()
936e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
937e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a1 = this.$matrix.m11;
938e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b1 = this.$matrix.m12;
939e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c1 = this.$matrix.m13;
940e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d1 = this.$matrix.m14;
941e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
942e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a2 = this.$matrix.m21;
943e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b2 = this.$matrix.m22;
944e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c2 = this.$matrix.m23;
945e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d2 = this.$matrix.m24;
946e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
947e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a3 = this.$matrix.m31;
948e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b3 = this.$matrix.m32;
949e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c3 = this.$matrix.m33;
950e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d3 = this.$matrix.m34;
951e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
952e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var a4 = this.$matrix.m41;
953e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var b4 = this.$matrix.m42;
954e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var c4 = this.$matrix.m43;
955e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var d4 = this.$matrix.m44;
956e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
957e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    // Row column labeling reversed since we transpose rows & columns
958e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m11  =   this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
959e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m21  = - this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
960e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m31  =   this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
961e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m41  = - this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
962e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
963e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m12  = - this._determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
964e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m22  =   this._determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
965e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m32  = - this._determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
966e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m42  =   this._determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
967e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
968e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m13  =   this._determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
969e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m23  = - this._determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
970e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m33  =   this._determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
971e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m43  = - this._determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
972e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
973e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m14  = - this._determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
974e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m24  =   this._determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
975e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m34  = - this._determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
976e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.$matrix.m44  =   this._determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
977e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
978e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
979e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang//
980e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang// J3DIVector3
981e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang//
982e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3 = function(x,y,z)
983e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
984e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this.load(x,y,z);
985e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
986e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
987e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.load = function(x,y,z)
988e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
989e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (typeof x == 'object' && "length" in x) {
990e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[0] = x[0];
991e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[1] = x[1];
992e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[2] = x[2];
993e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
994e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else if (typeof x == 'number') {
995e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[0] = x;
996e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[1] = y;
997e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[2] = z;
998e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
999e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    else {
1000e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[0] = 0;
1001e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[1] = 0;
1002e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[2] = 0;
1003e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
1004e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1005e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1006e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.getAsArray = function()
1007e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1008e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return [ this[0], this[1], this[2] ];
1009e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1010e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1011e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.getAsFloat32Array = function()
1012e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1013e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return new Float32Array(this.getAsArray());
1014e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1015e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1016e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.vectorLength = function()
1017e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1018e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return Math.sqrt(this[0] * this[0] + this[1] * this[1] + this[2] * this[2]);
1019e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1020e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1021e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.divide = function(divisor)
1022e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1023e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[0] /= divisor; this[1] /= divisor; this[2] /= divisor;
1024e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1025e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1026e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.cross = function(v)
1027e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1028e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[0] =  this[1] * v[2] - this[2] * v[1];
1029e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[1] = -this[0] * v[2] + this[2] * v[0];
1030e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[2] =  this[0] * v[1] - this[1] * v[0];
1031e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1032e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1033e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.dot = function(v)
1034e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1035e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return this[0] * v[0] + this[1] * v[1] + this[2] * v[2];
1036e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1037e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1038e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.combine = function(v, ascl, bscl)
1039e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1040e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[0] = (ascl * this[0]) + (bscl * v[0]);
1041e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[1] = (ascl * this[1]) + (bscl * v[1]);
1042e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[2] = (ascl * this[2]) + (bscl * v[2]);
1043e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1044e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1045e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.multVecMatrix = function(matrix)
1046e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1047e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var x = this[0];
1048e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var y = this[1];
1049e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var z = this[2];
1050e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1051e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[0] = matrix.$matrix.m41 + x * matrix.$matrix.m11 + y * matrix.$matrix.m21 + z * matrix.$matrix.m31;
1052e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[1] = matrix.$matrix.m42 + x * matrix.$matrix.m12 + y * matrix.$matrix.m22 + z * matrix.$matrix.m32;
1053e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    this[2] = matrix.$matrix.m43 + x * matrix.$matrix.m13 + y * matrix.$matrix.m23 + z * matrix.$matrix.m33;
1054e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    var w = matrix.$matrix.m44 + x * matrix.$matrix.m14 + y * matrix.$matrix.m24 + z * matrix.$matrix.m34;
1055e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    if (w != 1 && w != 0) {
1056e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[0] /= w;
1057e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[1] /= w;
1058e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang        this[2] /= w;
1059e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    }
1060e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1061e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang
1062e15aa36789a41772d5689bc7610d45736eae60d0Ricky LiangJ3DIVector3.prototype.toString = function()
1063e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang{
1064e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang    return "["+this[0]+","+this[1]+","+this[2]+"]";
1065e15aa36789a41772d5689bc7610d45736eae60d0Ricky Liang}
1066