Three.js源碼閱讀筆記(基礎(chǔ)的核心Core對象)
更新時間:2012年12月27日 16:48:50 作者:
Three.js是一個比較偉大的webgl開源庫,它簡化了瀏覽器3D編程,使得使用JavaScript在瀏覽器中創(chuàng)建復雜的場景變得容易很多接下來先從最基礎(chǔ)的核心(Core)對象開始,感興趣的朋友可以參考下
Three.js是一個比較偉大的webgl開源庫,它簡化了瀏覽器3D編程,使得使用JavaScript在瀏覽器中創(chuàng)建復雜的場景變得容易很多。Github上眾多webgl demo令我興奮不已,躍躍欲試。由于這個庫還處在開發(fā)階段,因此資料非常匱乏,愛好者大部分時間不得不通過閱讀該庫的源碼進行學習,我現(xiàn)在也準備這樣做。
這是第一篇筆記,先從最基礎(chǔ)的核心(Core)對象開始。
Core::Vector2
該構(gòu)造函數(shù)用來創(chuàng)建一個表示二維向量的對象
THREE.Vector2 = function ( x, y ) {
this.x = x || 0;
this.y = y || 0;
};
Vector2對象的功能函數(shù)采用定義構(gòu)造函數(shù)的原型對象來實現(xiàn),形如:
THREE.Vector2.prototype = {
constructor: THREE.Vector2,
set: function ( x, y ) {
this.x = x;
this.y = y;
return this;
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
return this;
},
...... // 更多的函數(shù)
};
函數(shù)set(x,y)用以指定向量的值,調(diào)用者本身的x,y值被影響了,而該方法本身又返回調(diào)用者本身,這種情況很常見,以下不再說明。通過文字能夠表述清楚功能的函數(shù)不再引用源代碼,這一點以下也不再說明。
函數(shù)copy(v)用來將向量v復制進調(diào)用者。
函數(shù)add(a,b)和函數(shù)sub(a,b)分別表示對向量a,b相加和相減。
函數(shù)addSelf(v)和subSelf(v)分別表示對調(diào)用者本身加上或減去向量v。
函數(shù)multiplyScale(s)和divideScale(s)分別表示對調(diào)用者本身乘以或除以s。
函數(shù)lerpSelf(v,alpha)將調(diào)用者向v所指的方向旋轉(zhuǎn)alpha,當alpha為1時,調(diào)用者最終等于v,而當alpha=0時,調(diào)用者還等于原來。
lerpSelf: function ( v, alpha ) {
this.x += ( v.x - this.x ) * alpha;
this.y += ( v.y - this.y ) * alpha;
return this;
},
函數(shù)negate()對調(diào)用者取反。
函數(shù)dot(v)返回float類型的調(diào)用者和向量v的點乘。
函數(shù)lengthSq()和函數(shù)length()返回float類型的調(diào)用者長度平方或長度。
函數(shù)normalize()將調(diào)用者本身歸一化。
函數(shù)distanceToSquared(v)和distanceTo(v)將返回調(diào)用者和向量v的距離。這里的距離其實是兩向量起點都在原點時,終點之間的距離,也就是向量this-v的長度。
函數(shù)setLength(s)將向量的長度縮放至為s,方向不變。
函數(shù)equals(v)判斷調(diào)用者與向量v的值是否相同。
函數(shù)isZero()判斷調(diào)用者是否是零向量。
函數(shù)clone()返回一個與調(diào)用者值一樣的新向量,相當于將其復制出去,注意與copy(v)的區(qū)別。
Core::Vector3
該構(gòu)造函數(shù)創(chuàng)建一個表示三維向量的對象
THREE.Vector3 = function ( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
};
三維向量和二維向量有許多共通之處,比如set,add,dot,length,clone等,此處盡數(shù)略去,只記錄三維向量比二維向量多出的部分函數(shù)。
函數(shù)setX(x),setY(y)和setZ(z)用來單獨設(shè)置某一分量的值。
函數(shù)cross(a,b)和crossSelf(v)分別使調(diào)用者變?yōu)閍,b的叉乘或者調(diào)用者本身與v的叉乘。叉乘是一個向量,垂直于參與叉乘的兩個向量并呈右手螺旋法則。
函數(shù)getPositionFromMatrix(m),getRotationFromMatrix(m),getScaleFromMatrix(m)從4×4的模型矩陣中提取位置分量,旋轉(zhuǎn)分量和縮放分量。模型矩陣表示了一系列平移、旋轉(zhuǎn)、縮放變換的疊加效果。(這里第二個函數(shù)出現(xiàn)在文檔中,在源碼中被另外兩個函數(shù)代替了,也許還沒來得及更新)。
函數(shù)angleTo(v)計算調(diào)用者和向量v的夾角。
Core::Vector4
該構(gòu)造函數(shù)創(chuàng)建一個表示四維向量的對象
THREE.Vector4 = function ( x, y, z, w ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = ( w !== undefined ) ? w : 1;
};
四維向量用來表示齊次坐標,其函數(shù)和Vector2,Vector3中的函數(shù)功能重合,僅僅是多一個分量而已,這里不再記錄。
Core::Matrix3
該構(gòu)造函數(shù)創(chuàng)建一個表示3×3矩陣的對象
THREE.Matrix3 = function () {
this.elements = new Float32Array(9);
};
3×3矩陣有9個元素,存儲在矩陣對象的屬性elements中,elements是一個數(shù)組。
函數(shù)getInverse(m)返回矩陣m的逆矩陣,同時改變調(diào)用者本身。
函數(shù)transpose()轉(zhuǎn)置調(diào)用者。
函數(shù)transposeToArray(r)將調(diào)用者轉(zhuǎn)置進數(shù)組r而不改變自身。(這個地方似乎源碼錯了,var m=this.m應(yīng)該為var m=this.elements。)
Core::Matrix4
該構(gòu)造函數(shù)創(chuàng)建一個表示4×4矩陣的對象,4×4矩陣在三維圖形學中非常重要,模型矩陣、視圖矩陣和投影矩陣都是這樣的矩陣。
THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
this.elements = new Float32Array( 16 );
this.set(
( n11 !== undefined ) ? n11 : 1, n12 || 0, n13 || 0, n14 || 0,
n21 || 0, ( n22 !== undefined ) ? n22 : 1, n23 || 0, n24 || 0,
n31 || 0, n32 || 0, ( n33 !== undefined ) ? n33 : 1, n34 || 0,
n41 || 0, n42 || 0, n43 || 0, ( n44 !== undefined ) ? n44 : 1
);
};
在Matrix3對象中出現(xiàn)的幾個函數(shù)在Matrix4中有相同的作用,這里也略去。
函數(shù)identity()將對象重置為單位陣。
函數(shù)lookAt(eye,center,up)將對象設(shè)定為一個視圖矩陣,參數(shù)都是Vector3對象,該矩陣只會用到eye和center的相對位置。該視圖矩陣表示,攝像機在eye位置看向center位置,且向上的向量(這一點稍后解釋)為up時的視圖矩陣。視圖矩陣又可以看做攝像機的模型矩陣,所以該函數(shù)產(chǎn)生的矩陣又可以表示以下變換:將物體從原點平移至位置center-eye,再將其旋轉(zhuǎn)至向上的向量為up。向上的向量up用來固定相機,可以想象當相機固定在一點,鏡頭朝向固定方向的時候,還是可以在一個維度里自由旋轉(zhuǎn)的,up向量固定相機的這個維度。
lookAt: function ( eye, target, up ) {
var te = this.elements;
var x = THREE.Matrix4.__v1; // 空Vector3對象,下同
var y = THREE.Matrix4.__v2;
var z = THREE.Matrix4.__v3;
z.sub( eye, target ).normalize();
if ( z.length() === 0 ) {
z.z = 1;
}
x.cross( up, z ).normalize();
if ( x.length() === 0 ) {
z.x += 0.0001;
x.cross( up, z ).normalize();
}
y.cross( 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;
},
函數(shù)multiply(a,b),multiplySelf(v)和multiplyToArray(a,b,r)將兩個矩陣相乘。
函數(shù)multiplyScale(s)將對象所有16個元素都乘以s。
函數(shù)multiplyVector3(v)和multiplyVector4(v)將對象矩陣左乘四維行向量,返回vector3和vector4類型的行向量。如果對象矩陣是模型視圖矩陣,輸入的向量是點位置信息,則輸出的向量則是經(jīng)過模型變換和相機變換后,該點相對于相機的位置。輸入vector3類型向量時,自動補足為齊次坐標,返回時再砍掉第四個分量成為普通坐標。
函數(shù)rotateAxis(v)使用對象矩陣左上角的3×3子矩陣左乘行向量v,得到一個新的行向量并歸一化,返回這個新行向量。該函數(shù)同時更新了向量v的值。模型視圖矩陣左上角3×3的子矩陣包含了模型矩陣中的旋轉(zhuǎn)信息,將該子矩陣左乘一個向量,得到的新向量實際上就是原向量經(jīng)過旋轉(zhuǎn)(該旋轉(zhuǎn)效果來自于模型矩陣)得到的。因此該函數(shù)名為rotateAxis。
rotateAxis: function ( v ) {
var te = this.elements;
var vx = v.x, vy = v.y, vz = v.z;
v.x = vx * te[0] + vy * te[4] + vz * te[8];
v.y = vx * te[1] + vy * te[5] + vz * te[9];
v.z = vx * te[2] + vy * te[6] + vz * te[10];
v.normalize();
return v;
},
函數(shù)crossVector(v)計算矩陣對象(調(diào)用者)和v的叉乘,實際上就是對象矩陣左乘四維行向量v,返回向量。這個具體是做什么的,我還沒弄明白。
crossVector: function ( a ) {
var te = this.elements;
var v = new THREE.Vector4();
v.x = te[0] * a.x + te[4] * a.y + te[8] * a.z + te[12] * a.w;
v.y = te[1] * a.x + te[5] * a.y + te[9] * a.z + te[13] * a.w;
v.z = te[2] * a.x + te[6] * a.y + te[10] * a.z + te[14] * a.w;
v.w = ( a.w ) ? te[3] * a.x + te[7] * a.y + te[11] * a.z + te[15] * a.w : 1;
return v;
},
函數(shù)determinant()計算矩陣的行列式值。
函數(shù)flattenToArray(flat)和函數(shù)flattenToArrayOfset(flat,offset)將矩陣轉(zhuǎn)存到一維數(shù)組中,前一個函數(shù)從flat[0]存儲到flat[15],后一個函數(shù)允許指定開始存儲的位置,從flat[offset]存儲到flat[offset+15]。
函數(shù)getPosition()和函數(shù)setPosition()用來獲取或設(shè)置矩陣對象的位置分量。正如旋轉(zhuǎn)分量存儲在左上角3×3的子矩陣中,位置分量存儲在第四行前三個分量上,即element[12], element[13], element[14]中。
函數(shù)getColumeX(),getColumeY(),getColumeZ()分別提取左上角3×3子矩陣的三列。
函數(shù)compose(translate,rotation,scale)將對象矩陣設(shè)置為由vector3類型translate對象表示的平移、由matrix3類型rotation對象表示的旋轉(zhuǎn)、由vector3類型scale對象表示的縮放這三個變換組合到一起的變換矩陣。實際上就是講其直接填充到模型矩陣的相應(yīng)子空間。
函數(shù)decompose(translate,rotation,scale)將矩陣對象拆開到三個對象中,和上一個函數(shù)正好相反。
函數(shù)extractPosition(m)和extractRotation(m)將矩陣對象m中表示位置或旋轉(zhuǎn)的分量抽取到調(diào)用者對象中,比如兩個物體經(jīng)過多次各不相同的變換,只需要一個物體的模型視圖矩陣extractRotation另一個物體的模型視圖矩陣,則調(diào)用者就和另外一個物體保持著變換之處相同的旋轉(zhuǎn)方位。
函數(shù)translate(v)是模型矩陣最基本的變換之一:平移變換,將模型矩陣從屬的物體平移向量v。
函數(shù)rotateX(angle),rotateY(angle),rotateZ(angle)分別將模型矩陣從屬的物體繞X,Y,Z軸旋轉(zhuǎn)角度angle。
函數(shù)rotateByAxis(axis, angle)將模型矩陣從屬的物體繞一個任意軸axis旋轉(zhuǎn)角度angle,這是上面兩條所涉及的變換的多次疊加(疊加參數(shù)由當前位置和axis參數(shù)決定),我在《模型視圖矩陣和投影矩陣:webgl筆記(1)》中曾討論到繞任意軸旋轉(zhuǎn)的問題。
這里不應(yīng)該有一個scale(s)函數(shù)嗎?可是我在源碼中沒找到。
函數(shù)makeTranslate(x,y,z),makeRotationX(theta),makeRotationY(theta),makeRotationZ(theta),makeRotationAxis(axis,angle),makeScale(s)函數(shù)將對象矩陣直接重置為單位陣經(jīng)過一次平移、或繞某軸旋轉(zhuǎn)、或單純某次縮放后的矩陣。該函數(shù)更新對象本身的值,而且更新的結(jié)果與對象之前的值毫無關(guān)聯(lián)(這也是make前綴函數(shù)的特點)。
函數(shù)makeFrustum(...),makePerspective(...),makeOrthographic(...)也是用來初始化新矩陣,具體含義到相機類里面再討論,我想相機類的構(gòu)造函數(shù)里一定會調(diào)用這些函數(shù)的。
函數(shù)clone()將矩陣對象復制出來并返回。
Core::Face3
該函數(shù)創(chuàng)建一個三角形平面對象
THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) {
this.a = a;
this.b = b;
this.c = c;
this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
this.vertexNormals = normal instanceof Array ? normal : [ ];
this.color = color instanceof THREE.Color ? color : new THREE.Color();
this.vertexColors = color instanceof Array ? color : [];
this.vertexTangents = [];
this.materialIndex = materialIndex;
this.centroid = new THREE.Vector3();
};
對象的a,b,c值是三個頂點的索引(后面會說到,Mesh對象中將所有點存儲為一個數(shù)組);顧名思義normal是法線;color是顏色;materialIndex是頂點材質(zhì)索引:這幾個參數(shù)即可以傳入vector3類型又可以傳入數(shù)組類型。
clone(x)方法返回一個新的,具有相同值的對象。
Core::Face4
該函數(shù)創(chuàng)建一個四個頂點的面,和Face3幾乎一樣,略去。
Core::Math
THREE.Math是一個“靜態(tài)類”,沒有構(gòu)造函數(shù)因此也不需要通過new關(guān)鍵字初始化。該類提供一些必要的數(shù)學工具。
函數(shù)clamp(x,a,b)將x夾在區(qū)間[a,b]中。clampBottom(x,a)的作用類似,只不過只夾一邊。
函數(shù)mapLinear(x,a1,a2,b1,b2)計算出一個值y,使得點(x,y)落在(a1,a2)和(b1,b2)連成的直線上。
mapLinear: function ( x, a1, a2, b1, b2 ) {
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
},
函數(shù)random16(),randInt(low,high),randFloat(low,high),randFloatSpread(range)分別產(chǎn)生[0,1]區(qū)間的16位隨機浮點數(shù),[low,high]區(qū)間隨機整數(shù),[low,high]區(qū)間隨機浮點數(shù),[-range/2,range/2]區(qū)間隨機浮點數(shù)。
函數(shù)sigh(x)根據(jù)x的符號返回+1或-1。
Core::Clock
該構(gòu)造函數(shù)創(chuàng)建時鐘(確切的說是秒表)對象
THREE.Clock = function ( autoStart ) {
this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
this.startTime = 0;
this.oldTime = 0;
this.elapsedTime = 0;
this.running = false;
};
函數(shù)start()和stop()用來開始計時或停止計時。
函數(shù)getDelta()返回調(diào)用該函數(shù)時距離上一次調(diào)用該函數(shù)時的時間長度,如果是第一次調(diào)用該函數(shù),則返回此時距離開始計時時的時間長度。如果autoStart值為真,若在調(diào)用getDelta()函數(shù)時尚未調(diào)用start()函數(shù)或者已經(jīng)調(diào)用過stop()函數(shù),則自動開始計時并返回0。如果autoStart()值為假,則在調(diào)用start()之前或stop()之后,調(diào)用getDelta()返回0。
函數(shù)getElapsedTime()返回調(diào)用該函數(shù)時距離開始計時時的時間。
Core::Color
該構(gòu)造函數(shù)構(gòu)造一個表示顏色的對象
THREE.Color = function ( hex ) {
if ( hex !== undefined ) this.setHex( hex );
return this;
};
函數(shù)setHex(hex)以十六進制序列設(shè)置對象的r,g,b屬性。實際上在對象中,最終是以這三個屬性存儲顏色的。
setHex: function ( hex ) {
hex = Math.floor( hex );
this.r = ( hex >> 16 & 255 ) / 255;
this.g = ( hex >> 8 & 255 ) / 255;
this.b = ( hex & 255 ) / 255;
return this;
},
函數(shù)setRGB(r,g,b)和setHSV(h,s,v)以RGB值或HSV值設(shè)置對象。
函數(shù)getHex()返回16進制顏色值。
函數(shù)copyGammaToLinear(color),copyLinearToGamma(color)將color的rgb值分別平方或開方,賦給調(diào)用者對象。
函數(shù)convertGammaToLinear()和convertLinearToGamma()分別對調(diào)用者自身的rgb值平方或開放。
這是第一篇筆記,先從最基礎(chǔ)的核心(Core)對象開始。
Core::Vector2
該構(gòu)造函數(shù)用來創(chuàng)建一個表示二維向量的對象
復制代碼 代碼如下:
THREE.Vector2 = function ( x, y ) {
this.x = x || 0;
this.y = y || 0;
};
Vector2對象的功能函數(shù)采用定義構(gòu)造函數(shù)的原型對象來實現(xiàn),形如:
復制代碼 代碼如下:
THREE.Vector2.prototype = {
constructor: THREE.Vector2,
set: function ( x, y ) {
this.x = x;
this.y = y;
return this;
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
return this;
},
...... // 更多的函數(shù)
};
函數(shù)set(x,y)用以指定向量的值,調(diào)用者本身的x,y值被影響了,而該方法本身又返回調(diào)用者本身,這種情況很常見,以下不再說明。通過文字能夠表述清楚功能的函數(shù)不再引用源代碼,這一點以下也不再說明。
函數(shù)copy(v)用來將向量v復制進調(diào)用者。
函數(shù)add(a,b)和函數(shù)sub(a,b)分別表示對向量a,b相加和相減。
函數(shù)addSelf(v)和subSelf(v)分別表示對調(diào)用者本身加上或減去向量v。
函數(shù)multiplyScale(s)和divideScale(s)分別表示對調(diào)用者本身乘以或除以s。
函數(shù)lerpSelf(v,alpha)將調(diào)用者向v所指的方向旋轉(zhuǎn)alpha,當alpha為1時,調(diào)用者最終等于v,而當alpha=0時,調(diào)用者還等于原來。
復制代碼 代碼如下:
lerpSelf: function ( v, alpha ) {
this.x += ( v.x - this.x ) * alpha;
this.y += ( v.y - this.y ) * alpha;
return this;
},
函數(shù)negate()對調(diào)用者取反。
函數(shù)dot(v)返回float類型的調(diào)用者和向量v的點乘。
函數(shù)lengthSq()和函數(shù)length()返回float類型的調(diào)用者長度平方或長度。
函數(shù)normalize()將調(diào)用者本身歸一化。
函數(shù)distanceToSquared(v)和distanceTo(v)將返回調(diào)用者和向量v的距離。這里的距離其實是兩向量起點都在原點時,終點之間的距離,也就是向量this-v的長度。
函數(shù)setLength(s)將向量的長度縮放至為s,方向不變。
函數(shù)equals(v)判斷調(diào)用者與向量v的值是否相同。
函數(shù)isZero()判斷調(diào)用者是否是零向量。
函數(shù)clone()返回一個與調(diào)用者值一樣的新向量,相當于將其復制出去,注意與copy(v)的區(qū)別。
Core::Vector3
該構(gòu)造函數(shù)創(chuàng)建一個表示三維向量的對象
復制代碼 代碼如下:
THREE.Vector3 = function ( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
};
三維向量和二維向量有許多共通之處,比如set,add,dot,length,clone等,此處盡數(shù)略去,只記錄三維向量比二維向量多出的部分函數(shù)。
函數(shù)setX(x),setY(y)和setZ(z)用來單獨設(shè)置某一分量的值。
函數(shù)cross(a,b)和crossSelf(v)分別使調(diào)用者變?yōu)閍,b的叉乘或者調(diào)用者本身與v的叉乘。叉乘是一個向量,垂直于參與叉乘的兩個向量并呈右手螺旋法則。
函數(shù)getPositionFromMatrix(m),getRotationFromMatrix(m),getScaleFromMatrix(m)從4×4的模型矩陣中提取位置分量,旋轉(zhuǎn)分量和縮放分量。模型矩陣表示了一系列平移、旋轉(zhuǎn)、縮放變換的疊加效果。(這里第二個函數(shù)出現(xiàn)在文檔中,在源碼中被另外兩個函數(shù)代替了,也許還沒來得及更新)。
函數(shù)angleTo(v)計算調(diào)用者和向量v的夾角。
Core::Vector4
該構(gòu)造函數(shù)創(chuàng)建一個表示四維向量的對象
復制代碼 代碼如下:
THREE.Vector4 = function ( x, y, z, w ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = ( w !== undefined ) ? w : 1;
};
四維向量用來表示齊次坐標,其函數(shù)和Vector2,Vector3中的函數(shù)功能重合,僅僅是多一個分量而已,這里不再記錄。
Core::Matrix3
該構(gòu)造函數(shù)創(chuàng)建一個表示3×3矩陣的對象
THREE.Matrix3 = function () {
this.elements = new Float32Array(9);
};
3×3矩陣有9個元素,存儲在矩陣對象的屬性elements中,elements是一個數(shù)組。
函數(shù)getInverse(m)返回矩陣m的逆矩陣,同時改變調(diào)用者本身。
函數(shù)transpose()轉(zhuǎn)置調(diào)用者。
函數(shù)transposeToArray(r)將調(diào)用者轉(zhuǎn)置進數(shù)組r而不改變自身。(這個地方似乎源碼錯了,var m=this.m應(yīng)該為var m=this.elements。)
Core::Matrix4
該構(gòu)造函數(shù)創(chuàng)建一個表示4×4矩陣的對象,4×4矩陣在三維圖形學中非常重要,模型矩陣、視圖矩陣和投影矩陣都是這樣的矩陣。
復制代碼 代碼如下:
THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
this.elements = new Float32Array( 16 );
this.set(
( n11 !== undefined ) ? n11 : 1, n12 || 0, n13 || 0, n14 || 0,
n21 || 0, ( n22 !== undefined ) ? n22 : 1, n23 || 0, n24 || 0,
n31 || 0, n32 || 0, ( n33 !== undefined ) ? n33 : 1, n34 || 0,
n41 || 0, n42 || 0, n43 || 0, ( n44 !== undefined ) ? n44 : 1
);
};
在Matrix3對象中出現(xiàn)的幾個函數(shù)在Matrix4中有相同的作用,這里也略去。
函數(shù)identity()將對象重置為單位陣。
函數(shù)lookAt(eye,center,up)將對象設(shè)定為一個視圖矩陣,參數(shù)都是Vector3對象,該矩陣只會用到eye和center的相對位置。該視圖矩陣表示,攝像機在eye位置看向center位置,且向上的向量(這一點稍后解釋)為up時的視圖矩陣。視圖矩陣又可以看做攝像機的模型矩陣,所以該函數(shù)產(chǎn)生的矩陣又可以表示以下變換:將物體從原點平移至位置center-eye,再將其旋轉(zhuǎn)至向上的向量為up。向上的向量up用來固定相機,可以想象當相機固定在一點,鏡頭朝向固定方向的時候,還是可以在一個維度里自由旋轉(zhuǎn)的,up向量固定相機的這個維度。
復制代碼 代碼如下:
lookAt: function ( eye, target, up ) {
var te = this.elements;
var x = THREE.Matrix4.__v1; // 空Vector3對象,下同
var y = THREE.Matrix4.__v2;
var z = THREE.Matrix4.__v3;
z.sub( eye, target ).normalize();
if ( z.length() === 0 ) {
z.z = 1;
}
x.cross( up, z ).normalize();
if ( x.length() === 0 ) {
z.x += 0.0001;
x.cross( up, z ).normalize();
}
y.cross( 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;
},
函數(shù)multiply(a,b),multiplySelf(v)和multiplyToArray(a,b,r)將兩個矩陣相乘。
函數(shù)multiplyScale(s)將對象所有16個元素都乘以s。
函數(shù)multiplyVector3(v)和multiplyVector4(v)將對象矩陣左乘四維行向量,返回vector3和vector4類型的行向量。如果對象矩陣是模型視圖矩陣,輸入的向量是點位置信息,則輸出的向量則是經(jīng)過模型變換和相機變換后,該點相對于相機的位置。輸入vector3類型向量時,自動補足為齊次坐標,返回時再砍掉第四個分量成為普通坐標。
函數(shù)rotateAxis(v)使用對象矩陣左上角的3×3子矩陣左乘行向量v,得到一個新的行向量并歸一化,返回這個新行向量。該函數(shù)同時更新了向量v的值。模型視圖矩陣左上角3×3的子矩陣包含了模型矩陣中的旋轉(zhuǎn)信息,將該子矩陣左乘一個向量,得到的新向量實際上就是原向量經(jīng)過旋轉(zhuǎn)(該旋轉(zhuǎn)效果來自于模型矩陣)得到的。因此該函數(shù)名為rotateAxis。
復制代碼 代碼如下:
rotateAxis: function ( v ) {
var te = this.elements;
var vx = v.x, vy = v.y, vz = v.z;
v.x = vx * te[0] + vy * te[4] + vz * te[8];
v.y = vx * te[1] + vy * te[5] + vz * te[9];
v.z = vx * te[2] + vy * te[6] + vz * te[10];
v.normalize();
return v;
},
函數(shù)crossVector(v)計算矩陣對象(調(diào)用者)和v的叉乘,實際上就是對象矩陣左乘四維行向量v,返回向量。這個具體是做什么的,我還沒弄明白。
復制代碼 代碼如下:
crossVector: function ( a ) {
var te = this.elements;
var v = new THREE.Vector4();
v.x = te[0] * a.x + te[4] * a.y + te[8] * a.z + te[12] * a.w;
v.y = te[1] * a.x + te[5] * a.y + te[9] * a.z + te[13] * a.w;
v.z = te[2] * a.x + te[6] * a.y + te[10] * a.z + te[14] * a.w;
v.w = ( a.w ) ? te[3] * a.x + te[7] * a.y + te[11] * a.z + te[15] * a.w : 1;
return v;
},
函數(shù)determinant()計算矩陣的行列式值。
函數(shù)flattenToArray(flat)和函數(shù)flattenToArrayOfset(flat,offset)將矩陣轉(zhuǎn)存到一維數(shù)組中,前一個函數(shù)從flat[0]存儲到flat[15],后一個函數(shù)允許指定開始存儲的位置,從flat[offset]存儲到flat[offset+15]。
函數(shù)getPosition()和函數(shù)setPosition()用來獲取或設(shè)置矩陣對象的位置分量。正如旋轉(zhuǎn)分量存儲在左上角3×3的子矩陣中,位置分量存儲在第四行前三個分量上,即element[12], element[13], element[14]中。
函數(shù)getColumeX(),getColumeY(),getColumeZ()分別提取左上角3×3子矩陣的三列。
函數(shù)compose(translate,rotation,scale)將對象矩陣設(shè)置為由vector3類型translate對象表示的平移、由matrix3類型rotation對象表示的旋轉(zhuǎn)、由vector3類型scale對象表示的縮放這三個變換組合到一起的變換矩陣。實際上就是講其直接填充到模型矩陣的相應(yīng)子空間。
函數(shù)decompose(translate,rotation,scale)將矩陣對象拆開到三個對象中,和上一個函數(shù)正好相反。
函數(shù)extractPosition(m)和extractRotation(m)將矩陣對象m中表示位置或旋轉(zhuǎn)的分量抽取到調(diào)用者對象中,比如兩個物體經(jīng)過多次各不相同的變換,只需要一個物體的模型視圖矩陣extractRotation另一個物體的模型視圖矩陣,則調(diào)用者就和另外一個物體保持著變換之處相同的旋轉(zhuǎn)方位。
函數(shù)translate(v)是模型矩陣最基本的變換之一:平移變換,將模型矩陣從屬的物體平移向量v。
函數(shù)rotateX(angle),rotateY(angle),rotateZ(angle)分別將模型矩陣從屬的物體繞X,Y,Z軸旋轉(zhuǎn)角度angle。
函數(shù)rotateByAxis(axis, angle)將模型矩陣從屬的物體繞一個任意軸axis旋轉(zhuǎn)角度angle,這是上面兩條所涉及的變換的多次疊加(疊加參數(shù)由當前位置和axis參數(shù)決定),我在《模型視圖矩陣和投影矩陣:webgl筆記(1)》中曾討論到繞任意軸旋轉(zhuǎn)的問題。
這里不應(yīng)該有一個scale(s)函數(shù)嗎?可是我在源碼中沒找到。
函數(shù)makeTranslate(x,y,z),makeRotationX(theta),makeRotationY(theta),makeRotationZ(theta),makeRotationAxis(axis,angle),makeScale(s)函數(shù)將對象矩陣直接重置為單位陣經(jīng)過一次平移、或繞某軸旋轉(zhuǎn)、或單純某次縮放后的矩陣。該函數(shù)更新對象本身的值,而且更新的結(jié)果與對象之前的值毫無關(guān)聯(lián)(這也是make前綴函數(shù)的特點)。
函數(shù)makeFrustum(...),makePerspective(...),makeOrthographic(...)也是用來初始化新矩陣,具體含義到相機類里面再討論,我想相機類的構(gòu)造函數(shù)里一定會調(diào)用這些函數(shù)的。
函數(shù)clone()將矩陣對象復制出來并返回。
Core::Face3
該函數(shù)創(chuàng)建一個三角形平面對象
復制代碼 代碼如下:
THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) {
this.a = a;
this.b = b;
this.c = c;
this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
this.vertexNormals = normal instanceof Array ? normal : [ ];
this.color = color instanceof THREE.Color ? color : new THREE.Color();
this.vertexColors = color instanceof Array ? color : [];
this.vertexTangents = [];
this.materialIndex = materialIndex;
this.centroid = new THREE.Vector3();
};
對象的a,b,c值是三個頂點的索引(后面會說到,Mesh對象中將所有點存儲為一個數(shù)組);顧名思義normal是法線;color是顏色;materialIndex是頂點材質(zhì)索引:這幾個參數(shù)即可以傳入vector3類型又可以傳入數(shù)組類型。
clone(x)方法返回一個新的,具有相同值的對象。
Core::Face4
該函數(shù)創(chuàng)建一個四個頂點的面,和Face3幾乎一樣,略去。
Core::Math
THREE.Math是一個“靜態(tài)類”,沒有構(gòu)造函數(shù)因此也不需要通過new關(guān)鍵字初始化。該類提供一些必要的數(shù)學工具。
函數(shù)clamp(x,a,b)將x夾在區(qū)間[a,b]中。clampBottom(x,a)的作用類似,只不過只夾一邊。
函數(shù)mapLinear(x,a1,a2,b1,b2)計算出一個值y,使得點(x,y)落在(a1,a2)和(b1,b2)連成的直線上。
復制代碼 代碼如下:
mapLinear: function ( x, a1, a2, b1, b2 ) {
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
},
函數(shù)random16(),randInt(low,high),randFloat(low,high),randFloatSpread(range)分別產(chǎn)生[0,1]區(qū)間的16位隨機浮點數(shù),[low,high]區(qū)間隨機整數(shù),[low,high]區(qū)間隨機浮點數(shù),[-range/2,range/2]區(qū)間隨機浮點數(shù)。
函數(shù)sigh(x)根據(jù)x的符號返回+1或-1。
Core::Clock
該構(gòu)造函數(shù)創(chuàng)建時鐘(確切的說是秒表)對象
復制代碼 代碼如下:
THREE.Clock = function ( autoStart ) {
this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
this.startTime = 0;
this.oldTime = 0;
this.elapsedTime = 0;
this.running = false;
};
函數(shù)start()和stop()用來開始計時或停止計時。
函數(shù)getDelta()返回調(diào)用該函數(shù)時距離上一次調(diào)用該函數(shù)時的時間長度,如果是第一次調(diào)用該函數(shù),則返回此時距離開始計時時的時間長度。如果autoStart值為真,若在調(diào)用getDelta()函數(shù)時尚未調(diào)用start()函數(shù)或者已經(jīng)調(diào)用過stop()函數(shù),則自動開始計時并返回0。如果autoStart()值為假,則在調(diào)用start()之前或stop()之后,調(diào)用getDelta()返回0。
函數(shù)getElapsedTime()返回調(diào)用該函數(shù)時距離開始計時時的時間。
Core::Color
該構(gòu)造函數(shù)構(gòu)造一個表示顏色的對象
復制代碼 代碼如下:
THREE.Color = function ( hex ) {
if ( hex !== undefined ) this.setHex( hex );
return this;
};
函數(shù)setHex(hex)以十六進制序列設(shè)置對象的r,g,b屬性。實際上在對象中,最終是以這三個屬性存儲顏色的。
復制代碼 代碼如下:
setHex: function ( hex ) {
hex = Math.floor( hex );
this.r = ( hex >> 16 & 255 ) / 255;
this.g = ( hex >> 8 & 255 ) / 255;
this.b = ( hex & 255 ) / 255;
return this;
},
函數(shù)setRGB(r,g,b)和setHSV(h,s,v)以RGB值或HSV值設(shè)置對象。
函數(shù)getHex()返回16進制顏色值。
函數(shù)copyGammaToLinear(color),copyLinearToGamma(color)將color的rgb值分別平方或開方,賦給調(diào)用者對象。
函數(shù)convertGammaToLinear()和convertLinearToGamma()分別對調(diào)用者自身的rgb值平方或開放。
相關(guān)文章
JavaScript Math.floor方法(對數(shù)值向下取整)
這篇文章主要介紹了Math.floor 方法用于對數(shù)值向下取整,即得到小于或等于該數(shù)值的最大整數(shù),需要的朋友可以參考下2015-01-01Javascript模塊化編程(三)require.js的用法及功能介紹
這個系列的第一部分和第二部分,介紹了Javascript模塊原型和理論概念,今天介紹如何將它們用于實戰(zhàn)。我采用的是一個非常流行的庫require.js感興趣的朋友可以了解下啊2013-01-01THREE.JS入門教程(4)創(chuàng)建粒子系統(tǒng)
Three.js是一個偉大的開源WebGL庫,WebGL允許JavaScript操作GPU,在瀏覽器端實現(xiàn)真正意義的3D本文將介紹創(chuàng)建一個粒子系統(tǒng)/風格/引入物理等等,感興趣的朋友可以了解下哦,希望本文對你有所幫助2013-01-01JavaScript中把數(shù)字轉(zhuǎn)換為字符串的程序代碼
本篇文章是對JavaScript中把數(shù)字轉(zhuǎn)換為字符串的實現(xiàn)代碼進行了詳細的分析介紹,需要的朋友參考下2013-06-06onkeyup,onkeydown和onkeypress的區(qū)別介紹
三者在事件的響應(yīng)上還有一點不同,就是onkeydown 、onkeypress事件響應(yīng)的時候輸入的字符并沒有被系統(tǒng)接受,而響應(yīng)onkeyup的時候,輸入流已經(jīng)被系統(tǒng)接受2013-10-10