欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Three.js源碼閱讀筆記(Object3D類(lèi))

 更新時(shí)間:2012年12月27日 16:41:53   作者:  
Object3D似乎是Three.js框架中最重要的類(lèi),相當(dāng)一部分其他的類(lèi)都是繼承自O(shè)bject3D類(lèi),比如場(chǎng)景類(lèi)、幾何形體類(lèi)、相機(jī)類(lèi)、光照類(lèi)等等:他們都是3D空間中的對(duì)象,所以稱(chēng)為Object3D類(lèi),需要了解的朋友可以參考下
這是Three.js源碼閱讀筆記的第二篇,直接開(kāi)始。
Core::Object3D
Object3D似乎是Three.js框架中最重要的類(lèi),相當(dāng)一部分其他的類(lèi)都是繼承自O(shè)bject3D類(lèi),比如場(chǎng)景類(lèi)、幾何形體類(lèi)、相機(jī)類(lèi)、光照類(lèi)等等:他們都是3D空間中的對(duì)象,所以稱(chēng)為Object3D類(lèi)。Object3D構(gòu)造函數(shù)如下:
復(fù)制代碼 代碼如下:

THREE.Object3D = function () {
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.rotation = new THREE.Vector3();
this.eulerOrder = THREE.Object3D.defaultEulerOrder;
this.scale = new THREE.Vector3( 1, 1, 1 );
this.renderDepth = null;
this.rotationAutoUpdate = true;
this.matrix = new THREE.Matrix4();
this.matrixWorld = new THREE.Matrix4();
this.matrixRotationWorld = new THREE.Matrix4();
this.matrixAutoUpdate = true;
this.matrixWorldNeedsUpdate = true;
this.quaternion = new THREE.Quaternion();
this.useQuaternion = false;
this.boundRadius = 0.0;
this.boundRadiusScale = 1.0;
this.visible = true;
this.castShadow = false;
this.receiveShadow = false;
this.frustumCulled = true;
this._vector = new THREE.Vector3();
};

在介紹函數(shù)之前,需要先介紹一下這個(gè)類(lèi)的幾個(gè)重要屬性。
屬性parent和children說(shuō)明,通常需要使用樹(shù)來(lái)管理眾多Object3D對(duì)象。比如一輛行駛的汽車(chē)是一個(gè)Object3D對(duì)象,控制汽車(chē)行駛路線的邏輯在該對(duì)象內(nèi)部實(shí)現(xiàn),汽車(chē)的每個(gè)頂點(diǎn)經(jīng)過(guò)模型矩陣的處理后,都位于正確的位置;但是汽車(chē)擺動(dòng)的雨刮器,其不但隨著汽車(chē)行駛方向運(yùn)動(dòng),而且自身相對(duì)汽車(chē)也在左右擺動(dòng),這個(gè)擺動(dòng)的邏輯無(wú)法在汽車(chē)這個(gè)對(duì)象內(nèi)部的實(shí)現(xiàn)。解決的方法是,將雨刮器設(shè)定為汽車(chē)的chidren,雨刮器內(nèi)部的邏輯只負(fù)責(zé)其相對(duì)于汽車(chē)的擺動(dòng)。在這種樹(shù)狀結(jié)構(gòu)下,一個(gè)場(chǎng)景Scene實(shí)際上就是最頂端的Object3D,它的模型矩陣就是視圖矩陣(取決于相機(jī))的逆矩陣。

屬性matrix和matrixWorld就很好理解了,matrix表示本地的模型矩陣,僅僅表示該對(duì)象的運(yùn)動(dòng),而matrixWorld則需要依次向父親節(jié)點(diǎn)迭代,每一次迭代都左乘父親對(duì)象的本地模型矩陣,直到Scene對(duì)象——當(dāng)然,實(shí)際上是左乘父親對(duì)象的全局模型矩陣。

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

可以看到,關(guān)于該Object3D對(duì)象最重要的“變換狀態(tài)”信息實(shí)際上是存儲(chǔ)在兩個(gè)“備份”中的,一個(gè)是matrix對(duì)象,還有一個(gè)是position等屬性,兩部分應(yīng)當(dāng)保持一致,如果通過(guò)某種方法改變了一個(gè)備份,則另一個(gè)備份也應(yīng)該在適當(dāng)?shù)臅r(shí)候更新。還有一些其他屬性從字面和類(lèi)型上就能看出其含義,不再單獨(dú)列出了。下面說(shuō)函數(shù):
函數(shù)applyMatrix(matrix)將參數(shù)matrix左乘到this.matrix上,實(shí)際上就是對(duì)該Object3D對(duì)象實(shí)行某個(gè)變換(該變換可能要經(jīng)過(guò)好幾步基本變換,但是已經(jīng)存儲(chǔ)在參數(shù)matrix里面了)。注意,在對(duì)this.matrix執(zhí)行完左乘之后,;立刻更新了position等參數(shù)的值。比起下面幾個(gè)變換函數(shù),該函數(shù)更“高級(jí)”,允許開(kāi)發(fā)者自由指定變換矩陣,而不是說(shuō)“朝著x軸前進(jìn)5單位距離”。
復(fù)制代碼 代碼如下:

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

函數(shù)translate(distance, axis)令該對(duì)象向axis軸指定的方向前進(jìn)distance距離。函數(shù)translateX(distance),translateY(distance),translateZ(distance)令其向X,Y,Z軸前進(jìn)distance距離。注意這些函數(shù)僅僅改變了position對(duì)象的值,而不曾改變matrix的值。
復(fù)制代碼 代碼如下:

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

函數(shù)localToWorld(vector)將本地坐標(biāo)轉(zhuǎn)化為世界坐標(biāo)中,函數(shù)worldToLocal則正好相反。注意這里的vector本地坐標(biāo)指的是未變換之前的坐標(biāo),也就是說(shuō)雨刮器的默認(rèn)位置的頂點(diǎn)坐標(biāo)。

函數(shù)lookAt(eye,center,up)執(zhí)行其matrix屬性對(duì)象的lookAt函數(shù)(之前介紹過(guò),matrix4對(duì)象也有一個(gè)lookAt函數(shù)),一般用于相機(jī)對(duì)象。該函數(shù)僅僅改變了旋轉(zhuǎn)狀態(tài),所以當(dāng)matrix屬性對(duì)象執(zhí)行完之后,如果屬性rotationAutoUpdate為真,則會(huì)更新rotation或quaternion的值,更新哪一個(gè)取決于屬性u(píng)seQuation。
函數(shù)add(object)和函數(shù)remove(object)從當(dāng)前Object3D對(duì)象中添加一個(gè)子對(duì)象,或刪除一個(gè)子對(duì)象,了解到場(chǎng)景中的眾多Object3D對(duì)象是用樹(shù)來(lái)管理的,這就很容易理解了。

函數(shù)traverse(callback)遍歷調(diào)用者和調(diào)用者的所有后代,callback參數(shù)是一個(gè)函數(shù),被調(diào)用者和每一個(gè)后代對(duì)象調(diào)用callback(this)。
復(fù)制代碼 代碼如下:

traverse: function ( callback ) {
callback( this );
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
this.children[ i ].traverse( callback );
}
},

函數(shù)getChildByName(name,recursive)通過(guò)字符串在調(diào)用者的子元素(recursive為false)或后代元素(recursive為true)中查詢(xún)屬性name符合的對(duì)象返回。

函數(shù)getDescendants(array)將調(diào)用者的所有后代對(duì)象全部push到數(shù)組array中。
函數(shù)updateMatrix()和updateMatrixWorld(force)將根據(jù)position,rotation或quaternion,scale參數(shù)更新matrix和matrixWorld。updateMatrixWorld還會(huì)更新所有后代元素的matrixWorld,如果force值為真或者調(diào)用者本身的matrixWorldNeedsUpdate值為真。在函數(shù)applyMatrix(matrix)中,改變了matrix值后立刻就更新了position,rotation等屬性,但在函數(shù)translate(distance,axis)中改變了position等變量(或者直接改變position等屬性)后并沒(méi)有立刻更新matrix值,這時(shí)應(yīng)該手動(dòng)調(diào)用updateMatrix()。這些細(xì)節(jié)值得注意,你也許會(huì)認(rèn)為應(yīng)該加入事件監(jiān)聽(tīng),一旦一個(gè)值發(fā)生變化,其他所有的都會(huì)立刻更新,但我想在,可能是出于這方面的考慮:適當(dāng)?shù)臅r(shí)候更新會(huì)帶來(lái)更高的效率——比如可能會(huì)頻繁地改變r(jià)otation值,但是僅僅在使用matrix屬性之前,才對(duì)其進(jìn)行更新。
復(fù)制代碼 代碼如下:

updateMatrix: function () {
this.matrix.setPosition( this.position );
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 ) this.updateMatrix();
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 < l; i ++ ) {
this.children[ i ].updateMatrixWorld( force );
}
},

函數(shù)deallocate手動(dòng)將調(diào)用者占用的空間釋放掉,當(dāng)不再需要該對(duì)象時(shí)這樣做。
Core::Projectors
管理投影矩陣的類(lèi),代碼太復(fù)雜了,我猜會(huì)涉及到render類(lèi)里的操作,等到適當(dāng)?shù)臅r(shí)候再看吧。
Core::UV
該構(gòu)造函數(shù)產(chǎn)生一個(gè)材質(zhì)坐標(biāo)類(lèi)——就是材質(zhì)上的坐標(biāo),往往與頂點(diǎn)對(duì)應(yīng)起來(lái),光柵化后每個(gè)像素都有一個(gè)材質(zhì)坐標(biāo),再?gòu)牟馁|(zhì)上“取色”以實(shí)現(xiàn)紋理。
復(fù)制代碼 代碼如下:

THREE.UV = function ( u, v ) {
this.u = u || 0;
this.v = v || 0;
};

材質(zhì)坐標(biāo)類(lèi)就是一個(gè)簡(jiǎn)化的vector2類(lèi),除了屬性名稱(chēng)不同而已。
Core::Ray Core::Rectangle Core:Spline
射線類(lèi),有原點(diǎn)、方向、遠(yuǎn)近截?cái)帱c(diǎn)。在點(diǎn)光源中應(yīng)該有應(yīng)用。矩形類(lèi)、曲線類(lèi),相對(duì)都比較簡(jiǎn)單,也不那么“核心”,以后再看吧。
Core::Geometry
Geometry類(lèi)也是非常重要的一類(lèi),表示一個(gè)由頂點(diǎn)和表面構(gòu)成的幾何形體。
復(fù)制代碼 代碼如下:

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 = false;
this.elementsNeedUpdate = false;
this.uvsNeedUpdate = false;
this.normalsNeedUpdate = false;
this.tangentsNeedUpdate = false;
this.colorsNeedUpdate = false;
this.lineDistancesNeedUpdate = false;
this.buffersNeedUpdate = false;
};

以下兩組屬性最重要
屬性vertics是一個(gè)數(shù)組,每個(gè)元素是vector3類(lèi)型的對(duì)象,表示一個(gè)頂點(diǎn)坐標(biāo)。屬性colors和normals表示和頂點(diǎn)對(duì)應(yīng)的顏色值和發(fā)現(xiàn)向量,只有在很少的情況下才使用,大部分情況下,頂點(diǎn)的顏色和發(fā)現(xiàn)時(shí)在“表面”中定義的——如果立方體的6面顏色各不相同,則每個(gè)頂點(diǎn)實(shí)在不同的面上是不同的顏色。

屬性faces是一個(gè)數(shù)組,每個(gè)元素是face4或face3類(lèi)型的對(duì)象,之前介紹face3的時(shí)候說(shuō)到,face中存儲(chǔ)的僅僅是頂點(diǎn)的索引值,通過(guò)索引值就可以在數(shù)組vertices中取到頂點(diǎn)的坐標(biāo)值。

下面說(shuō)函數(shù)
applyMatrix(matrix)函數(shù)更新geometry中的所有頂點(diǎn)坐標(biāo)和表面的法線向量,所做的實(shí)際上是用變換矩陣matrix對(duì)geometry形體進(jìn)行空間變換。normalMatrix是參數(shù)matrix左上角3×3矩陣的逆轉(zhuǎn)置矩陣,該矩陣用來(lái)旋轉(zhuǎn)矢量(法線,而不是頂點(diǎn)坐標(biāo))。
復(fù)制代碼 代碼如下:

applyMatrix: function ( matrix ) {
var normalMatrix = new THREE.Matrix3();
normalMatrix.getInverse( matrix ).transpose();
for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
var vertex = this.vertices[ i ];
matrix.multiplyVector3( vertex );
}
for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
var face = this.faces[ i ];
normalMatrix.multiplyVector3( face.normal ).normalize();
for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
normalMatrix.multiplyVector3( face.vertexNormals[ j ] ).normalize();
}
matrix.multiplyVector3( face.centroid );
}
},

函數(shù)ComputeCentroid()計(jì)算幾何形體中每個(gè)表面的重心(不是幾何形體自己的重心)。這個(gè)函數(shù)似乎應(yīng)當(dāng)放到face類(lèi)的原型上會(huì)更好,但是由于face類(lèi)內(nèi)部無(wú)法獲取點(diǎn)的坐標(biāo)(除非再將點(diǎn)坐標(biāo)數(shù)組的引用作為參數(shù)傳入構(gòu)造函數(shù),這樣代價(jià)就大了)而僅僅是索引值,所以只好在geometry類(lèi)的原型上定義了。下面幾個(gè)函數(shù)都是類(lèi)似的情況(事實(shí)上,face類(lèi)幾乎沒(méi)有什么成員函數(shù))。

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

函數(shù)createMorphNormal為每一個(gè)morph創(chuàng)建法線。morph應(yīng)該是用作顯示固定連續(xù)動(dòng)畫(huà)的變形效果。
函數(shù)mergeVertics將坐標(biāo)值相同的點(diǎn)剔除,同時(shí)更新face對(duì)象中的點(diǎn)索引值。
Core::Quaternian
四維數(shù)旋轉(zhuǎn)類(lèi)用另一種方式表達(dá)一個(gè)旋轉(zhuǎn)變換,相比用rotation,可以避免萬(wàn)向節(jié)死鎖問(wèn)題。
復(fù)制代碼 代碼如下:

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

如果不談函數(shù),Quaternian就是一個(gè)簡(jiǎn)單的vector4類(lèi)型對(duì)象。
函數(shù)setFromEuler(v,order)通過(guò)一次歐拉旋轉(zhuǎn)設(shè)置四維數(shù)旋轉(zhuǎn)。
函數(shù)setFromAxis(axis,angle)通過(guò)繞任意軸旋轉(zhuǎn)設(shè)定四維數(shù)旋轉(zhuǎn)。
函數(shù)setFromRotationMatrix(matrix)通過(guò)旋轉(zhuǎn)矩陣設(shè)置四維數(shù)旋轉(zhuǎn)。
還有一些和vector4類(lèi)相同的函數(shù)這里就不列了。

相關(guān)文章

  • javascript的基礎(chǔ)交互詳解

    javascript的基礎(chǔ)交互詳解

    這篇文章主要介紹了javascript的基礎(chǔ)交互詳解,文章通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • JavaScript中的acos()方法使用詳解

    JavaScript中的acos()方法使用詳解

    這篇文章主要介紹了JavaScript中的acos()方法使用詳解,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-06-06
  • JavaScript中的正則表達(dá)式簡(jiǎn)明總結(jié)

    JavaScript中的正則表達(dá)式簡(jiǎn)明總結(jié)

    這篇文章主要介紹了JavaScript中的正則表達(dá)式,簡(jiǎn)明總結(jié)了正則中的語(yǔ)法含義和RegExp對(duì)象,需要的朋友可以參考下
    2014-04-04
  • 淺談JavaScript函數(shù)節(jié)流

    淺談JavaScript函數(shù)節(jié)流

    這篇文章主要簡(jiǎn)單介紹了JavaScript函數(shù)節(jié)流的相關(guān)知識(shí),有相同需求的小伙伴們可以仔細(xì)閱讀下
    2014-12-12
  • JavaScript函數(shù)、閉包、原型、面向?qū)ο髮W(xué)習(xí)筆記

    JavaScript函數(shù)、閉包、原型、面向?qū)ο髮W(xué)習(xí)筆記

    這篇文章給大家分享了一篇關(guān)于JavaScript函數(shù)、閉包、原型、面向?qū)ο蟮闹R(shí)點(diǎn)學(xué)習(xí)筆記內(nèi)容,有興趣的朋友參考下。
    2018-09-09
  • Javascript事件實(shí)例詳解

    Javascript事件實(shí)例詳解

    本文實(shí)例當(dāng)你單擊頁(yè)面上的任何位置都會(huì)彈出“a”,正是運(yùn)用了document的特性
    2013-11-11
  • JavaScript 操作宏任務(wù)與微任務(wù)

    JavaScript 操作宏任務(wù)與微任務(wù)

    這篇文章主要介紹了JavaScript 操作宏任務(wù)與微任務(wù),簡(jiǎn)要說(shuō)明了有關(guān)定時(shí)器和具體的代碼實(shí)現(xiàn),希望對(duì)你有所幫助
    2021-06-06
  • 全面理解閉包機(jī)制

    全面理解閉包機(jī)制

    下面小編就為大家?guī)?lái)一篇全面理解閉包機(jī)制。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-07-07
  • JavaScript 中的事件教程

    JavaScript 中的事件教程

    JavaScript 中的事件教程...
    2007-04-04
  • 詳解JavaScript中shift()方法的使用

    詳解JavaScript中shift()方法的使用

    這篇文章主要介紹了詳解JavaScript中shift()方法的使用,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-06-06

最新評(píng)論