首頁 >web前端 >js教程 >Three.js原始碼閱讀筆記(Object3D類別)_基礎知識

Three.js原始碼閱讀筆記(Object3D類別)_基礎知識

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

這是Three.js原始碼閱讀筆記的第二篇,直接開始。
Core::Object3D
Object3D似乎是Three.js框架中最重要的類,相當一部分其他的類都是繼承自Object3D類,例如場景類、幾何形體類、相機類別、光照類別等等:他們都是3D空間中的對象,所以稱為Object3D類別。 Object3D建構子如下:

複製程式碼 程式碼如下:

THREE.Object3D = ftionREE. {
THREE.Object3DLibrary.push( this );
this.id = THREE.Object3DIdCount ;
this.name = '';
this.properties = {};
this.parent = undefined;
this.children = [];
this.up = new THREE.Vector3( 0, 1, 0 );
this.position = new THREE.Vector3();
this>this .rotation = new THREE.Vector3();
this.eulerOrder = THREE.Object3D.defaultEulerOrder;
this.scale = new THREE.Vector3( 1, 1, 1 );
this.r. ;
this.rotationAutoUpdate = true;
this.matrix = new THREE.Matrix4();
this.matrixWorld = new THREE.Matrix4();
this.matrixRotationWorld = new THREE.Matrix4();
this.matrixRotationWorld = new THREEtation );
this.matrixAutoUpdate = true;
this.matrixWorldNeedsUpdate = true;
this.quaternion = new THREE.Quaternion();
this.useQuaternion = false; 0.0;
this.boundRadiusScale = 1.0;
this.visible = true;
this.castShadow = false;
this.receiveShadow = false;
this.PustumCulled = true; this._vector = new THREE.Vector3();
};

在介紹函數之前,需要先介紹一下這個類別的幾個重要屬性。
屬性parent和children說明,通常需要使用樹來管理眾多Object3D物件。例如一輛行駛的汽車是一個Object3D對象,控制汽車行駛路線的邏輯在該對象內部實現,汽車的每個頂點經過模型矩陣的處理後,都位於正確的位置;但是汽車擺動的雨刮器,其不但隨著汽車行駛方向運動,自身相對汽車也在左右擺動,這個擺動的邏輯無法在汽車這個物體內部的實現。解決的方法是,將雨刷設定為汽車的chidren,雨刷內部的邏輯只負責其相對於汽車的擺動。在這個樹狀結構下,一個場景Scene其實就是最頂端的Object3D,它的模型矩陣就是視圖矩陣(取決於相機)的逆矩陣。

屬性matrix和matrixWorld就很好理解了,matrix表示本地的模型矩陣,僅表示該物件的運動,而matrixWorld則需要依序向父親節點迭代,每一次迭代都左乘父親物件的本地模型矩陣,直到Scene物件——當然,實際上是左乘父親物件的全局模型矩陣。

屬性position、rotation、scale表示模型矩陣的三種變換部分,在Matrix4類中有相關說明。 rotation和eulerOrder共同描述了一個旋轉狀態,quaternion也可以描述一個旋轉狀態,具體使用哪一個方法要看useQuation的布爾值。

可以看到,關於該Object3D對象最重要的「變換狀態」資訊實際上是儲存在兩個「備份」中的,一個是matrix對象,還有一個是position等屬性,兩部分應保持一致,如果透過某種方法改變了一個備份,則另一個備份也應該在適當的時候更新。還有一些其他屬性從字面和類型就能看出其意義,不再單獨列出了。下面說函數:
函數applyMatrix(matrix)將參數matrix左乘到this.matrix上,實際上就是對該Object3D物件實行某個變換(該變換可能要經過好幾步基本變換,但是已經儲存在參數matrix裡面了)。注意,在對this.matrix執行完左乘之後,;立刻更新了position等參數的值。比起下面幾個變換函數,該函數更“高級”,允許開發者自由指定變換矩陣,而不是說“朝著x軸前進5單位距離”。

複製程式碼 程式碼如下:
applyMatrix: function ( 🎜>

applyMatrix: function ( matrix) matrix.multiply( matrix, this.matrix );
this.scale.getScaleFromMatrix( this.matrix );
var mat = new THREE.Matrix4().extractRotation( this.matrix );
. rotation.setEulerFromRotationMatrix( mat, this.eulerOrder );
this.position.getPositionFromMatrix( this.matrix );
},

函數translate(distance, axis)令該物件向axis軸指定的方向前進distance距離。函數translateX(distance),translateY(distance),translateZ(distance)令其向X,Y,Z軸前進distance距離。注意這些函數只是改變了position物件的值,而不曾改變matrix的值。
複製程式碼 程式碼如下:

translate: function ( this.matrix.rotateAxis( axis );
this.position.addSelf( axis.multiplyScalar( distance ) );
},
translateX: function ( distance ) {
this.translate( this._vector.set( 1, 0, 0 ) );
},

函數localToWorld(vector)將本地座標轉換為世界座標中,函數worldToLocal則正好相反。注意這裡的vector本地座標指的是未變換之前的座標,也就是說雨刷的預設位置的頂點座標。

函數lookAt(eye,center,up)執行其matrix屬性物件的lookAt函數(之前介紹過,matrix4物件也有一個lookAt函數),一般用於相機物件。函數只是改變了旋轉狀態,所以當matrix屬性物件執行完後,如果屬性rotationAutoUpdate為真,則會更新rotation或quaternion的值,而更新哪一個取決於屬性useQuation。
函數add(object)和函數remove(object)從當前Object3D對像中添加一個子對象,或刪除一個子對象,了解到場景中的眾多Object3D對像是用樹來管理的,這就很容易理解了。

函數traverse(callback)遍歷調用者和調用者的所有後代,callback參數是一個函數,被調用者和每一個後代物件調用callback(this)。

複製程式碼 程式碼如下:
traverse: function ( callback ) {ballback> this );
for ( var i = 0, l = this.children.length; i this.children[ i ].traverse( callback );
}
},


函數getChildByName(name,recursive)透過字串在呼叫者的子元素(recursive為false)或後代元素(recursive為true)中查詢屬性name符合的物件傳回。

函數getDescendants(array)將呼叫者的所有後代物件全部push到陣列array中。
函數updateMatrix()和updateMatrixWorld(force)將根據position,rotation或quaternion,scale參數更新matrix和matrixWorld。 updateMatrixWorld也會更新所有後代元素的matrixWorld,如果force值為真或呼叫者本身的matrixWorldNeedsUpdate值為真。在函數applyMatrix(matrix)中,改變了matrix值後立刻就更新了position,rotation等屬性,但在函數translate(distance,axis)中改變了position等變數(或直接改變position等屬性)後並沒有立刻更新matrix值,這時應該手動呼叫updateMatrix()。這些細節值得注意,你也許會認為應該加入事件監聽,一旦一個值發生變化,其他所有的都會立刻更新,但我想在,可能是出於這方面的考慮:適當的時候更新會帶來更高的效率-例如可能會頻繁地改變rotation值,但僅在使用matrix屬性之前,才對其進行更新。


複製程式碼 程式碼如下:
fupdateMatrix: function () { if ( this.useQuaternion === false ) {
this.matrix.setRotationFromEuler( this.rotation, this.eulerOrder );
} else {this
.matrix.setRotationFromQuaternion( this.quaternion );
}
if ( this.scale.x !== 1 || this.scale.y !== 1 || this.scale.z !== 1 ) {
this.matrix.scale( this.scale );
this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale.z ) ) ;
}
this.matrixWorldNeedsUpdate = true;
},
updateMatrixWorld: function ( force ) {
if ( this.matrixAutoUpdate === true ) ) {
if ( this.matrixAutoUpdate === true ) ) . >if ( this.matrixWorldNeedsUpdate === true || force === true ) {
if ( this.parent === undefined ) {
this.matrixWorld.copy( this.matrix );
} else {
this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix );
}
this.matrixWorldNeedsUpdate = false;
force = true;
}
}
for ( var i = 0, l = this.children.length; i this.children[ i ].updateMatrixWorld( force );
}
},


函數deallocate手動將呼叫者佔用的空間釋放掉,當不再需要該物件時這樣做。
Core::Projectors
管理投影矩陣的類,程式碼太複雜了,我猜會涉及到render類裡的操作,等到適當的時候再看吧。
Core::UV
這個建構函式產生一個材質座標類別-就是材質上的座標,常與頂點對應起來,光柵化後每個像素都有一個材質座標,再從材質上「取色」以實現紋理。
複製程式碼 程式碼如下:

THREE.UV = function ( u, v, v. 🎜>this.u = u || 0;
this.v = v || 0;
};

材質座標類就是一個簡化的vector2類,除了屬性名稱不同而已。

Core::Ray Core::Rectangle Core:Spline 射線類,有原點、方向、遠近截斷點。在點光源中應該有應用。矩形類、曲線類,相對都比較簡單,也不那麼“核心”,以後再看。

Core::Geometry Geometry類也是非常重要的一類,表示一個由頂點和表面構成的幾何形體。

複製代碼 代碼如下:
THREE.Geometry = function () {
THREE .GeometryLibrary.push( this );
this.id = THREE.GeometryIdCount ;
this.name = '';
this.vertices = [];
this.colors = [];
this.normals = [];
this.faces = [];
this.faceUvs = [[]];
this.faceVertexUvs = [[]];
this.morphTargets = [];
this.morphColors = [];
this.morphNormals = [];
this.skinWeights = [];
this.skinIndices = [];
this.lineDistances = [];
this.boundingBox = null;
this.boundingSphere = null;
this.hasTangents = false;
this.dynamic = true;
this.verticesNeedUpdate = fsese; >this.elementsNeedUpdate = false;
this.uvsNeedUpdate = false;
this.normalsNeedUpdate = false;
this.tangentsNeedUpdate = false; false;
this.buffersNeedUpdate = false;
};



以下兩組屬性最重要
屬性vertics是一個數組,以下兩組屬性最重要
屬性vertics是一個數組,每個元素是vector3類型的對象,表示一個頂點座標。屬性colors和normals表示和頂點對應的顏色值和發現向量,只有在很少的情況下才使用,大部分情況下,頂點的顏色和發現時在「表面」中定義的——如果立方體的6面顏色各不相同,則每個頂點實在不同的面上是不同的顏色。
屬性faces是一個數組,每個元素是face4或face3類型的對象,之前介紹face3的時候說到,face中儲存的只是頂點的索引值,透過索引值就可以在數組vertices中取到頂點的座標值。


下面說函數
applyMatrix(matrix)函數更新geometry中的所有頂點座標和表面的法線向量,所做的實際上是用變換矩陣matrix對geometry形體進行空間變換。 normalMatrix是參數matrix左上角3×3矩陣的逆轉置矩陣,該矩陣用來旋轉向量(法線,而不是頂點座標)。

複製程式碼 程式碼如下:
applyMatrix: function ( maktrix trix) = new THREE.Matrix3();
normalMatrix.getInverse( matrix ).transpose();
for ( var i = 0, il = this.vertices.length; i var vertex = this.vertices[ i ];
matrix.multiplyVector3( vertex );
}
for ( var i = 0, il = this.faces.length; i var face = this.faces[ i ];
normalMatrix.multiplyVector3( face.normal ).normalize();
for ( var j = 0, jl = face.vertexNormals.length; j normalMatrix.multiplyVector3( face.vertexNormals[ j ] ).normalize();
}
matrix.multiplyVector3( face.centroid );
}
,

}
}
,

函數ComputeCentroid()計算幾何形體中每個表面的重心(不是幾何形體自己的重心)。這個函數似乎應該放到face類別的原型上會更好,但是由於face類別內部無法取得點的座標(除非再將點座標數組的引用作為參數傳入建構函數,這樣代價就大了)而僅僅是索引值,所以只好在geometry類別的原型上定義了。下面幾個函數都是類似的情況(事實上,face類別幾乎沒有什麼成員函數)。

函數computeFaceNormals()和computeVertexNormals(areaWeight)計算法線向量,前者影響的是face數組中每個元素的normal屬性,一個face只有1個;後者face數組中每個元素的vertexNormal屬性,一個face3型物件有3個,一個face4型物件有4個,但是要注意的是,被多個表面共享的頂點,其法線向量只有一個,同時受到多個表面的影響。例如中心在原點,三組表面都垂直於軸的立方體,其第一象限中的頂點,法線向量是(1,1,1)的歸一化。雖然看起來不可思議,平面的頂點的法線居然不是垂直於平面的,但這種指定法線的方法在利用平面模擬曲面的時候有很好的效果。

函數createMorphNormal為每一個morph建立法線。 morph應該是用來顯示固定連續動畫的變形效果。
函數mergeVertics將座標值相同的點剔除,同時更新face物件中的點索引值。
Core::Quaternian
四維數旋轉類別用另一種方​​式表達一個旋轉變換,相較於rotation,可以避免萬向節死鎖問題。
複製程式碼 程式碼如下:

THREE.Quaternion = ftion( x y, z, w ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = ( w != = undefined ) ? w : 1;
};

如果不談函數,Quaternian就是一個簡單的vector4型別物件。
函數setFromEuler(v,order)透過一次歐拉旋轉設定四維數旋轉。
函數setFromAxis(axis,angle)透過繞任意軸旋轉設定四維數旋轉。
函數setFromRotationMatrix(matrix)透過旋轉矩陣設定四維數旋轉。
還有一些和vector4類別相同的函數這裡就不列了。
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn