mirror of
https://github.com/tiennm99/fbird.git
synced 2026-09-03 08:18:48 +00:00
1012 lines
35 KiB
JavaScript
Vendored
1012 lines
35 KiB
JavaScript
Vendored
/**
|
|
Copyright (c) 2008-2010 Ricardo Quesada
|
|
Copyright (c) 2011-2012 cocos2d-x.org
|
|
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
|
Copyright (c) 2008, Luke Benstead.
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
(function(cc) {
|
|
/**
|
|
* <p>
|
|
* A 4x4 matrix </br>
|
|
* </br>
|
|
* mat = </br>
|
|
* | 0 4 8 12 | </br>
|
|
* | 1 5 9 13 | </br>
|
|
* | 2 6 10 14 | </br>
|
|
* | 3 7 11 15 |
|
|
* </p>
|
|
* @class
|
|
* @param {cc.math.Matrix4} [mat4]
|
|
*/
|
|
cc.math.Matrix4 = function (mat4) {
|
|
if(mat4 && mat4.mat){
|
|
this.mat = new Float32Array(mat4.mat);
|
|
} else {
|
|
this.mat = new Float32Array(16);
|
|
}
|
|
};
|
|
cc.kmMat4 = cc.math.Matrix4;
|
|
var proto = cc.math.Matrix4.prototype;
|
|
|
|
/**
|
|
* Fills a cc.math.Matrix4 structure with the values from a 16 element array of floats
|
|
* @param {Array} scalarArr
|
|
*/
|
|
proto.fill = function(scalarArr){ //cc.kmMat4Fill
|
|
var mat = this.mat;
|
|
for(var i = 0; i < 16; i++){
|
|
mat[i] = scalarArr[i];
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Sets pOut to an identity matrix returns pOut
|
|
* @param pOut - A pointer to the matrix to set to identity
|
|
* @returns Returns pOut so that the call can be nested
|
|
*/
|
|
cc.kmMat4Identity = function (pOut) {
|
|
var mat = pOut.mat;
|
|
mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7]
|
|
= mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
|
|
mat[0] = mat[5] = mat[10] = mat[15] = 1.0;
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* Sets matrix to identity value.
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
proto.identity = function(){
|
|
var mat = this.mat;
|
|
mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7]
|
|
= mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
|
|
mat[0] = mat[5] = mat[10] = mat[15] = 1.0;
|
|
return this;
|
|
};
|
|
|
|
proto.get = function(row, col){
|
|
return this.mat[row + 4 * col];
|
|
};
|
|
|
|
proto.set = function(row, col, value){
|
|
this.mat[row + 4 * col] = value;
|
|
};
|
|
|
|
proto.swap = function(r1, c1, r2, c2) {
|
|
/* var tmp = this.get(r1, c1);
|
|
this.set(r1, c1, this.get(r2, c2));
|
|
this.set(r2, c2, tmp);*/
|
|
var mat = this.mat, tmp = mat[r1 + 4 * c1];
|
|
mat[r1 + 4 * c1] = mat[r2 + 4 * c2];
|
|
mat[r2 + 4 * c2] = tmp;
|
|
};
|
|
|
|
//Returns an upper and a lower triangular matrix which are L and R in the Gauss algorithm
|
|
cc.math.Matrix4._gaussj = function (a, b) {
|
|
var i, icol = 0, irow = 0, j, k, l, ll, n = 4, m = 4, selElement;
|
|
var big, dumb, pivinv;
|
|
var indxc = [0, 0, 0, 0], indxr = [0, 0, 0, 0], ipiv = [0, 0, 0, 0];
|
|
|
|
/* for (j = 0; j < n; j++) {
|
|
ipiv[j] = 0;
|
|
}*/
|
|
|
|
for (i = 0; i < n; i++) {
|
|
big = 0.0;
|
|
for (j = 0; j < n; j++) {
|
|
if (ipiv[j] !== 1) {
|
|
for (k = 0; k < n; k++) {
|
|
if (ipiv[k] === 0) {
|
|
selElement = Math.abs(a.get(j, k));
|
|
if (selElement >= big) {
|
|
big = selElement;
|
|
irow = j;
|
|
icol = k;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
++(ipiv[icol]);
|
|
if (irow !== icol) {
|
|
for (l = 0; l < n; l++)
|
|
a.swap(irow, l, icol, l);
|
|
for (l = 0; l < m; l++)
|
|
b.swap(irow, l, icol, l);
|
|
}
|
|
indxr[i] = irow;
|
|
indxc[i] = icol;
|
|
if (a.get(icol, icol) === 0.0)
|
|
return false;
|
|
|
|
pivinv = 1.0 / a.get(icol, icol);
|
|
a.set(icol, icol, 1.0);
|
|
for (l = 0; l < n; l++)
|
|
a.set(icol, l, a.get(icol, l) * pivinv);
|
|
|
|
for (l = 0; l < m; l++)
|
|
b.set(icol, l, b.get(icol, l) * pivinv);
|
|
|
|
for (ll = 0; ll < n; ll++) {
|
|
if (ll !== icol) {
|
|
dumb = a.get(ll, icol);
|
|
a.set(ll, icol, 0.0);
|
|
for (l = 0; l < n; l++)
|
|
a.set(ll, l, a.get(ll, l) - a.get(icol, l) * dumb);
|
|
|
|
for (l = 0; l < m; l++)
|
|
b.set(ll, l, a.get(ll, l) - b.get(icol, l) * dumb);
|
|
}
|
|
}
|
|
}
|
|
// This is the end of the main loop over columns of the reduction. It only remains to unscram-
|
|
// ble the solution in view of the column interchanges. We do this by interchanging pairs of
|
|
// columns in the reverse order that the permutation was built up.
|
|
for (l = n - 1; l >= 0; l--) {
|
|
if (indxr[l] !== indxc[l]) {
|
|
for (k = 0; k < n; k++)
|
|
a.swap(k, indxr[l], k, indxc[l]);
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
var identityMatrix = new cc.math.Matrix4().identity();
|
|
/**
|
|
* Calculates the inverse of pM and stores the result in pOut.
|
|
* Please use matrix4's inverse function instead.
|
|
* @Return Returns NULL if there is no inverse, else pOut
|
|
*/
|
|
cc.kmMat4Inverse = function (pOut, pM) {
|
|
var inv = new cc.math.Matrix4(pM);
|
|
var tmp = new cc.math.Matrix4(identityMatrix);
|
|
if (cc.math.Matrix4._gaussj(inv, tmp) === false)
|
|
return null;
|
|
pOut.assignFrom(inv);
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* Calculates the inverse of current matrix.
|
|
* @returns {cc.math.Matrix4} Returns null if there is no inverse, else returns a new inverse matrix object
|
|
*/
|
|
proto.inverse = function(){ //cc.kmMat4Inverse
|
|
var inv = new cc.math.Matrix4(this);
|
|
var tmp = new cc.math.Matrix4(identityMatrix);
|
|
if (cc.math.Matrix4._gaussj(inv, tmp) === false)
|
|
return null;
|
|
return inv;
|
|
};
|
|
|
|
/**
|
|
* Returns true if current matrix is an identity matrix, false otherwise
|
|
*/
|
|
proto.isIdentity = function () { // cc.kmMat4IsIdentity
|
|
var mat = this.mat;
|
|
return (mat[0] === 1 && mat[1] === 0 && mat[2] === 0 && mat[3] === 0
|
|
&& mat[4] === 0 && mat[5] === 1 && mat[6] === 0 && mat[7] === 0
|
|
&& mat[8] === 0 && mat[9] === 0 && mat[10] === 1 && mat[11] === 0
|
|
&& mat[12] === 0 && mat[13] === 0 && mat[14] === 0 && mat[15] === 1);
|
|
};
|
|
|
|
/**
|
|
* transpose the current matrix
|
|
*/
|
|
proto.transpose = function() { // cc.kmMat4Transpose
|
|
var mat = this.mat;
|
|
var m1 = mat[1], m2 = mat[2], m3 = mat[3],
|
|
m4 = mat[4], m6 = mat[6], m7 = mat[7],
|
|
m8 = mat[8], m9 = mat[9], m11 = mat[11],
|
|
m12 = mat[12], m13 = mat[13], m14 = mat[14];
|
|
mat[1] = m4;
|
|
mat[2] = m8;
|
|
mat[3] = m12;
|
|
|
|
mat[4] = m1;
|
|
mat[6] = m9;
|
|
mat[7] = m13;
|
|
|
|
mat[8] = m2;
|
|
mat[9] = m6;
|
|
mat[11] = m14;
|
|
|
|
mat[12] = m3;
|
|
mat[13] = m7;
|
|
mat[14] = m11;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Multiplies pM1 with pM2, stores the result in pOut, returns pOut
|
|
*/
|
|
cc.kmMat4Multiply = function (pOut, pM1, pM2) {
|
|
// Cache the matrix values (makes for huge speed increases!)
|
|
var outArray = pOut.mat, mat1 = pM1.mat, mat2 = pM2.mat;
|
|
var a00 = mat1[0], a01 = mat1[1], a02 = mat1[2], a03 = mat1[3];
|
|
var a10 = mat1[4], a11 = mat1[5], a12 = mat1[6], a13 = mat1[7];
|
|
var a20 = mat1[8], a21 = mat1[9], a22 = mat1[10], a23 = mat1[11];
|
|
var a30 = mat1[12], a31 = mat1[13], a32 = mat1[14], a33 = mat1[15];
|
|
|
|
var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3];
|
|
var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7];
|
|
var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11];
|
|
var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
|
|
|
|
outArray[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
|
|
outArray[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
|
|
outArray[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
|
|
outArray[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
|
|
outArray[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
|
|
outArray[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
|
|
outArray[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
|
|
outArray[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
|
|
outArray[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
|
|
outArray[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
|
|
outArray[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
|
|
outArray[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
|
|
outArray[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
|
|
outArray[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
|
|
outArray[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
|
|
outArray[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* current matrix multiplies with other matrix mat4
|
|
* @param {cc.math.Matrix4} mat4
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
proto.multiply = function(mat4){
|
|
// Cache the matrix values (makes for huge speed increases!)
|
|
var mat = this.mat, mat2 = mat4.mat;
|
|
var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
|
|
var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
|
|
var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
|
|
var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
|
|
|
|
var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3];
|
|
var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7];
|
|
var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11];
|
|
var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
|
|
|
|
mat[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
|
|
mat[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
|
|
mat[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
|
|
mat[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
|
|
mat[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
|
|
mat[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
|
|
mat[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
|
|
mat[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
|
|
mat[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
|
|
mat[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
|
|
mat[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
|
|
mat[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
|
|
mat[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
|
|
mat[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
|
|
mat[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
|
|
mat[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
|
|
return this;
|
|
};
|
|
|
|
cc.getMat4MultiplyValue = function (pM1, pM2) {
|
|
var m1 = pM1.mat, m2 = pM2.mat;
|
|
var mat = new Float32Array(16);
|
|
|
|
mat[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
|
|
mat[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
|
|
mat[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
|
|
mat[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
|
|
|
|
mat[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
|
|
mat[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
|
|
mat[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
|
|
mat[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
|
|
|
|
mat[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
|
|
mat[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
|
|
mat[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
|
|
mat[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
|
|
|
|
mat[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
|
|
mat[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
|
|
mat[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
|
|
mat[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
|
|
|
|
return mat;
|
|
};
|
|
|
|
/**
|
|
* Assigns the value of pIn to pOut
|
|
*/
|
|
cc.kmMat4Assign = function (pOut, pIn) {
|
|
if (pOut === pIn) {
|
|
cc.log("cc.kmMat4Assign(): pOut equals pIn");
|
|
return pOut;
|
|
}
|
|
|
|
var outArr = pOut.mat;
|
|
var inArr = pIn.mat;
|
|
|
|
outArr[0] = inArr[0];
|
|
outArr[1] = inArr[1];
|
|
outArr[2] = inArr[2];
|
|
outArr[3] = inArr[3];
|
|
|
|
outArr[4] = inArr[4];
|
|
outArr[5] = inArr[5];
|
|
outArr[6] = inArr[6];
|
|
outArr[7] = inArr[7];
|
|
|
|
outArr[8] = inArr[8];
|
|
outArr[9] = inArr[9];
|
|
outArr[10] = inArr[10];
|
|
outArr[11] = inArr[11];
|
|
|
|
outArr[12] = inArr[12];
|
|
outArr[13] = inArr[13];
|
|
outArr[14] = inArr[14];
|
|
outArr[15] = inArr[15];
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* Assigns the value of current matrix from mat4
|
|
* @param {cc.math.Matrix4} mat4
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
proto.assignFrom = function(mat4) {
|
|
if (this === mat4) {
|
|
cc.log("cc.mat.Matrix4.assignFrom(): mat4 equals current matrix");
|
|
return this;
|
|
}
|
|
var outArr = this.mat, inArr = mat4.mat;
|
|
|
|
outArr[0] = inArr[0];
|
|
outArr[1] = inArr[1];
|
|
outArr[2] = inArr[2];
|
|
outArr[3] = inArr[3];
|
|
|
|
outArr[4] = inArr[4];
|
|
outArr[5] = inArr[5];
|
|
outArr[6] = inArr[6];
|
|
outArr[7] = inArr[7];
|
|
|
|
outArr[8] = inArr[8];
|
|
outArr[9] = inArr[9];
|
|
outArr[10] = inArr[10];
|
|
outArr[11] = inArr[11];
|
|
|
|
outArr[12] = inArr[12];
|
|
outArr[13] = inArr[13];
|
|
outArr[14] = inArr[14];
|
|
outArr[15] = inArr[15];
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Returns true if current matrix equal mat4 (approximately)
|
|
* @param {cc.math.Matrix4} mat4
|
|
* @returns {boolean}
|
|
*/
|
|
proto.equals = function(mat4) {
|
|
if (this === mat4) {
|
|
cc.log("cc.kmMat4AreEqual(): pMat1 and pMat2 are same object.");
|
|
return true;
|
|
}
|
|
var matA = this.mat, matB = mat4.mat, EPSILON = cc.math.EPSILON;
|
|
for (var i = 0; i < 16; i++) {
|
|
if (!(matA[i] + EPSILON > matB[i] && matA[i] - EPSILON < matB[i]))
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Builds an X-axis rotation matrix and stores it in matrix, returns matrix, if matrix is null, create a new matrix
|
|
* @param {Number} radians
|
|
* @param {cc.math.Matrix4} [matrix]
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByRotationX = function(radians, matrix) { //cc.kmMat4RotationX
|
|
/*
|
|
| 1 0 0 0 |
|
|
M = | 0 cos(A) -sin(A) 0 |
|
|
| 0 sin(A) cos(A) 0 |
|
|
| 0 0 0 1 |
|
|
*/
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var mat = matrix.mat;
|
|
mat[0] = 1.0;
|
|
mat[3] = mat[2] = mat[1] = 0.0;
|
|
|
|
mat[4] = 0.0;
|
|
mat[5] = Math.cos(radians);
|
|
mat[6] = Math.sin(radians);
|
|
mat[7] = 0.0;
|
|
|
|
mat[8] = 0.0;
|
|
mat[9] = -Math.sin(radians);
|
|
mat[10] = Math.cos(radians);
|
|
mat[11] = 0.0;
|
|
|
|
mat[14] = mat[13] = mat[12] = 0.0;
|
|
mat[15] = 1.0;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Builds a rotation matrix using the rotation around the Y-axis, The result is stored in matrix, matrix is returned.
|
|
* @param {Number} radians
|
|
* @param {cc.math.Matrix4} [matrix]
|
|
* @returns {*}
|
|
*/
|
|
cc.math.Matrix4.createByRotationY = function(radians, matrix) { // cc.kmMat4RotationY
|
|
/*
|
|
| cos(A) 0 sin(A) 0 |
|
|
M = | 0 1 0 0 |
|
|
| -sin(A) 0 cos(A) 0 |
|
|
| 0 0 0 1 |
|
|
*/
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var mat = matrix.mat;
|
|
mat[0] = Math.cos(radians);
|
|
mat[1] = 0.0;
|
|
mat[2] = -Math.sin(radians);
|
|
mat[3] = 0.0;
|
|
|
|
mat[7] = mat[6] = mat[4] = 0.0;
|
|
mat[5] = 1.0;
|
|
|
|
mat[8] = Math.sin(radians);
|
|
mat[9] = 0.0;
|
|
mat[10] = Math.cos(radians);
|
|
mat[11] = 0.0;
|
|
|
|
mat[14] = mat[13] = mat[12] = 0.0;
|
|
mat[15] = 1.0;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Builds a rotation matrix around the Z-axis. The resulting matrix is stored in matrix. matrix is returned.
|
|
* @param {Number} radians
|
|
* @param {cc.math.Matrix4} matrix
|
|
* @return {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByRotationZ = function(radians, matrix){ // cc.kmMat4RotationZ
|
|
/*
|
|
| cos(A) -sin(A) 0 0 |
|
|
M = | sin(A) cos(A) 0 0 |
|
|
| 0 0 1 0 |
|
|
| 0 0 0 1 |
|
|
*/
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var mat = matrix.mat;
|
|
mat[0] = Math.cos(radians);
|
|
mat[1] = Math.sin(radians);
|
|
mat[3] = mat[2] = 0.0;
|
|
|
|
mat[4] = -Math.sin(radians);
|
|
mat[5] = Math.cos(radians);
|
|
mat[7] = mat[6] = 0.0;
|
|
|
|
mat[11] = mat[9] = mat[8] = 0.0;
|
|
mat[10] = 1.0;
|
|
|
|
mat[14] = mat[13] = mat[12] = 0.0;
|
|
mat[15] = 1.0;
|
|
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Builds a rotation matrix from pitch, yaw and roll. The resulting matrix is stored in parameter matrix and returns.
|
|
* @param {Number} pitch
|
|
* @param {Number} yaw
|
|
* @param {Number} roll
|
|
* @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByPitchYawRoll = function(pitch, yaw, roll, matrix) {
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var cr = Math.cos(pitch), sr = Math.sin(pitch);
|
|
var cp = Math.cos(yaw), sp = Math.sin(yaw);
|
|
var cy = Math.cos(roll), sy = Math.sin(roll);
|
|
var srsp = sr * sp, crsp = cr * sp;
|
|
var mat = matrix.mat;
|
|
|
|
mat[0] = cp * cy;
|
|
mat[4] = cp * sy;
|
|
mat[8] = -sp;
|
|
|
|
mat[1] = srsp * cy - cr * sy;
|
|
mat[5] = srsp * sy + cr * cy;
|
|
mat[9] = sr * cp;
|
|
|
|
mat[2] = crsp * cy + sr * sy;
|
|
mat[6] = crsp * sy - sr * cy;
|
|
mat[10] = cr * cp;
|
|
|
|
mat[3] = mat[7] = mat[11] = 0.0;
|
|
mat[15] = 1.0;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Builds a matrix by a quaternion.
|
|
* @param {cc.math.Quaternion} quaternion
|
|
* @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByQuaternion = function(quaternion, matrix) {
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var mat = matrix.mat;
|
|
mat[0] = 1.0 - 2.0 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z );
|
|
mat[1] = 2.0 * (quaternion.x * quaternion.y + quaternion.z * quaternion.w);
|
|
mat[2] = 2.0 * (quaternion.x * quaternion.z - quaternion.y * quaternion.w);
|
|
mat[3] = 0.0;
|
|
|
|
// Second row
|
|
mat[4] = 2.0 * ( quaternion.x * quaternion.y - quaternion.z * quaternion.w );
|
|
mat[5] = 1.0 - 2.0 * ( quaternion.x * quaternion.x + quaternion.z * quaternion.z );
|
|
mat[6] = 2.0 * (quaternion.z * quaternion.y + quaternion.x * quaternion.w );
|
|
mat[7] = 0.0;
|
|
|
|
// Third row
|
|
mat[8] = 2.0 * ( quaternion.x * quaternion.z + quaternion.y * quaternion.w );
|
|
mat[9] = 2.0 * ( quaternion.y * quaternion.z - quaternion.x * quaternion.w );
|
|
mat[10] = 1.0 - 2.0 * ( quaternion.x * quaternion.x + quaternion.y * quaternion.y );
|
|
mat[11] = 0.0;
|
|
|
|
// Fourth row
|
|
mat[14] = mat[13] = mat[12] = 0;
|
|
mat[15] = 1.0;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Build a 4x4 OpenGL transformation matrix using a 3x3 rotation matrix, and a 3d vector representing a translation.
|
|
* @param {cc.math.Matrix3} rotation
|
|
* @param {cc.math.Vec3} translation
|
|
* @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByRotationTranslation = function(rotation, translation, matrix) {
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var mat = matrix.mat, rMat = rotation.mat;
|
|
mat[0] = rMat[0];
|
|
mat[1] = rMat[1];
|
|
mat[2] = rMat[2];
|
|
mat[3] = 0.0;
|
|
|
|
mat[4] = rMat[3];
|
|
mat[5] = rMat[4];
|
|
mat[6] = rMat[5];
|
|
mat[7] = 0.0;
|
|
|
|
mat[8] = rMat[6];
|
|
mat[9] = rMat[7];
|
|
mat[10] = rMat[8];
|
|
mat[11] = 0.0;
|
|
|
|
mat[12] = translation.x;
|
|
mat[13] = translation.y;
|
|
mat[14] = translation.z;
|
|
mat[15] = 1.0;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Builds a scaling matrix
|
|
* @param {Number} x
|
|
* @param {Number} y
|
|
* @param {Number} z
|
|
* @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByScale = function(x, y, z, matrix) { //cc.kmMat4Scaling
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var mat = matrix.mat;
|
|
mat[0] = x;
|
|
mat[5] = y;
|
|
mat[10] = z;
|
|
mat[15] = 1.0;
|
|
mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7] =
|
|
mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Builds a translation matrix. All other elements in the matrix
|
|
* will be set to zero except for the diagonal which is set to 1.0
|
|
*/
|
|
cc.kmMat4Translation = function (pOut, x, y, z) {
|
|
//FIXME: Write a test for this
|
|
pOut.mat[0] = pOut.mat[5] = pOut.mat[10] = pOut.mat[15] = 1.0;
|
|
pOut.mat[1] = pOut.mat[2] = pOut.mat[3] =
|
|
pOut.mat[4] = pOut.mat[6] = pOut.mat[7] =
|
|
pOut.mat[8] = pOut.mat[9] = pOut.mat[11] = 0.0;
|
|
pOut.mat[12] = x;
|
|
pOut.mat[13] = y;
|
|
pOut.mat[14] = z;
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* Builds a translation matrix.
|
|
* @param {Number} x
|
|
* @param {Number} y
|
|
* @param {Number} z
|
|
* @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByTranslation = function(x, y, z, matrix){ //cc.kmMat4Translation
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
matrix.identity();
|
|
matrix.mat[12] = x;
|
|
matrix.mat[13] = y;
|
|
matrix.mat[14] = z;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Get the up vector from a matrix.
|
|
* @returns {cc.math.Vec3}
|
|
*/
|
|
proto.getUpVec3 = function() {
|
|
var mat = this.mat;
|
|
var ret = new cc.math.Vec3(mat[4],mat[5], mat[6]);
|
|
return ret.normalize();
|
|
};
|
|
|
|
/**
|
|
* Extract the right vector from a 4x4 matrix.
|
|
* @returns {cc.math.Vec3}
|
|
*/
|
|
proto.getRightVec3 = function(){
|
|
var mat = this.mat;
|
|
var ret = new cc.math.Vec3(mat[0],mat[1], mat[2]);
|
|
return ret.normalize();
|
|
};
|
|
|
|
/**
|
|
* Extract the forward vector from a 4x4 matrix.
|
|
* @returns {cc.math.Vec3}
|
|
*/
|
|
proto.getForwardVec3 = function() {
|
|
var mat = this.mat;
|
|
var ret = new cc.math.Vec3(mat[8],mat[9], mat[10]);
|
|
return ret.normalize();
|
|
};
|
|
|
|
/**
|
|
* Creates a perspective projection matrix in the
|
|
* same way as gluPerspective
|
|
*/
|
|
cc.kmMat4PerspectiveProjection = function (pOut, fovY, aspect, zNear, zFar) {
|
|
var r = cc.degreesToRadians(fovY / 2);
|
|
var deltaZ = zFar - zNear;
|
|
var s = Math.sin(r);
|
|
|
|
if (deltaZ === 0 || s === 0 || aspect === 0)
|
|
return null;
|
|
|
|
//cos(r) / sin(r) = cot(r)
|
|
var cotangent = Math.cos(r) / s;
|
|
pOut.identity();
|
|
pOut.mat[0] = cotangent / aspect;
|
|
pOut.mat[5] = cotangent;
|
|
pOut.mat[10] = -(zFar + zNear) / deltaZ;
|
|
pOut.mat[11] = -1;
|
|
pOut.mat[14] = -2 * zNear * zFar / deltaZ;
|
|
pOut.mat[15] = 0;
|
|
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* Creates a perspective projection matrix in the same way as gluPerspective
|
|
* @param {Number} fovY
|
|
* @param {Number} aspect
|
|
* @param {Number} zNear
|
|
* @param {Number} zFar
|
|
* @returns {cc.math.Matrix4|Null}
|
|
*/
|
|
cc.math.Matrix4.createPerspectiveProjection = function(fovY, aspect, zNear, zFar){
|
|
var r = cc.degreesToRadians(fovY / 2), deltaZ = zFar - zNear;
|
|
var s = Math.sin(r);
|
|
|
|
if (deltaZ === 0 || s === 0 || aspect === 0)
|
|
return null;
|
|
|
|
//cos(r) / sin(r) = cot(r)
|
|
var cotangent = Math.cos(r) / s;
|
|
var matrix = new cc.math.Matrix4(), mat = matrix.mat;
|
|
matrix.identity();
|
|
mat[0] = cotangent / aspect;
|
|
mat[5] = cotangent;
|
|
mat[10] = -(zFar + zNear) / deltaZ;
|
|
mat[11] = -1;
|
|
mat[14] = -2 * zNear * zFar / deltaZ;
|
|
mat[15] = 0;
|
|
return matrix;
|
|
};
|
|
|
|
/** Creates an orthographic projection matrix like glOrtho */
|
|
cc.kmMat4OrthographicProjection = function (pOut, left, right, bottom, top, nearVal, farVal) {
|
|
pOut.identity();
|
|
pOut.mat[0] = 2 / (right - left);
|
|
pOut.mat[5] = 2 / (top - bottom);
|
|
pOut.mat[10] = -2 / (farVal - nearVal);
|
|
pOut.mat[12] = -((right + left) / (right - left));
|
|
pOut.mat[13] = -((top + bottom) / (top - bottom));
|
|
pOut.mat[14] = -((farVal + nearVal) / (farVal - nearVal));
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* Creates an orthographic projection matrix like glOrtho
|
|
* @param {Number} left
|
|
* @param {Number} right
|
|
* @param {Number} bottom
|
|
* @param {Number} top
|
|
* @param {Number} nearVal
|
|
* @param {Number} farVal
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createOrthographicProjection = function (left, right, bottom, top, nearVal, farVal) {
|
|
var matrix = new cc.math.Matrix4(), mat = matrix.mat;
|
|
matrix.identity();
|
|
mat[0] = 2 / (right - left);
|
|
mat[5] = 2 / (top - bottom);
|
|
mat[10] = -2 / (farVal - nearVal);
|
|
mat[12] = -((right + left) / (right - left));
|
|
mat[13] = -((top + bottom) / (top - bottom));
|
|
mat[14] = -((farVal + nearVal) / (farVal - nearVal));
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Builds a translation matrix in the same way as gluLookAt()
|
|
* the resulting matrix is stored in pOut. pOut is returned.
|
|
*/
|
|
cc.kmMat4LookAt = function (pOut, pEye, pCenter, pUp) {
|
|
var f = new cc.math.Vec3(pCenter), up = new cc.math.Vec3(pUp);
|
|
f.subtract(pEye);
|
|
f.normalize();
|
|
up.normalize();
|
|
|
|
var s = new cc.math.Vec3(f);
|
|
s.cross(up);
|
|
s.normalize();
|
|
|
|
var u = new cc.math.Vec3(s);
|
|
u.cross(f);
|
|
s.normalize();
|
|
|
|
pOut.identity();
|
|
|
|
pOut.mat[0] = s.x;
|
|
pOut.mat[4] = s.y;
|
|
pOut.mat[8] = s.z;
|
|
|
|
pOut.mat[1] = u.x;
|
|
pOut.mat[5] = u.y;
|
|
pOut.mat[9] = u.z;
|
|
|
|
pOut.mat[2] = -f.x;
|
|
pOut.mat[6] = -f.y;
|
|
pOut.mat[10] = -f.z;
|
|
|
|
var translate = cc.math.Matrix4.createByTranslation(-pEye.x, -pEye.y, -pEye.z);
|
|
pOut.multiply(translate);
|
|
return pOut;
|
|
};
|
|
|
|
var tempMatrix = new cc.math.Matrix4(); // an internal matrix
|
|
proto.lookAt = function(eyeVec, centerVec, upVec) {
|
|
var f = new cc.math.Vec3(centerVec), up = new cc.math.Vec3(upVec), mat = this.mat;
|
|
f.subtract(eyeVec);
|
|
f.normalize();
|
|
up.normalize();
|
|
|
|
var s = new cc.math.Vec3(f);
|
|
s.cross(up);
|
|
s.normalize();
|
|
|
|
var u = new cc.math.Vec3(s);
|
|
u.cross(f);
|
|
s.normalize();
|
|
|
|
this.identity();
|
|
mat[0] = s.x;
|
|
mat[4] = s.y;
|
|
mat[8] = s.z;
|
|
|
|
mat[1] = u.x;
|
|
mat[5] = u.y;
|
|
mat[9] = u.z;
|
|
|
|
mat[2] = -f.x;
|
|
mat[6] = -f.y;
|
|
mat[10] = -f.z;
|
|
|
|
tempMatrix = cc.math.Matrix4.createByTranslation(-eyeVec.x, -eyeVec.y, -eyeVec.z, tempMatrix);
|
|
this.multiply(tempMatrix);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Build a rotation matrix from an axis and an angle. Result is stored in pOut.
|
|
* pOut is returned.
|
|
*/
|
|
cc.kmMat4RotationAxisAngle = function (pOut, axis, radians) {
|
|
var rcos = Math.cos(radians), rsin = Math.sin(radians);
|
|
|
|
var normalizedAxis = new cc.math.Vec3(axis);
|
|
normalizedAxis.normalize();
|
|
|
|
pOut.mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos);
|
|
pOut.mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos);
|
|
pOut.mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos);
|
|
pOut.mat[3] = 0.0;
|
|
|
|
pOut.mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos);
|
|
pOut.mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos);
|
|
pOut.mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos);
|
|
pOut.mat[7] = 0.0;
|
|
|
|
pOut.mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos);
|
|
pOut.mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos);
|
|
pOut.mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos);
|
|
pOut.mat[11] = 0.0;
|
|
|
|
pOut.mat[12] = 0.0;
|
|
pOut.mat[13] = 0.0;
|
|
pOut.mat[14] = 0.0;
|
|
pOut.mat[15] = 1.0;
|
|
|
|
return pOut;
|
|
};
|
|
|
|
/**
|
|
* Build a rotation matrix from an axis and an angle.
|
|
* @param {cc.math.Vec3} axis
|
|
* @param {Number} radians
|
|
* @param {cc.math.Matrix4} [matrix]
|
|
* @returns {cc.math.Matrix4}
|
|
*/
|
|
cc.math.Matrix4.createByAxisAndAngle = function(axis, radians, matrix) {
|
|
matrix = matrix || new cc.math.Matrix4();
|
|
var mat = this.mat, rcos = Math.cos(radians), rsin = Math.sin(radians) ;
|
|
|
|
var normalizedAxis = new cc.math.Vec3(axis);
|
|
normalizedAxis.normalize();
|
|
|
|
mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos);
|
|
mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos);
|
|
mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos);
|
|
mat[3] = 0.0;
|
|
|
|
mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos);
|
|
mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos);
|
|
mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos);
|
|
mat[7] = 0.0;
|
|
|
|
mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos);
|
|
mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos);
|
|
mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos);
|
|
mat[11] = 0.0;
|
|
|
|
mat[12] = mat[13] = mat[14] = 0.0;
|
|
mat[15] = 1.0;
|
|
return matrix;
|
|
};
|
|
|
|
/**
|
|
* Extract a 3x3 rotation matrix from the input 4x4 transformation.
|
|
* @returns {cc.math.Matrix3}
|
|
*/
|
|
proto.extractRotation = function(){
|
|
var matrix = new cc.math.Matrix3(), mat4 = this.mat, mat3 = matrix.mat;
|
|
mat3[0] = mat4[0];
|
|
mat3[1] = mat4[1];
|
|
mat3[2] = mat4[2];
|
|
|
|
mat3[3] = mat4[4];
|
|
mat3[4] = mat4[5];
|
|
mat3[5] = mat4[6];
|
|
|
|
mat3[6] = mat4[8];
|
|
mat3[7] = mat4[9];
|
|
mat3[8] = mat4[10];
|
|
return matrix;
|
|
};
|
|
|
|
proto.extractPlane = function(planeType) {
|
|
var plane = new cc.math.Plane(), mat = this.mat;
|
|
switch (planeType) {
|
|
case cc.math.Plane.RIGHT:
|
|
plane.a = mat[3] - mat[0];
|
|
plane.b = mat[7] - mat[4];
|
|
plane.c = mat[11] - mat[8];
|
|
plane.d = mat[15] - mat[12];
|
|
break;
|
|
case cc.math.Plane.LEFT:
|
|
plane.a = mat[3] + mat[0];
|
|
plane.b = mat[7] + mat[4];
|
|
plane.c = mat[11] + mat[8];
|
|
plane.d = mat[15] + mat[12];
|
|
break;
|
|
case cc.math.Plane.BOTTOM:
|
|
plane.a = mat[3] + mat[1];
|
|
plane.b = mat[7] + mat[5];
|
|
plane.c = mat[11] + mat[9];
|
|
plane.d = mat[15] + mat[13];
|
|
break;
|
|
case cc.math.Plane.TOP:
|
|
plane.a = mat[3] - mat[1];
|
|
plane.b = mat[7] - mat[5];
|
|
plane.c = mat[11] - mat[9];
|
|
plane.d = mat[15] - mat[13];
|
|
break;
|
|
case cc.math.Plane.FAR:
|
|
plane.a = mat[3] - mat[2];
|
|
plane.b = mat[7] - mat[6];
|
|
plane.c = mat[11] - mat[10];
|
|
plane.d = mat[15] - mat[14];
|
|
break;
|
|
case cc.math.Plane.NEAR:
|
|
plane.a = mat[3] + mat[2];
|
|
plane.b = mat[7] + mat[6];
|
|
plane.c = mat[11] + mat[10];
|
|
plane.d = mat[15] + mat[14];
|
|
break;
|
|
default:
|
|
cc.log("cc.math.Matrix4.extractPlane: Invalid plane index");
|
|
break;
|
|
}
|
|
|
|
var t = Math.sqrt(plane.a * plane.a + plane.b * plane.b + plane.c * plane.c);
|
|
plane.a /= t;
|
|
plane.b /= t;
|
|
plane.c /= t;
|
|
plane.d /= t;
|
|
return plane;
|
|
};
|
|
|
|
/**
|
|
* Take the rotation from a 4x4 transformation matrix, and return it as an axis and an angle (in radians)
|
|
* @returns {*|{axis: cc.math.Vec3, angle: number}}
|
|
*/
|
|
proto.toAxisAndAngle = function() {
|
|
/*Surely not this easy?*/
|
|
var rotation = this.extractRotation();
|
|
var temp = cc.math.Quaternion.rotationMatrix(rotation);
|
|
return temp.toAxisAndAngle();
|
|
};
|
|
})(cc);
|