商域無疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商業用途-保持一致”創作公用協議
轉載請保留此句:商域無疆 - 本博客專注於 敏捷開發及移動和物聯設備研究:數據可視化、GOLANG、Html5、WEBGL、THREE.JS,否則,出自本博客的文章拒絕轉載或再轉載,謝謝合作。
今天把math庫中最大的對象Matrix4凝視完了,發現之前好多的凝視理解的不太正確,還有好多的凝視由於馬虎,好多小錯誤.能改的都在github上更新了,只是大概意思,臨時我覺得是正確的.哈哈哈:)
下面代碼是THREE.JS 源代碼文件里Math/Matrix4.js文件的凝視.
很多其它更新在 : https://github.com/omni360/three.js.sourcecode/blob/master/Three.js
// File:src/math/Matrix4.js /** * @author mrdoob / http://mrdoob.com/ * @author supereggbert / http://www.paulbrunt.co.uk/ * @author philogb / http://blog.thejit.org/ * @author jordi_ros / http://plattsoft.com * @author D1plo1d / http://github.com/D1plo1d * @author alteredq / http://alteredqualia.com/ * @author mikael emtinger / http://gomo.se/ * @author timknip / http://www.floorplanner.com/ * @author bhouston / http://exocortex.com * @author WestLangley / http://github.com/WestLangley */ ///Matrix4對象的構造函數.用來創建一個4x4矩陣.Matrix4對象的功能函數採用 ///定義構造的函數原型對象來實現,實際就是一個數組. /// /// 使用方法: var m = new Matrix4(11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44) /// 創建一個4x4的矩陣,事實上就是一個長度為9的數組,將參數(11, 12, 13, 21, 22, 23, 31, 32, 33, 41, 42, 43, 44)傳遞給數組用來初始化. /// 一個變換矩陣能夠運行隨意的線形3D變換(比如,平移。旋轉,縮放。切邊等等)並且透視變換使用齊次坐標。/// 腳本中非常少使用矩陣:最經常使用Vector3,Quaternion。並且Transform類的功能更簡單。單純的矩陣用於特殊情況,如設置非標准相機投影。
/// /// NOTE: 參數 n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, 41, 42, 43, 44 代表4x4矩陣中的元素的值,n11表示矩陣的第一行,第一列的元素值 /// ///<summary>Matrix4</summary> ///<param name ="n11" type="number">n11第 1 行,第 1 列的元素值</param> ///<param name ="n12" type="number">n12第 1 行,第 2 列的元素值</param> ///<param name ="n13" type="number">n13第 1 行,第 3 列的元素值</param> ///<param name ="n13" type="number">n13第 1 行,第 4 列的元素值</param> ///<param name ="n21" type="number">n21第 2 行,第 1 列的元素值</param> ///<param name ="n22" type="number">n22第 2 行,第 2 列的元素值</param> ///<param name ="n23" type="number">n23第 2 行,第 3 列的元素值</param> ///<param name ="n23" type="number">n23第 2 行,第 4 列的元素值</param> ///<param name ="n31" type="number">n31第 3 行,第 1 列的元素值</param> ///<param name ="n32" type="number">n32第 3 行,第 2 列的元素值</param> ///<param name ="n33" type="number">n33第 3 行,第 3 列的元素值</param> ///<param name ="n33" type="number">n33第 3 行,第 4 列的元素值</param> ///<param name ="n31" type="number">n31第 4 行,第 1 列的元素值</param> ///<param name ="n32" type="number">n32第 4 行,第 2 列的元素值</param> ///<param name ="n33" type="number">n33第 4 行,第 3 列的元素值</param> ///<param name ="n33" type="number">n33第 4 行,第 4 列的元素值</param> ///<returns type="Matrix4">返回新的4x4矩陣</returns> THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { this.elements = new Float32Array( 16 ); // TODO: 假設n11未定義,Matrix4將被初始化為一個單位矩陣.假設n11定義了值,直接復制該值到矩陣中. // TODO: if n11 is undefined, then just set to identity, otherwise copy all other values into matrix // 我們不支持semi規范的Matrix4(4x4矩陣),semi規范非常奇怪?
??(英語實在只是關) // we should not support semi specification of Matrix4, it is just weird. var te = this.elements; te[ 0 ] = ( n11 !== undefined ) ?
n11 : 1; te[ 4 ] = n12 || 0; te[ 8 ] = n13 || 0; te[ 12 ] = n14 || 0; te[ 1 ] = n21 || 0; te[ 5 ] = ( n22 !== undefined ) ? n22 : 1; te[ 9 ] = n23 || 0; te[ 13 ] = n24 || 0; te[ 2 ] = n31 || 0; te[ 6 ] = n32 || 0; te[ 10 ] = ( n33 !== undefined ) ?
n33 : 1; te[ 14 ] = n34 || 0; te[ 3 ] = n41 || 0; te[ 7 ] = n42 || 0; te[ 11 ] = n43 || 0; te[ 15 ] = ( n44 !== undefined ) ? n44 : 1; //初始化Matrix4(4x4矩陣)對象. }; /**************************************** ****以下是Matrix4對象提供的功能函數. ****************************************/ THREE.Matrix4.prototype = { constructor: THREE.Matrix4, //構造器 /* ///set方法用來從新設置Matrix4(4x4矩陣)的元素值.並返回新的坐標值的Matrix4(4x4矩陣). /// TODO:改動set方法,兼容 n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, 41, 42, 43, 44 參數省略支持多態. */ ///<summary>set</summary> ///<param name ="n11" type="number">n11第 1 行,第 1 列的元素值</param> ///<param name ="n12" type="number">n12第 1 行,第 2 列的元素值</param> ///<param name ="n13" type="number">n13第 1 行,第 3 列的元素值</param> ///<param name ="n13" type="number">n13第 1 行,第 4 列的元素值</param> ///<param name ="n21" type="number">n21第 2 行,第 1 列的元素值</param> ///<param name ="n22" type="number">n22第 2 行,第 2 列的元素值</param> ///<param name ="n23" type="number">n23第 2 行,第 3 列的元素值</param> ///<param name ="n23" type="number">n23第 2 行,第 4 列的元素值</param> ///<param name ="n31" type="number">n31第 3 行,第 1 列的元素值</param> ///<param name ="n32" type="number">n32第 3 行,第 2 列的元素值</param> ///<param name ="n33" type="number">n33第 3 行,第 3 列的元素值</param> ///<param name ="n33" type="number">n33第 3 行,第 4 列的元素值</param> ///<param name ="n31" type="number">n31第 4 行,第 1 列的元素值</param> ///<param name ="n32" type="number">n32第 4 行,第 2 列的元素值</param> ///<param name ="n33" type="number">n33第 4 行,第 3 列的元素值</param> ///<param name ="n33" type="number">n33第 4 行,第 4 列的元素值</param> ///<returns type="Matrix4">返回新的4x4矩陣</returns> set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { var te = this.elements; te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; return this; //返回新的4x4矩陣 }, /* ///identity方法用來獲得一個4x4矩陣的單位矩陣 /// /// NOTE:在矩陣的乘法中。有一種矩陣起着特殊的作用,如同數的乘法中的1,我們稱這樣的矩陣為單位矩陣 /// 它是個方陣,從左上角到右下角的對角線(稱為主對角線)上的元素均為1以外全都為0。 /// 對於單位矩陣。有AE=EA=A */ ///<summary>identity</summary> ///<returns type="Matrix4(4x4矩陣)">返回4x4矩陣的一個單位矩陣</returns> identity: function () { this.set( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); return this; //返回4x4矩陣的一個單位矩陣 }, /* ///copy方法用來復制4x4矩陣的元素值.並返回新的Matrix4(4x4矩陣). */ ///<summary>copy</summary> ///<param name ="m" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> copy: function ( m ) { this.elements.set( m.elements ); return this; //返回新的Matrix4(4x4矩陣) }, /* ///extractPosition方法用來復制參數m(4x4矩陣)的平移分量.並返回新的Matrix4(4x4矩陣). /// NOTE: extractPosition方法已經被重命名為.copyPosition() */ ///<summary>extractPosition</summary> ///<param name ="m" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> extractPosition: function ( m ) { console.warn( 'THREEMatrix4: .extractPosition() has been renamed to .copyPosition().' ); return this.copyPosition( m ); //調用copyPosition()方法,返回新的Matrix4(4x4矩陣) }, /* ///copyPosition方法用來復制參數m(4x4矩陣)的平移分量.並返回新的Matrix4(4x4矩陣). */ ///<summary>copyPosition</summary> ///<param name ="m" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> copyPosition: function ( m ) { var te = this.elements; var me = m.elements; te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; return this; //返回新的Matrix4(4x4矩陣) }, /* ///extractRotation方法用來提取參數m(4x4矩陣)的旋轉分量.並返回新的Matrix4(4x4矩陣). */ ///<summary>extractRotation</summary> ///<param name ="m" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> extractRotation: function () { var v1 = new THREE.Vector3(); return function ( m ) { var te = this.elements; var me = m.elements; var scaleX = 1 / v1.set( me[ 0 ], me[ 1 ], me[ 2 ] ).length(); var scaleY = 1 / v1.set( me[ 4 ], me[ 5 ], me[ 6 ] ).length(); var scaleZ = 1 / v1.set( me[ 8 ], me[ 9 ], me[ 10 ] ).length(); te[ 0 ] = me[ 0 ] * scaleX; te[ 1 ] = me[ 1 ] * scaleX; te[ 2 ] = me[ 2 ] * scaleX; te[ 4 ] = me[ 4 ] * scaleY; te[ 5 ] = me[ 5 ] * scaleY; te[ 6 ] = me[ 6 ] * scaleY; te[ 8 ] = me[ 8 ] * scaleZ; te[ 9 ] = me[ 9 ] * scaleZ; te[ 10 ] = me[ 10 ] * scaleZ; return this; //返回新的Matrix4(4x4矩陣) }; }(), /* ///applyEuler方法通過歐拉旋轉(參數euler)對Matrix4(4x4矩陣)應用旋轉變換. */ ///<summary>applyEuler</summary> ///<param name ="euler" type="THREE.Euler">THREE.Euler對象,歐拉對象</param> ///<returns type="Matrix4">返回變換后的Matrix4(4x4矩陣)</returns> makeRotationFromEuler: function ( euler ) { if ( euler instanceof THREE.Euler === false ) { console.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); } var te = this.elements; var x = euler.x, y = euler.y, z = euler.z; var a = Math.cos( x ), b = Math.sin( x ); var c = Math.cos( y ), d = Math.sin( y ); var e = Math.cos( z ), f = Math.sin( z ); if ( euler.order === 'XYZ' ) { var ae = a * e, af = a * f, be = b * e, bf = b * f; te[ 0 ] = c * e; te[ 4 ] = - c * f; te[ 8 ] = d; te[ 1 ] = af + be * d; te[ 5 ] = ae - bf * d; te[ 9 ] = - b * c; te[ 2 ] = bf - ae * d; te[ 6 ] = be + af * d; te[ 10 ] = a * c; } else if ( euler.order === 'YXZ' ) { var ce = c * e, cf = c * f, de = d * e, df = d * f; te[ 0 ] = ce + df * b; te[ 4 ] = de * b - cf; te[ 8 ] = a * d; te[ 1 ] = a * f; te[ 5 ] = a * e; te[ 9 ] = - b; te[ 2 ] = cf * b - de; te[ 6 ] = df + ce * b; te[ 10 ] = a * c; } else if ( euler.order === 'ZXY' ) { var ce = c * e, cf = c * f, de = d * e, df = d * f; te[ 0 ] = ce - df * b; te[ 4 ] = - a * f; te[ 8 ] = de + cf * b; te[ 1 ] = cf + de * b; te[ 5 ] = a * e; te[ 9 ] = df - ce * b; te[ 2 ] = - a * d; te[ 6 ] = b; te[ 10 ] = a * c; } else if ( euler.order === 'ZYX' ) { var ae = a * e, af = a * f, be = b * e, bf = b * f; te[ 0 ] = c * e; te[ 4 ] = be * d - af; te[ 8 ] = ae * d + bf; te[ 1 ] = c * f; te[ 5 ] = bf * d + ae; te[ 9 ] = af * d - be; te[ 2 ] = - d; te[ 6 ] = b * c; te[ 10 ] = a * c; } else if ( euler.order === 'YZX' ) { var ac = a * c, ad = a * d, bc = b * c, bd = b * d; te[ 0 ] = c * e; te[ 4 ] = bd - ac * f; te[ 8 ] = bc * f + ad; te[ 1 ] = f; te[ 5 ] = a * e; te[ 9 ] = - b * e; te[ 2 ] = - d * e; te[ 6 ] = ad * f + bc; te[ 10 ] = ac - bd * f; } else if ( euler.order === 'XZY' ) { var ac = a * c, ad = a * d, bc = b * c, bd = b * d; te[ 0 ] = c * e; te[ 4 ] = - f; te[ 8 ] = d * e; te[ 1 ] = ac * f + bd; te[ 5 ] = a * e; te[ 9 ] = ad * f - bc; te[ 2 ] = bc * f - ad; te[ 6 ] = b * e; te[ 10 ] = bd * f + ac; } //最后一列 // last column te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; //最以下的一行 // bottom row te[ 12 ] = 0; te[ 13 ] = 0; te[ 14 ] = 0; te[ 15 ] = 1; return this; //返回變換后的Matrix4(4x4矩陣) }, /* ///setRotationFromQuaternion方法通過四元數對Matrix4(4x4矩陣)應用旋轉變換. /// NOTE: setRotationFromQuaternion()方法已經被重命名為makeRotationFromQuaternion(),這里保留是為了向下兼容. */ ///<summary>setRotationFromQuaternion</summary> ///<param name ="q" type="Quaternion">四元數</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> setRotationFromQuaternion: function ( q ) { console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' ); return this.makeRotationFromQuaternion( q ); //調用makeRotationFromQuaternion()方法,應用旋轉變換,並返回新的Matrix4(4x4矩陣)對象. }, /* ///makeRotationFromQuaternion方法通過四元數對Matrix4(4x4矩陣)應用旋轉變換. */ ///<summary>setRotationFromQuaternion</summary> ///<param name ="q" type="Quaternion">四元數</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> makeRotationFromQuaternion: function ( q ) { var te = this.elements; var x = q.x, y = q.y, z = q.z, w = q.w; var x2 = x + x, y2 = y + y, z2 = z + z; var xx = x * x2, xy = x * y2, xz = x * z2; var yy = y * y2, yz = y * z2, zz = z * z2; var wx = w * x2, wy = w * y2, wz = w * z2; te[ 0 ] = 1 - ( yy + zz ); te[ 4 ] = xy - wz; te[ 8 ] = xz + wy; te[ 1 ] = xy + wz; te[ 5 ] = 1 - ( xx + zz ); te[ 9 ] = yz - wx; te[ 2 ] = xz - wy; te[ 6 ] = yz + wx; te[ 10 ] = 1 - ( xx + yy ); //最后一列 // last column te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; //最后一行 // bottom row te[ 12 ] = 0; te[ 13 ] = 0; te[ 14 ] = 0; te[ 15 ] = 1; return this; //返回新的Matrix4(4x4矩陣) }, /* ///lookAt(eye,center,up)將對象設定為一個視圖矩陣。參數都是Vector3對象,該矩陣僅僅會用到eye和center的相對位置。 ///該視圖矩陣表示,攝像機在eye位置看向center位置。且向上的向量(這一點稍后解釋)為up時的視圖矩陣。
///視圖矩陣又能夠看做攝像機的模型矩陣,所以該函數產生的矩陣又能夠表示以下變換:將物體從原點平移至位置center-eye, ///再將其旋轉至向上的向量為up。向上的向量up用來固定相機,能夠想象當相機固定在一點,鏡頭朝向固定方向的時候, ///還是能夠在一個維度里自由旋轉的。up向量固定相機的這個維度。 ///這里的解釋摘抄自:http://www.cnblogs.com/yiyezhai/archive/2012/11/29/2791319.html */ ///<summary>lookAt</summary> ///<param name ="eye" type="Vector3">表示相機位置的Vector3三維向量</param> ///<param name ="target" type="Vector3">表示目標的Vector3三維向量</param> ///<param name ="up" type="Vector3">表示向上的Vector3三維向量</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> lookAt: function () { var x = new THREE.Vector3(); var y = new THREE.Vector3(); var z = new THREE.Vector3(); return function ( eye, target, up ) { var te = this.elements; z.subVectors( eye, target ).normalize(); if ( z.length() === 0 ) { z.z = 1; } x.crossVectors( up, z ).normalize(); if ( x.length() === 0 ) { z.x += 0.0001; x.crossVectors( up, z ).normalize(); } y.crossVectors( z, x ); te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x; te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y; te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z; return this; //返回新的Matrix4(4x4矩陣) }; }(), /* ///multiply方法用來將當前Matrix4(4x4矩陣)與參數m相乘.並返回新的Matrix4(4x4矩陣) /// NOTE:這里僅僅接受一個參數,假設傳遞兩個參數請使用.multiplyMatrices( a, b )方法替代,假設有兩個參數會自己主動調用.multiplyMatrices( a, b )方法 */ ///<summary>multiply</summary> ///<param name ="m" type="Matrix4(4x4矩陣)">與當前對象元素值相乘的Matrix4(4x4矩陣)</param> ///<param name ="n" type="Matrix4(4x4矩陣)">推斷是否有第二個參數w,假設有的話,調用.multiplyMatrices()方法</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> multiply: function ( m, n ) { if ( n !== undefined ) { //推斷是否有第二個參數w,假設有的話,調用.multiplyMatrices()方法 // NOTE:這里僅僅接受一個參數,假設傳遞兩個參數請使用.multiplyMatrices( a, b )方法替代, console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); return this.multiplyMatrices( m, n ); //調用.multiplyMatrices()方法,返回新的Matrix4(4x4矩陣),矩陣m和矩陣n相乘 } return this.multiplyMatrices( this, m ); //調用.multiplyMatrices()方法,返回新的Matrix4(4x4矩陣),當前矩陣和矩陣m相乘 }, /* ///multiply方法用來將矩陣a,b相乘,並返回新的Matrix4(4x4矩陣). */ ///<summary>multiplyMatrices</summary> ///<param name ="a" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<param name ="b" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<returns type="Matrix4(4x4矩陣)">返回新的Matrix4(4x4矩陣)</returns> multiplyMatrices: function ( a, b ) { var ae = a.elements; var be = b.elements; var te = this.elements; //將矩陣a,b相乘. var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; return this; //返回新的Matrix4(4x4矩陣) }, /* ///multiply方法用來將矩陣a,b相乘,並返回新Matrix4(4x4矩陣)賦值給數組對象r */ ///<summary>multiplyMatrices</summary> ///<param name ="a" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<param name ="b" type="Matrix4(4x4矩陣)">Matrix4(4x4矩陣)</param> ///<param name ="r" type="Array">數組對象</param> ///<returns type="Array">返回新Matrix4(4x4矩陣)</returns> multiplyToArray: function ( a, b, r ) { var te = this.elements; this.multiplyMatrices( a, b ); //矩陣a,b相乘 //新Matrix4(4x4矩陣)賦值給數組對象 r[ 0 ] = te[ 0 ]; r[ 1 ] = te[ 1 ]; r[ 2 ] = te[ 2 ]; r[ 3 ] = te[ 3 ]; r[ 4 ] = te[ 4 ]; r[ 5 ] = te[ 5 ]; r[ 6 ] = te[ 6 ]; r[ 7 ] = te[ 7 ]; r[ 8 ] = te[ 8 ]; r[ 9 ] = te[ 9 ]; r[ 10 ] = te[ 10 ]; r[ 11 ] = te[ 11 ]; r[ 12 ] = te[ 12 ]; r[ 13 ] = te[ 13 ]; r[ 14 ] = te[ 14 ]; r[ 15 ] = te[ 15 ]; return this; //返回新Matrix4(4x4矩陣) }, /* ///multiplyScalar方法用來將Matrix4(4x4矩陣)的元素直接與參數s相乘.並返回新的Matrix4(4x4矩陣). /// NOTE:這里傳遞的參數s是一個標量. */ ///<summary>multiplyScalar</summary> ///<param name ="s" type="number">與當前Matrix4(4x4矩陣)對象的值相乘的標量,數值</param> ///<returns type="Matrix4">返回新的Matrix4(4x4矩陣)</returns> multiplyScalar: function ( s ) { var te = this.elements; te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; return this; //返回新的Matrix4(4x4矩陣) }, /* ///multiplyVector3方法用來將3x3矩陣和一個Vector3(三維向量)相乘.並返回新Matrix4(4x4矩陣)對象. /// NOTE:multiplyVector3方法已經被刪除使用vector.applyMatrix4( matrix )方法替換,這里保留是為了向下兼容. /// NOTE:multiplyVector3方法經經常使用來應用某種變換. */ ///<summary>multiplyVector3</summary> ///<param name ="vector" type="Vector3">三維向量</param> ///<returns type="Matrix4">並返回新的Matrix4(4x4矩陣)對象</returns> multiplyVector3: function ( vector ) { // 提示用戶multiplyVector3方法已經被刪除使用vector.applyMatrix4( matrix )方法替換,這里保留是為了向下兼容. console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.' ); return vector.applyProjection( this ); //並返回新的Matrix4(4x4矩陣)對象 }, /* ///multiplyVector4方法用來將3x3矩陣和一個Vector4(四維向量)相乘.並返回新Matrix4(4x4矩陣)對象. /// NOTE:multiplyVector4方法已經被刪除使用vector.applyMatrix4( matrix )方法替換,這里保留是為了向下兼容. /// NOTE:multiplyVector4方法經經常使用來應用某種變換. */ ///<summary>multiplyVector4</summary> ///<param name ="vector" type="Vector4">四維向量</param> ///<returns type="Matrix4">並返回新的Matrix4(4x4矩陣)對象</returns> multiplyVector4: function ( vector ) { // 提示用戶multiplyVector4方法已經被刪除使用vector.applyMatrix4( matrix )方法替換,這里保留是為了向下兼容. console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); return vector.applyMatrix4( this ); //並返回新的Matrix4(4x4矩陣)對象 }, /* ///multiplyVector3Array方法用來將數組a和一個Vector3(三維向量)相乘.並返回新的數組對象. /// NOTE:multiplyVector3Array方法已經被刪除使用matrix.applyToVector3Array( array )方法替換,這里保留是為了向下兼容. /// NOTE:multiplyVector3Array方法經經常使用來應用某種變換. */ ///<summary>multiplyVector3Array</summary> ///<param name ="a" type="Array">數組對象</param> ///<returns type="Array">並返回新的數組對象</returns> multiplyVector3Array: function ( a ) { // 提示用戶multiplyVector3Array方法已經被刪除使用matrix.applyToVector3Array( array )方法替換,這里保留是為了向下兼容. console.warn( 'THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); return this.applyToVector3Array( a ); //並返回新的Matrix4(4x4矩陣)對象 }, /* ///applyToVector3Array方法用來將當前矩陣應用到一個三維向量,並將結果轉換成一個數組,返回數組對象. /// NOTE:applyToVector3Array方法經經常使用來對三維向量應用某種變換. 參數offset,length用來對不同長度的數組應用變換. /// */ ///<summary>applyMatrix4</summary> ///<param name ="array" type="Array">數組對象</param> ///<param name ="offset" type="Number">偏移量</param> ///<param name ="length" type="Number">長度</param> ///<returns type="Array">並返回新的數組對象</returns> applyToVector3Array: function () { var v1 = new THREE.Vector3(); return function ( array, offset, length ) { if ( offset === undefined ) offset = 0; if ( length === undefined ) length = array.length; for ( var i = 0, j = offset, il; i < length; i += 3, j += 3 ) { v1.x = array[ j ]; v1.y = array[ j + 1 ]; v1.z = array[ j + 2 ]; v1.applyMatrix4( this ); array[ j ] = v1.x; array[ j + 1 ] = v1.y; array[ j + 2 ] = v1.z; } return array; //並返回新的數組對象 }; }(), /* ///rotateAxis方法對參數v三維向量的應用一個旋轉變換 /// NOTE:rotateAxis方法已經被刪除使用Vector3.transformDirection( matrix )方法替換,這里保留是為了向下兼容. */ ///<summary>rotateAxis</summary> ///<param name ="v" type="Vector3">仿射矩陣</param> ///<returns type="Vector3">返回新坐標值的三維向量</returns> rotateAxis: function ( v ) { //提示用戶rotateAxis方法已經被刪除使用Vector3.transformDirection( matrix )方法替換,這里保留是為了向下兼容. console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' ); v.transformDirection( this ); //調用Vector3.transformDirection( matrix ) 方法,對向量應用旋轉變換 }, /*crossVector方法 ///crossVector方法將返回兩個交叉乘積,調用者變為a,b的叉乘。
叉乘是一個向量,垂直於參與叉乘的兩個向量並呈右手螺旋法則。 /// 返回為同一時候垂直於兩個參數向量的向量,方向可朝上也可朝下,由兩向量夾角的方向決定。
/// NOTE:crossVector方法已經被刪除使用vector.applyMatrix4( matrix )方法替換,這里保留是為了向下兼容. /// NOTE:借助右手定則輔助推斷方向。參考:http://zh.wikipedia.org/zh/%E5%90%91%E9%87%8F%E7%A7%AF /// 叉乘是一種在向量空間中向量的二元運算。與點乘不同,它的運算結果是一個偽向量而不是一個標量。 /// 叉乘的運算結果叫叉積(即交叉乘積)、外積或向量積。
叉積與原來的兩個向量都垂直。
1、理論知識 數學上的定義:c=axb【注:粗體小寫字母表示向量】當中a,b,c均為向量。即兩個向量的叉積得到的還是向量! 性質1:c⊥a,c⊥b,即向量c垂直與向量a,b所在的平面。 性質2:模長|c|=|a||b|sin<a,b> 性質3:滿足右手法則。從這點我們有axb ≠ bxa,而axb = - bxa。所以我們能夠使用叉積的正負值來推斷向量a,b的相對位置。 即向量b是處於向量a的順時針方向還是逆時針方向。 */ ///<summary>crossVector</summary> ///<param name ="vector" type="Vector3">三維向量</param> ///<returns type="Vector3">三維向量</returns> crossVector: function ( vector ) { //提示用戶crossVector方法已經被刪除使用vector.applyMatrix4( matrix )方法替換,這里保留是為了向下兼容. console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); return vector.applyMatrix4( this ); //調用Vector3.applyMatrix4( matrix ) 方法,返回參數vector和當前矩陣的差乘. }, /* ///determinant方法用來獲得Matrix4(4x4矩陣)的行列式 /// NOTE:通過求解行列式值的方式來推斷矩陣的逆矩陣是否存在(行列式的值不等於0,表示該矩陣有逆矩陣). */ ///<summary>determinant</summary> ///<returns type="Number">返回Matrix4(4x4矩陣)的四階行列式</returns> determinant: function () { var te = this.elements; var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; //TODO: make this more efficient //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) return ( n41 * ( + n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34 ) + n42 * ( + n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31 ) + n43 * ( + n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31 ) + n44 * ( - n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31 ) //返回Matrix4(4x4矩陣)的四階行列式 ); }, /* ///transpose方法用來獲得Matrix4(4x4矩陣)的轉置矩陣. /// NOTE:一個mxn的矩陣的轉置矩陣式nxm矩陣,就是矩陣的行和列交換. /// 比如: /// /// -- -- -- -- T /// | 1 2 3 | | 1 4 7 | /// matrix A = | 4 5 6 | = | 2 5 8 | /// | 7 8 9 | | 3 6 9 | /// -- -- -- -- */ ///<summary>transpose</summary> ///<returns type="Matrix4">返回Matrix4(4x4矩陣)的轉置矩陣.</returns> transpose: function () { var te = this.elements; var tmp; tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; return this; //返回Matrix4(4x4矩陣)的轉置矩陣. }, /* ///flattenToArrayOffset方法通過參數offset指定偏移量,將矩陣展開到數組(參數array)中,返回新的數組. /// NOTE:flattenToArrayOffset方法能夠用在將3x3矩陣變換成4x4矩陣中. /// -- -- /// | 1 2 3 | /// matrix A = | 4 5 6 | => flattenToArrayOffset(arrary,3) => array(0,0,0,0,1,2,3,0,0,0,0,4,5,6,0,0,0,0,7,8,9) /// | 7 8 9 | /// -- -- */ ///<summary>flattenToArrayOffset</summary> ///<param name ="array" type="Array">Array數組對象</param> ///<param name ="offset" type="Number">偏移量</param> ///<returns type="Matrix4">返回包括矩陣元素的數組</returns> flattenToArrayOffset: function ( array, offset ) { var te = this.elements; array[ offset ] = te[ 0 ]; array[ offset + 1 ] = te[ 1 ]; array[ offset + 2 ] = te[ 2 ]; array[ offset + 3 ] = te[ 3 ]; array[ offset + 4 ] = te[ 4 ]; array[ offset + 5 ] = te[ 5 ]; array[ offset + 6 ] = te[ 6 ]; array[ offset + 7 ] = te[ 7 ]; array[ offset + 8 ] = te[ 8 ]; array[ offset + 9 ] = te[ 9 ]; array[ offset + 10 ] = te[ 10 ]; array[ offset + 11 ] = te[ 11 ]; array[ offset + 12 ] = te[ 12 ]; array[ offset + 13 ] = te[ 13 ]; array[ offset + 14 ] = te[ 14 ]; array[ offset + 15 ] = te[ 15 ]; return array; //返回包括矩陣元素的數組 }, /* ///getPosition方法將當前矩陣中代表位置的元素值設置給三維向量 /// NOTE:getPosition方法已經被刪除使用vector.setFromMatrixPosition( matrix )方法替換,這里保留是為了向下兼容. */ ///<summary>getPosition</summary> ///<returns type="Vector3">返回三維向量</returns> getPosition: function () { var v1 = new THREE.Vector3(); return function () { console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' ); var te = this.elements; return v1.set( te[ 12 ], te[ 13 ], te[ 14 ] ); //返回三維向量 }; }(), /* ///setPosition方法將當前矩陣中代表位置的元素值設置給三維向量 */ ///<summary>setPosition</summary> ///<param name ="v" type="Vector3">偏移量</param> ///<returns type="Matrix4">返回新的Matrix4(4x4矩陣)</returns> setPosition: function ( v ) { var te = this.elements; te[ 12 ] = v.x; te[ 13 ] = v.y; te[ 14 ] = v.z; return this; //返回新的Matrix4(4x4矩陣) }, /* ///getInverse方法用來獲得Matrix4(4x4矩陣)的逆矩陣. /// NOTE:逆矩陣與當前矩陣相乘得到單位矩陣. */ ///<summary>multiplyScalar</summary> ///<param name ="matrix" type="Matrix4">THREE.Matrix4</param> ///<param name ="throwOnInvertible" type="Number">異常標志</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣)的逆矩陣.</returns> getInverse: function ( m, throwOnInvertible ) { // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm var te = this.elements; var me = m.elements; var n11 = me[ 0 ], n12 = me[ 4 ], n13 = me[ 8 ], n14 = me[ 12 ]; var n21 = me[ 1 ], n22 = me[ 5 ], n23 = me[ 9 ], n24 = me[ 13 ]; var n31 = me[ 2 ], n32 = me[ 6 ], n33 = me[ 10 ], n34 = me[ 14 ]; var n41 = me[ 3 ], n42 = me[ 7 ], n43 = me[ 11 ], n44 = me[ 15 ]; te[ 0 ] = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44; te[ 4 ] = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44; te[ 8 ] = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44; te[ 12 ] = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; te[ 1 ] = n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44; te[ 5 ] = n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44; te[ 9 ] = n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44; te[ 13 ] = n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34; te[ 2 ] = n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44; te[ 6 ] = n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44; te[ 10 ] = n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44; te[ 14 ] = n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34; te[ 3 ] = n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43; te[ 7 ] = n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43; te[ 11 ] = n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43; te[ 15 ] = n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33; var det = n11 * te[ 0 ] + n21 * te[ 4 ] + n31 * te[ 8 ] + n41 * te[ 12 ]; //獲得參數matrix行列式的值 if ( det == 0 ) { // 沒有逆矩陣 var msg = "Matrix4.getInverse(): can't invert matrix, determinant is 0"; //提示用戶該矩陣沒有逆矩陣 if ( throwOnInvertible || false ) { throw new Error( msg ); } else { console.warn( msg ); } this.identity(); //獲得一個單位矩陣 return this; //返回單位矩陣 } this.multiplyScalar( 1 / det ); //除以行列式得到逆矩陣 return this; //返回Matrix4(4x4矩陣)的逆矩陣. }, /* ///translate方法用來變換Matrix4(4x4矩陣). /// NOTE:translate方法已經刪除. */ ///<summary>translate</summary> ///<param name ="v" type="Vector3">THREE.Vecter3</param> ///<returns type="Matrix4">返回帶有新位置信息的Matrix4(4x4矩陣).</returns> translate: function ( v ) { //提示用戶translate()方法已經刪除. console.warn( 'THREE.Matrix4: .translate() has been removed.' ); }, /* ///rotateX方法用來變換Matrix4(4x4矩陣)的x軸. /// NOTE:rotateX方法已經刪除. */ ///<summary>rotateX</summary> ///<param name ="angle" type="Number">角度</param> ///<returns type="Matrix4">返回帶有新的Matrix4(4x4矩陣).</returns> rotateX: function ( angle ) { //提示用戶rotateX()方法已經刪除. console.warn( 'THREE.Matrix4: .rotateX() has been removed.' ); }, /* ///rotateY方法用來變換Matrix4(4x4矩陣)的Y軸. /// NOTE:rotateX方法已經刪除. */ ///<summary>rotateY</summary> ///<param name ="angle" type="Number">角度</param> ///<returns type="Matrix4">返回帶有新的Matrix4(4x4矩陣).</returns> rotateY: function ( angle ) { //提示用戶rotateY()方法已經刪除. console.warn( 'THREE.Matrix4: .rotateY() has been removed.' ); }, /* ///rotateZ方法用來變換Matrix4(4x4矩陣)的Z軸. /// NOTE:rotateZ方法已經刪除. */ ///<summary>rotateZ</summary> ///<param name ="angle" type="Number">角度</param> ///<returns type="Matrix4">返回帶有新的Matrix4(4x4矩陣).</returns> rotateZ: function ( angle ) { //提示用戶rotateZ()方法已經刪除. console.warn( 'THREE.Matrix4: .rotateZ() has been removed.' ); }, /* ///rotateByAxis方法用來變換Matrix4(4x4矩陣)的隨意軸. /// NOTE:rotateByAxis方法已經刪除. */ ///<summary>rotateByAxis</summary> ///<param name ="axis" type="Vector3">隨意軸</param> ///<param name ="angle" type="Number">角度</param> ///<returns type="Matrix4">返回帶有新的Matrix4(4x4矩陣).</returns> rotateByAxis: function ( axis, angle ) { //提示用戶rotateByAxis()方法已經刪除. console.warn( 'THREE.Matrix4: .rotateByAxis() has been removed.' ); }, /* ///scale方法通過預先計算比例向量,將指定的比例向量應用到此 Matrix4(4x4矩陣)。 */ ///<summary>scale</summary> ///<param name ="v" type="Vector3">比例向量Vector3</param> ///<returns type="Matrix4">返回新的Matrix4(4x4矩陣).</returns> scale: function ( v ) { var te = this.elements; var x = v.x, y = v.y, z = v.z; te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; return this; //返回新的Matrix4(4x4矩陣). }, getMaxScaleOnAxis: function () { var te = this.elements; var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; return Math.sqrt( Math.max( scaleXSq, Math.max( scaleYSq, scaleZSq ) ) ); }, /* ///makeTranslation方法依據x, y, z生成平移矩陣. */ ///<summary>makeTranslation</summary> ///<param name ="x" type="Number">x分量</param> ///<param name ="y" type="Number">y分量</param> ///<param name ="z" type="Number">z分量</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),平移矩陣.</returns> makeTranslation: function ( x, y, z ) { this.set( 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 ); return this; //返回Matrix4(4x4矩陣),平移矩陣 }, /* ///makeRotationX方法生成繞x軸轉theta弧度的旋轉矩陣 /// TODO:這里是弧度還是角度,有待確認. */ ///<summary>makeRotationX</summary> ///<param name ="theta" type="Number">弧度</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),旋轉矩陣.</returns> makeRotationX: function ( theta ) { var c = Math.cos( theta ), s = Math.sin( theta ); this.set( 1, 0, 0, 0, 0, c, - s, 0, 0, s, c, 0, 0, 0, 0, 1 ); return this; //返回Matrix4(4x4矩陣),旋轉矩陣. }, /* ///makeRotationY方法生成繞y軸轉theta弧度的旋轉矩陣 /// TODO:這里是弧度還是角度,有待確認. */ ///<summary>makeRotationY</summary> ///<param name ="theta" type="Number">弧度</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),旋轉矩陣.</returns> makeRotationY: function ( theta ) { var c = Math.cos( theta ), s = Math.sin( theta ); this.set( c, 0, s, 0, 0, 1, 0, 0, - s, 0, c, 0, 0, 0, 0, 1 ); return this; //返回Matrix4(4x4矩陣),旋轉矩陣. }, /* ///makeRotationZ方法生成繞z軸轉theta弧度的旋轉矩陣 /// TODO:這里是弧度還是角度,有待確認. */ ///<summary>makeRotationZ</summary> ///<param name ="theta" type="Number">弧度</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),旋轉矩陣.</returns> makeRotationZ: function ( theta ) { var c = Math.cos( theta ), s = Math.sin( theta ); this.set( c, - s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); return this; //返回Matrix4(4x4矩陣),旋轉矩陣. }, /* ///makeRotationAxis方法生成繞隨意軸轉angle弧度的旋轉矩陣 /// TODO:這里是弧度還是角度,有待確認. */ ///<summary>makeRotationAxis</summary> ///<param name ="axis" type="Vector3"> 轉軸向量(axis必須是單位向量)</param> ///<param name ="theta" type="Number">弧度</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),旋轉矩陣.</returns> makeRotationAxis: function ( axis, angle ) { // Based on http://www.gamedev.net/reference/articles/article1199.asp var c = Math.cos( angle ); var s = Math.sin( angle ); var t = 1 - c; var x = axis.x, y = axis.y, z = axis.z; var tx = t * x, ty = t * y; this.set( tx * x + c, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 0, 0, 0, 1 ); return this; //返回Matrix4(4x4矩陣),旋轉矩陣. }, /* ///makeScale方法依據x, y, z生成縮放矩陣. */ ///<summary>makeScale</summary> ///<param name ="x" type="Number">x分量</param> ///<param name ="y" type="Number">y分量</param> ///<param name ="z" type="Number">z分量</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),縮放矩陣.</returns> makeScale: function ( x, y, z ) { this.set( x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 ); return this; //返回Matrix4(4x4矩陣),縮放矩陣. }, /* ///compose方法設置變換矩陣的平移、旋轉和縮放設置 */ ///<summary>compose</summary> ///<param name ="position" type="Vector3">平移向量</param> ///<param name ="quaternion" type="Vector3">旋轉向量</param> ///<param name ="scale" type="Vector3">縮放向量</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),變換矩陣.</returns> compose: function ( position, quaternion, scale ) { this.makeRotationFromQuaternion( quaternion ); this.scale( scale ); this.setPosition( position ); return this; //返回Matrix4(4x4矩陣),變換矩陣. }, /* ///decompose方法將轉換矩陣的平移、旋轉和縮放設置作為由三個 Vector3 對象組成的矢量返回。
第一個 Vector3 對象容納平移元素。
第二個 Vector3 對象容納旋轉元素。第三個 Vector3 對象容納縮放元素。 */ ///<summary>decompose</summary> ///<param name ="position" type="Vector3">平移向量</param> ///<param name ="quaternion" type="Vector3">旋轉向量</param> ///<param name ="scale" type="Vector3">縮放向量</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),變換矩陣.</returns> decompose: function () { var vector = new THREE.Vector3(); var matrix = new THREE.Matrix4(); return function ( position, quaternion, scale ) { var te = this.elements; var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); // if determine is negative, we need to invert one scale // 假設行列式是負數,把比例轉換成正數 var det = this.determinant(); if ( det < 0 ) { sx = - sx; } position.x = te[ 12 ]; position.y = te[ 13 ]; position.z = te[ 14 ]; // scale the rotation part // 縮放有關旋轉的元素 matrix.elements.set( this.elements ); // at this point matrix is incomplete so we can't use .copy() //這個表示點的矩陣是不完整的,我們不能使用copy()方法 var invSX = 1 / sx; var invSY = 1 / sy; var invSZ = 1 / sz; matrix.elements[ 0 ] *= invSX; matrix.elements[ 1 ] *= invSX; matrix.elements[ 2 ] *= invSX; matrix.elements[ 4 ] *= invSY; matrix.elements[ 5 ] *= invSY; matrix.elements[ 6 ] *= invSY; matrix.elements[ 8 ] *= invSZ; matrix.elements[ 9 ] *= invSZ; matrix.elements[ 10 ] *= invSZ; quaternion.setFromRotationMatrix( matrix ); scale.x = sx; scale.y = sy; scale.z = sz; return this; //返回Matrix4(4x4矩陣),變換矩陣 }; }(), /* ///makeFrustum方法依據left, right, bottom, top, near, far生成透視投影矩陣,Frustum平截頭體 */ ///<summary>makeFrustum</summary> ///<param name ="left" type="Number">指明相對於垂直平面的左側坐標位置</param> ///<param name ="right" type="Number">指明相對於垂直平面的右側坐標位置</param> ///<param name ="bottom" type="Number">指明相對於垂直平面的底部坐標位置</param> ///<param name ="top" type="Number">指明相對於垂直平面的頂部坐標位置</param> ///<param name ="near" type="Number">指明相對於深度剪切面的近的距離,必須為正數</param> ///<param name ="far" type="Number">指明相對於深度剪切面的遠的距離,必須為正數</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),透視投影矩陣.</returns> makeFrustum: function ( left, right, bottom, top, near, far ) { var te = this.elements; var x = 2 * near / ( right - left ); var y = 2 * near / ( top - bottom ); var a = ( right + left ) / ( right - left ); var b = ( top + bottom ) / ( top - bottom ); var c = - ( far + near ) / ( far - near ); var d = - 2 * far * near / ( far - near ); te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; return this; //返回Matrix4(4x4矩陣),透視投影矩陣 }, /* ///makePerspective方法依據 fov, aspect, near, far 生成透視投影矩陣,對makeFrustu()方法的封裝,適配人們習慣的表達方式. */ ///<summary>makePerspective</summary> ///<param name ="fov" type="Number">指明相機的可視角度</param> ///<param name ="aspect" type="Number">指明相機可視范圍的長寬比</param> ///<param name ="near" type="Number">指明相對於深度剪切面的近的距離,必須為正數</param> ///<param name ="far" type="Number">指明相對於深度剪切面的遠的距離,必須為正數</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),透視投影矩陣.</returns> makePerspective: function ( fov, aspect, near, far ) { var ymax = near * Math.tan( THREE.Math.degToRad( fov * 0.5 ) ); var ymin = - ymax; var xmin = ymin * aspect; var xmax = ymax * aspect; return this.makeFrustum( xmin, xmax, ymin, ymax, near, far ); //調用makeFrustum()方法,返回透視投影矩陣. }, /* ///makeOrthographic方法依據 left, right, top, bottom, near, far 生成正交矩陣. */ ///<summary>makePerspective</summary> ///<param name ="left" type="Number">指明相對於垂直平面的左側坐標位置</param> ///<param name ="right" type="Number">指明相對於垂直平面的右側坐標位置</param> ///<param name ="bottom" type="Number">指明相對於垂直平面的底部坐標位置</param> ///<param name ="top" type="Number">指明相對於垂直平面的頂部坐標位置</param> ///<param name ="near" type="Number">指明相對於深度剪切面的近的距離,必須為正數</param> ///<param name ="far" type="Number">指明相對於深度剪切面的遠的距離,必須為正數</param> ///<returns type="Matrix4">返回Matrix4(4x4矩陣),正交投影矩陣.</returns> makeOrthographic: function ( left, right, top, bottom, near, far ) { var te = this.elements; var w = right - left; var h = top - bottom; var p = far - near; var x = ( right + left ) / w; var y = ( top + bottom ) / h; var z = ( far + near ) / p; te[ 0 ] = 2 / w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; te[ 1 ] = 0; te[ 5 ] = 2 / h; te[ 9 ] = 0; te[ 13 ] = - y; te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 / p; te[ 14 ] = - z; te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; return this; //返回Matrix4(4x4矩陣),正交投影矩陣. }, /*fromArray方法 ///fromArray方法將存儲Matrix4(4x4矩陣)元素值的數組賦值給當前Matrix4(4x4矩陣)對象 */ ///<summary>fromArray</summary> ///<param name ="array" type="Array">Matrix4(4x4矩陣)元素值的數組array</param> ///<returns type="Matrix4">返回新的Matrix4(4x4矩陣)</returns> fromArray: function ( array ) { this.elements.set( array ); //調用set方法,將數組賦值給當前Matrix4(4x4矩陣)對象 return this; //返回新的Matrix4(4x4矩陣) }, /*toArray方法 ///toArray方法將當前Matrix4(4x4矩陣)的元素值賦值給數組array.返回一個數組對象. */ ///<summary>toArray</summary> ///<returns type="Array">返回含有Matrix4(4x4矩陣)元素值的數組array</returns> toArray: function () { var te = this.elements; return [ te[ 0 ], te[ 1 ], te[ 2 ], te[ 3 ], te[ 4 ], te[ 5 ], te[ 6 ], te[ 7 ], te[ 8 ], te[ 9 ], te[ 10 ], te[ 11 ], te[ 12 ], te[ 13 ], te[ 14 ], te[ 15 ] ]; //返回含有Matrix4(4x4矩陣)元素值的數組array }, /*clone方法 ///clone方法克隆一個Matrix4(4x4矩陣)對象. */ ///<summary>clone</summary> ///<returns type="Matrix4(4x4矩陣)">返回克隆的Matrix4(4x4矩陣)對象</returns> clone: function () { var te = this.elements; return new THREE.Matrix4( te[ 0 ], te[ 4 ], te[ 8 ], te[ 12 ], te[ 1 ], te[ 5 ], te[ 9 ], te[ 13 ], te[ 2 ], te[ 6 ], te[ 10 ], te[ 14 ], te[ 3 ], te[ 7 ], te[ 11 ], te[ 15 ] ); //返回克隆的Matrix4(4x4矩陣)對象 } };
商域無疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商業用途-保持一致”創作公用協議
轉載請保留此句:商域無疆 - 本博客專注於 敏捷開發及移動和物聯設備研究:數據可視化、GOLANG、Html5、WEBGL、THREE.JS,否則。出自本博客的文章拒絕轉載或再轉載,謝謝合作。
下面代碼是THREE.JS 源代碼文件里Math/Matrix4.js文件的凝視.
很多其它更新在 : https://github.com/omni360/three.js.sourcecode/blob/master/Three.js