首頁  >  文章  >  web前端  >  Three.js原始碼閱讀筆記(基礎的核心Core物件)_基礎知識

Three.js原始碼閱讀筆記(基礎的核心Core物件)_基礎知識

WBOY
WBOY原創
2016-05-16 17:45:171328瀏覽

Three.js是一個比較偉大的webgl開源庫,它簡化了瀏覽器3D編程,使得使用JavaScript在瀏覽器中創建複雜的場景變得容易很多。 Github上眾多webgl demo令我興奮不已,躍躍欲試。由於這個庫還處在開發階段,因此資料非常匱乏,愛好者大部分時間不得不透過閱讀該庫的源碼進行學習,我現在也準備這樣做。

這是第一篇筆記,先從最基礎的核心(Core)物件開始。
Core::Vector2
該構造函數用來創建一個表示二維向量的對象

複製代碼 程式碼如下:

THREE.Vector2 = function ( x, y ) {
this.x = x || 0;
this.y = y || 0;
};

Vector2物件的功能函數會採用定義建構函式的原型物件來實現,形如:
複製代碼 程式碼如下:

THREE.Vector2.prototype = {
constructor: THREE.Vector2, set: function ( x, y ) { x
this.x = x;
this.y = y;
return this;
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
return this;
},
...... // 更多的函數
};

函數set( x,y)用以指定向量的值,呼叫者本身的x,y值被影響了,而該方法本身又傳回呼叫者本身,這種情況很常見,以下不再說明。透過文字能夠表達清楚功能的函數不再引用原始碼,這一點以下也不再說明。
函數copy(v)用來將向量v複製進呼叫者。
函數add(a,b)和函數sub(a,b)分別表示對向量a,b相加和相減。
函數addSelf(v)和subSelf(v)分別表示對呼叫者本身加上或減去向量v。
函數multiplyScale(s)和divideScale(s)分別表示對呼叫者本身乘以或除以s。
函數lerpSelf(v,alpha)將呼叫者向v所指的方向旋轉alpha,當alpha為1時,呼叫者最終等於v,而當alpha=0時,呼叫者還等於原來。

複製程式碼 程式碼如下:
lerpSelf: function ( v,>

lerpSelf alpha ) ( v,> this.x = ( v.x - this.x ) * alpha;
this.y = ( v.y - this.y ) * alpha;
return this;
},

函數negate()對呼叫者取反。
函數dot(v)傳回float類型的呼叫者和向量v的點乘。
函數lengthSq()和函數length()傳回float型別的呼叫者長度平方或長度。
函數normalize()將呼叫者本身歸一化。
函數distanceToSquared(v)和distanceTo(v)將傳回呼叫者和向量v的距離。這裡的距離其實是兩向量起點都在原點時,終點之間的距離,也就是向量this-v的長度。
函數setLength(s)將向量的長度縮放至為s,方向不變。
函數equals(v)判斷呼叫者與向量v的值是否相同。
函數isZero()判斷呼叫者是否為零向量。
函數clone()傳回一個與呼叫者值一樣的新向量,相當於將其複製出去,注意與copy(v)的差異。
Core::Vector3
該構造函數創建一個表示三維向量的對象
複製代碼 程式碼如下:

THREE.Vector3 = function ( x, y, z ) {
this.x = x || 0;
this.y = y || 0 ;
this.z = z || 0;
};

三維向量和二維向量有許多共通之處,例如set,add,dot,length,clone等,此處盡數略去,只記錄三維向量比二維向量多出的部分函數。

函數setX(x),setY(y)和setZ(z)用來單獨設定某一分量的值。
函數cross(a,b)和crossSelf(v)分別使呼叫者變成a,b的叉乘或呼叫者本身與v的叉乘。叉乘是一個向量,垂直於參與叉乘的兩個向量並呈現右手螺旋法則。

函數getPositionFromMatrix(m),getRotationFromMatrix(m),getScaleFromMatrix(m)從4×4的模型矩陣中提取位置分量,旋轉分量和縮放分量。模型矩陣表示了一系列平移、旋轉、縮放變換的疊加效果。 (這裡第二個函數出現在文件中,在原始碼中被另外兩個函數取代了,也許還沒來得及更新)。
函數angleTo(v)計算呼叫者和向量v的夾角。
Core::Vector4
該構造函數創建一個表示四維向量的對象
複製代碼 程式碼如下:

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;
};

四維向量用來表示齊次座標,其函數和Vector2,Vector3中的函數功能重合,僅是多一個分量而已,這裡不再記錄。
Core::Matrix3
該建構子建立一個表示3×3矩陣的物件
THREE.Matrix3 = function () {
this.elements = new Float32Array(9 );
};
3×3矩陣有9個元素,儲存在矩陣物件的屬性elements中,elements是一個陣列。
函數getInverse(m)傳回矩陣m的逆矩陣,同時改變呼叫者本身。
函數transpose()轉置呼叫者。
函數transposeToArray(r)將呼叫者轉置進數組r而不改變自身。 (這個地方似乎源碼錯了,var m=this.m應該為var m=this.elements。)
Core::Matrix4
該構造函數創建一個表示4×4矩陣的對象,4×4矩陣在三維圖形學中非常重要,模型矩陣、視圖矩陣和投影矩陣都是這樣的矩陣。
複製程式碼 程式碼如下:

THREE.Matrix4 = function (>

THREE.Matrix4 = function (>

THREE.Matrix4 = function (>

THREE.Matrix4 = function (11, n12, n113, n n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
this.elements = new Float32Array( 16 );
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
);
};

複製程式碼


程式碼如下:


lookAt: function ( 🎜>

lookAt: function ( 🎜>

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; },
函數multiply(a,b),multiplySelf(v)和multiplyToArray(a,b,r)將兩個矩陣相乘。
函數multiplyScale(s)將物件所有16個元素都乘以s。
函數multiplyVector3(v)和multiplyVector4(v)將物件矩陣左乘四維行向量,並傳回vector3和vector4類型的行向量。如果物件矩陣是模型視圖矩陣,輸入的向量是點位置訊息,則輸出的向量則是經過模型變換和相機變換後,該點相對於相機的位置。輸入vector3型向量時,自動補足為齊次座標,返回時再砍掉第四個分量成為普通座標。

函數rotateAxis(v)使用物件矩陣左上角的3×3子矩陣左乘行向量v,得到一個新的行向量並歸一化,回傳這個新行向量。此函數同時更新了向量v的值。模型視圖矩陣左上角3×3的子矩陣包含了模型矩陣中的旋轉訊息,將該子矩陣左乘一個向量,得到的新向量其實就是原向量經過旋轉(這個旋轉效果來自於模型矩陣)得到的。因此函數名為rotateAxis。
複製程式碼 程式碼如下:

rotateAxis: function ( v🎜>

rotateAxis: function ( v ) { = 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;
},


函數crossVector(v)計算矩陣物件(呼叫者)和v的叉乘,其實就是物件矩陣左乘四維行向量v,回傳向量。這個具體是做什麼的,我還沒搞清楚。 程式碼如下:


crossVector: function ( a ) { 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;
},

函數determinant()計算矩陣的行列式值。
函數flattenToArray(flat)和函數flattenToArrayOfset(flat,offset)將矩陣轉存到一維數組中,前一個函數從flat[0]儲存到flat[15],後一個函數允許指定開始儲存的位置,從flat[offset]儲存到flat[offset 15]。

函數getPosition()和函數setPosition()用來取得或設定矩陣物件的位置分量。正如旋轉分量儲存在左上角3×3的子矩陣中,位置分量儲存在第四行前三個分量上,即element[12], element[13], element[14]中。
函數getColumeX(),getColumeY(),getColumeZ()分別擷取左上角3×3子矩陣的三列。
函數compose(translate,rotation,scale)將物件矩陣設定為由vector3類型translate物件表示的平移、由matrix3類型rotation物件表示的旋轉、由vector3類型scale物件表示的縮放這三個變換組合在一起的變換矩陣。其實就是講其直接填入模型矩陣的對應子空間。

函數decompose(translate,rotation,scale)將矩陣物件拆開到三個物件中,和上一個函數正好相反。
函數extractPosition(m)和extractRotation(m)將矩陣物件m中表示位置或旋轉的分量抽取到呼叫者物件中,例如兩個物體經過多次各不相同的變換,只需要一個物體的模型視圖矩陣extractRotation另一個物體的模型視圖矩陣,則呼叫者就和另一個物體保持變換之處相同的旋轉方位。

函數translate(v)是模型矩陣最基本的變換之一:平移變換,將模型矩陣從屬的物體平移向量v。
函數rotateX(angle),rotateY(angle),rotateZ(angle)分別將模型矩陣從屬的物體繞X,Y,Z軸旋轉角度angle。

函數rotateByAxis(axis, angle)將模型矩陣從屬的物體繞一個任意軸axis旋轉角度angle,這是上面兩條所涉及的變換的多次疊加(疊加參數由當前位置和axis參數決定),我在《模型視圖矩陣與投影矩陣:webgl筆記(1)》中曾討論到繞任一軸旋轉的問題。

這裡不應該有一個scale(s)函數嗎?可是我在原始碼中沒找到。
函數makeTranslate(x,y,z),makeRotationX(theta),makeRotationY(theta),makeRotationZ(theta),makeRotationAxis(axis,angle),makeScale(s)函數將物件矩陣直接重設為單位陣經過一次平移、或繞某軸旋轉、或單純某次縮放後的矩陣。此函數更新物件本身的值,而且更新的結果與物件先前的值毫無關聯(這也是make前綴函數的特徵)。

函數makeFrustum(...),makePerspective(...),makeOrthographic(...)也是用來初始化新矩陣,具體意義到相機類別裡面再討論,我想相機類別的建構函數裡一定會呼叫這些函數的。
函數clone()將矩陣物件複製出來並傳回。
Core::Face3
該函數創建一個三角形平面對象
複製代碼 代碼如下:

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 : [ ];
. 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物件中將所有點儲存為一個陣列);顧名思義normal是法線;color是顏色;materialIndex是頂點材質索引:這幾個參數即可以傳入vector3類型又可以傳入陣列類型。
clone(x)方法傳回一個新的,具有相同值的物件。
Core::Face4
函數會建立一個四個頂點的面,和Face3幾乎一樣,略去。
Core::Math
THREE.Math是一個“靜態類別”,沒有建構子因此也不需要透過new關鍵字初始化。該類別提供一些必要的數學工具。
函數clamp(x,a,b)將x夾在區間[a,b]中。 clampBottom(x,a)的作用類似,只不過只夾一邊。
函數mapLinear(x,a1,a2,b1,b2)計算出一個值y,使得點(x,y)落在(a1,a2)和(b1,b2)連成的直線上。
複製程式碼 程式碼如下:

mapLinear: function ( x, a11, b11, b2 ) {
return b1 ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
},

函數random16(),randInt(low,high),randFloat(low,high),randFloatSpread(range)分別產生[0,1]區間的16位元隨機浮點數,[low,high]區間隨機整數, [low,high]區間隨機浮點數,[-range/2,range/2]區間隨機浮點數。
函數sigh(x)根據x的符號回傳 1或-1。
Core::Clock
該構造函數創建時鐘(確切的說是秒錶)對象
複製代碼 程式碼如下:

THREE.Clock = function ( autoStart ) {
this.autoStart = ( autoStart !== undefined ) ? autoStart : true; startTime = 0;
this.oldTime = 0;
this.elapsedTime = 0;
this.running = false;
};

函數start()和stop()用來開始計時或停止計時。
函數getDelta()傳回呼叫函數時距離上次呼叫函數時的時間長度,如果是第一次呼叫函數,則傳回此時距離開始計時時的時間長度。如果autoStart值為真,若在呼叫getDelta()函數時尚未呼叫start()函數或已經呼叫過stop()函數,則自動開始計時並傳回0。如果autoStart()值為假,則在呼叫start()之前或stop()之後,呼叫getDelta()傳回0。

函數getElapsedTime()傳回呼叫函數時距離開始計時時的時間。

Core::Color 該構造函數構造一個表示顏色的對象

複製代碼 程式碼如下:
THREE.Color = function ( hex ) {
if ( hex !== undefined ) this.setHex( hex );
return this
}
}; ;

函數setHex(hex)以十六進位序列設定物件的r,g,b屬性。實際上在物件中,最終是以這三個屬性儲存顏色的。
複製程式碼 程式碼如下:

setHex: function ( hex ) {this.r = ( hex >> 16 & 255 ) / 255;
this.g = ( hex >> 8 & 255 ) / 255;
this.b = ( hex & 255 ) / 255;
return this;
},

函數setRGB(r,g,b)和setHSV(h,s,v)以RGB值或HSV值設定物件。
函數getHex()傳回16進位顏色值。
函數copyGammaToLinear(color),copyLinearToGamma(color)將color的rgb值分別平方或開方,賦給呼叫者物件。
函數convertGammaToLinear()和convertLinearToGamma()分別對呼叫者本身的rgb值平方或開放。
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn