亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Three.js源碼閱讀筆記(物體是如何組織的)

 更新時(shí)間:2012年12月27日 16:35:39   作者:  
這一篇將主要討論Three.js中的物體是如何組織的:即如何將頂點(diǎn)、表面、材質(zhì)組合成為一個(gè)具體的對(duì)象,需要了解的朋友可以參考下
這是Three.js源碼閱讀筆記第三篇。之前兩篇主要是關(guān)于核心對(duì)象的,這些核心對(duì)象主要圍繞著矢量vector3對(duì)象和矩陣matrix4對(duì)象展開(kāi)的,關(guān)注的是空間中的單個(gè)頂點(diǎn)的位置和變化。這一篇將主要討論Three.js中的物體是如何組織的:即如何將頂點(diǎn)、表面、材質(zhì)組合成為一個(gè)具體的對(duì)象。
Object::Mesh
該構(gòu)造函數(shù)構(gòu)造了一個(gè)空間中的物體。之所以叫“網(wǎng)格”是因?yàn)椋瑢?shí)際上具有體積的物體基本都是建模成為“網(wǎng)格”的。
復(fù)制代碼 代碼如下:

THREE.Mesh = function ( geometry, material ) {
THREE.Object3D.call( this );
this.geometry = geometry;
this.material = ( material !== undefined ) ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe: true } );
/* 一些其他的與本節(jié)無(wú)關(guān)的內(nèi)容 */
}

實(shí)際上,Mesh類只有兩個(gè)屬性,表示幾何形體的geometry對(duì)象和表示材質(zhì)的material對(duì)象。geometry對(duì)象在上一篇博文中已經(jīng)介紹過(guò),還有部分派生類會(huì)在這篇博文中介紹(通過(guò)這些派生類的構(gòu)造過(guò)程,能更加清晰地了解到Mesh對(duì)象的工作原理);matrial對(duì)象及其派生類也將在這篇筆記中介紹。Mesh對(duì)象的這兩個(gè)屬性相互緊密關(guān)聯(lián),geometry對(duì)象中的face數(shù)組中,每個(gè)face對(duì)象的materialIndex用來(lái)匹配material屬性對(duì)象,face對(duì)象的vertexUVs數(shù)組用以依次匹配每個(gè)頂點(diǎn)在數(shù)組上的取值。值得注意的是,Mesh只能有一個(gè)material對(duì)象(不知這樣設(shè)計(jì)的意圖何在),如果需要用到多個(gè)材質(zhì),應(yīng)當(dāng)將材質(zhì)按照materialIndex順序初始化在geometry本身的materials屬性中。
Geometry::CubeGeometry
該構(gòu)造函數(shù)創(chuàng)建了一個(gè)立方體對(duì)象。
復(fù)制代碼 代碼如下:

THREE.CubeGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
THREE.Geometry.call( this );
var scope = this;
this.width = width;
this.height = height;
this.depth = depth;
var width_half = this.width / 2;
var height_half = this.height / 2;
var depth_half = this.depth / 2;
/* 略去 */
buildPlane( 'z', 'y', - 1, - 1, this.depth, this.height, width_half, 0 ); // px
/* 略去 */
function buildPlane( u, v, udir, vdir, width, height, depth, materialIndex ) {
/* 略去 */
}
this.computeCentroids();
this.mergeVertices();
};

構(gòu)造函數(shù)做的最重要的事在buildPlane中。該函數(shù)最重要的事情就是對(duì)scope的操作(上面的代碼塊中,scope就是this),包括:調(diào)用scope.vertices.push(vector)將頂點(diǎn)加入geometry對(duì)象;調(diào)用scope.faces.push(face)將表面加入到geometry對(duì)象,調(diào)用scope.faceVertexUvs[i].push(uv)方法將對(duì)應(yīng)于頂點(diǎn)的材質(zhì)坐標(biāo)加入geometry對(duì)象。代碼的大部分都是關(guān)于生成立方體的邏輯,這些邏輯很容易理解,也很容易擴(kuò)展到其他類型的geometry對(duì)象。

構(gòu)造函數(shù)的參數(shù)包括長(zhǎng)、寬、高和三個(gè)方向的分段數(shù)。所謂分段,就是說(shuō)如果將widthSeqments等三個(gè)參數(shù)都設(shè)定為2的話,那么每個(gè)面將被表現(xiàn)成2×2=4個(gè)面,整個(gè)立方體由24個(gè)表面組成,正如同網(wǎng)格一樣。
復(fù)制代碼 代碼如下:

function buildPlane( u, v, udir, vdir, width, height, depth, materialIndex ) {
var w, ix, iy,
gridX = scope.widthSegments,
gridY = scope.heightSegments,
width_half = width / 2,
height_half = height / 2,
offset = scope.vertices.length;
if ( ( u === 'x' && v === 'y' ) || ( u === 'y' && v === 'x' ) ) {w = 'z';}
else if ( ( u === 'x' && v === 'z' ) || ( u === 'z' && v === 'x' ) ) {w = 'y';gridY = scope.depthSegments;} else if ( ( u === 'z' && v === 'y' ) || ( u === 'y' && v === 'z' ) ) {w = 'x';gridX = scope.depthSegments;}
var gridX1 = gridX + 1,
gridY1 = gridY + 1,
segment_width = width / gridX,
segment_height = height / gridY,
normal = new THREE.Vector3();
normal[ w ] = depth > 0 ? 1 : - 1;
for ( iy = 0; iy < gridY1; iy ++ ) {
for ( ix = 0; ix < gridX1; ix ++ ) {
var vector = new THREE.Vector3();
vector[ u ] = ( ix * segment_width - width_half ) * udir;
vector[ v ] = ( iy * segment_height - height_half ) * vdir;
vector[ w ] = depth;
scope.vertices.push( vector );
}
}
for ( iy = 0; iy < gridY; iy++ ) {
for ( ix = 0; ix < gridX; ix++ ) {
var a = ix + gridX1 * iy;
var b = ix + gridX1 * ( iy + 1 );
var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
var d = ( ix + 1 ) + gridX1 * iy;
var face = new THREE.Face4( a + offset, b + offset, c + offset, d + offset );
face.normal.copy( normal );
face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );
face.materialIndex = materialIndex;
scope.faces.push( face );
scope.faceVertexUvs[ 0 ].push( [
new THREE.UV( ix / gridX, 1 - iy / gridY ),
new THREE.UV( ix / gridX, 1 - ( iy + 1 ) / gridY ),
new THREE.UV( ( ix + 1 ) / gridX, 1- ( iy + 1 ) / gridY ),
new THREE.UV( ( ix + 1 ) / gridX, 1 - iy / gridY )
] );
}
}
}

除了一個(gè)大部分對(duì)象都具有的clone()方法,CubeGeometry沒(méi)有其他的方法,其他的XXXGeometry對(duì)象也大抵如此。沒(méi)有方法說(shuō)明該對(duì)象負(fù)責(zé)組織和存儲(chǔ)數(shù)據(jù),而如何利用這些數(shù)據(jù)生成三維場(chǎng)景和動(dòng)畫(huà),則是在另外的對(duì)象中定義的。
Geometry::CylinderGeometry
顧名思義,該構(gòu)造函數(shù)創(chuàng)建一個(gè)圓柱體(或圓臺(tái))對(duì)象。
復(fù)制代碼 代碼如下:

THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded ) {
/* 略 */
}

有了CubeGeometry構(gòu)造函數(shù)的基礎(chǔ),自己也應(yīng)當(dāng)能夠?qū)崿F(xiàn)CylinderGeometry,我們只需要注意一下構(gòu)造函數(shù)各參數(shù)的意義。radiusTop和radiusBottom表示頂部和底部的半徑,height表示高度。radiusSegments定義了需要將圓周分成多少份(該數(shù)字越大,圓柱更圓),heightSegments定義了需要將整個(gè)高度分成多少份,openEnded指定是否生成頂面和底面。

源碼中還有兩點(diǎn)值得注意的:該模型的本地原點(diǎn)是中軸線的中點(diǎn),而不是重心之類的,也就是說(shuō)上圓面的高度(y軸值)是height/2,下圓面是-height/2,這一點(diǎn)對(duì)圓柱體來(lái)說(shuō)沒(méi)有差異,但對(duì)于上下半徑不同的圓臺(tái)體就有差異了;還有就是該模型的頂面和地面采用face3類型表面,而側(cè)面采用face4類型表面。
Geometry::SphereGeometry
該構(gòu)造函數(shù)創(chuàng)建一個(gè)球體。
復(fù)制代碼 代碼如下:

THREE.SphereGeometry = function ( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ){
/* 略 */
}

各參數(shù)的意義:radius指定半徑,widthSegments表示“經(jīng)度”分帶數(shù)目,heightSegments表示“緯度”分帶數(shù)目。后面四個(gè)參數(shù)是可選的,表示經(jīng)度的起始值和緯度的起始值。熟悉極坐標(biāo)的都了解,通常用希臘字母φ(phi)表示緯圈角度(經(jīng)度),而用θ(theta)表示經(jīng)圈角度(緯度)。這四個(gè)數(shù)的默認(rèn)值分別為0,2π,0,π,通過(guò)改變他們的值,可以創(chuàng)造出殘缺的球面(但是邊緣必須整齊)。

源碼中,除了北極和南極的極圈內(nèi)的區(qū)域是用face3類型表面,其他部位都是用的face4型表面。本地原點(diǎn)為球心。
Geometry::PlaneGeometry
該構(gòu)造函數(shù)創(chuàng)建一個(gè)平面。
復(fù)制代碼 代碼如下:

THREE.PlaneGeometry = function ( width, height, widthSegments, heightSegments ){
/* 略 */
}

各參數(shù)意義:依次為寬度、高度、寬度分段數(shù)、高度分段數(shù)。想必讀者對(duì)這種構(gòu)造“格網(wǎng)”的方式應(yīng)該很熟悉了吧。
源碼中得到一些其他信息:平面被構(gòu)造在x-y平面上,原點(diǎn)即矩形中心點(diǎn)。
Geometry::ExtrudeGeometry
該對(duì)象現(xiàn)在是構(gòu)造一般幾何形體的方法,但是通常我們是將建模好的對(duì)象存儲(chǔ)在某種格式的文件中,并通過(guò)loader加載進(jìn)來(lái),所以似乎鮮有直接用到該函數(shù)的機(jī)會(huì)。而且這個(gè)函數(shù)看上去還是半成品,很多設(shè)定一股腦地堆在options對(duì)象里,我也沒(méi)有仔細(xì)研究。
Material::Material
Material對(duì)象是所有其他種類Material的原型對(duì)象。
復(fù)制代碼 代碼如下:

THREE.Material = function () {
THREE.MaterialLibrary.push( this );
this.id = THREE.MaterialIdCount ++;
this.name = '';
this.side = THREE.FrontSide;
this.opacity = 1;
this.transparent = false;
this.blending = THREE.NormalBlending;
this.blendSrc = THREE.SrcAlphaFactor;
this.blendDst = THREE.OneMinusSrcAlphaFactor;
this.blendEquation = THREE.AddEquation;
this.depthTest = true;
this.depthWrite = true;
this.polygonOffset = false;
this.polygonOffsetFactor = 0;
this.polygonOffsetUnits = 0;
this.alphaTest = 0;
this.overdraw = false; // Boolean for fixing antialiasing gaps in CanvasRenderer
this.visible = true;
this.needsUpdate = true;
};

先看一些較為重要的屬性:
屬性opacity為一個(gè)0-1區(qū)間的值,表明透明度。屬性transparent指定是否使用透明,只有在該值為真的時(shí)候,才會(huì)將其與混合(透明是渲染像素時(shí),待渲染值與已存在值共同作用計(jì)算出渲染后像素值,達(dá)到混合的效果)。

屬性blending,blendSrc,blendDst,blendEquation指定了混合方式和混合源Src和混合像素已有的像元值Dst的權(quán)重指定方式。默認(rèn)情況下(如構(gòu)造函數(shù)中賦的缺省值),新的像元值等于:新值×alpha+舊值×(1-alpha)。

我曾困惑為何Material類中沒(méi)有最重要的對(duì)象,表示紋理圖片的屬性。后來(lái)我理解了,其實(shí)材質(zhì)和紋理還是有區(qū)別的,只能說(shuō)某種材質(zhì)有紋理的,但也有材質(zhì)是沒(méi)有紋理的。材質(zhì)影響的是整個(gè)形體的渲染效果,比如:“對(duì)一根線渲染為5px寬,兩端點(diǎn)為方塊,不透明的紅色”這段描述就可以認(rèn)為是材質(zhì),而沒(méi)有涉及任何紋理。

和眾多Geometry對(duì)象一樣,Material對(duì)象除了通用的clone(),dellocate()和setValues()方法,沒(méi)有其他方法。以下是兩種最基本的材質(zhì)對(duì)象。
Material::LineBasicMaterial
該構(gòu)造函數(shù)創(chuàng)建用于渲染線狀形體的材質(zhì)。
復(fù)制代碼 代碼如下:

THREE.LineBasicMaterial = function ( parameters ) {
THREE.Material.call( this );
this.color = new THREE.Color( 0xffffff );
this.linewidth = 1;
this.linecap = 'round';
this.linejoin = 'round';
this.vertexColors = false;
this.fog = true;
this.setValues( parameters );
};

屬性color和linewidth顧名思義,指線的顏色和線的寬度(線沒(méi)有寬度,這里的寬度是用來(lái)渲染的)。
屬性linecap和linejoin指定線條端點(diǎn)和連接點(diǎn)的樣式。
屬性fog指定該種材質(zhì)是否收到霧的影響。
Material::MeshBasicMaterial
該構(gòu)造函數(shù)創(chuàng)建用于渲染Mesh表面的材質(zhì)。
復(fù)制代碼 代碼如下:

THREE.MeshBasicMaterial = function ( parameters ) {
THREE.Material.call( this );
this.color = new THREE.Color( 0xffffff ); // emissive
this.map = null;
this.lightMap = null;
this.specularMap = null;
this.envMap = null;
this.combine = THREE.MultiplyOperation;
this.reflectivity = 1;
this.refractionRatio = 0.98;
this.fog = true;
this.shading = THREE.SmoothShading;
this.wireframe = false;
this.wireframeLinewidth = 1;
this.wireframeLinecap = 'round';
this.wireframeLinejoin = 'round';
this.vertexColors = THREE.NoColors;
this.skinning = false;
this.morphTargets = false;
this.setValues( parameters );
};

這里出現(xiàn)了最重要的紋理屬性,包括map,lightMap和specularMap,他們都是texture類型的對(duì)象。
屬性wireframe指定表面的邊界線是否渲染,如果渲染,后面的若干以wireframe開(kāi)頭的屬性表示如果渲染邊界線,將如何渲染。
Texture::Texture
該構(gòu)造函數(shù)用來(lái)創(chuàng)建紋理對(duì)象。
復(fù)制代碼 代碼如下:

THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
THREE.TextureLibrary.push( this );
this.id = THREE.TextureIdCount ++;
this.name = '';
this.image = image;
this.mapping = mapping !== undefined ? mapping : new THREE.UVMapping();
this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
this.format = format !== undefined ? format : THREE.RGBAFormat;
this.type = type !== undefined ? type : THREE.UnsignedByteType;
this.offset = new THREE.Vector2( 0, 0 );
this.repeat = new THREE.Vector2( 1, 1 );
this.generateMipmaps = true;
this.premultiplyAlpha = false;
this.flipY = true;
this.needsUpdate = false;
this.onUpdate = null;
};

最重要的屬性是image,這是一個(gè)JavaScript Image類型對(duì)象。傳入的第一個(gè)參數(shù)就是該對(duì)象,如何創(chuàng)建該對(duì)象在后面說(shuō)。

后面的對(duì)象都是可選的,如果缺省就會(huì)填充默認(rèn)值,而且往往都是填充默認(rèn)值。
屬性magFileter和minFileter指定紋理在放大和縮小時(shí)的過(guò)濾方式:最臨近點(diǎn)、雙線性內(nèi)插等。
從url中生成一個(gè)texture,需要調(diào)用Three.ImageUtils.loadTexture(paras),該函數(shù)返回一個(gè)texture類型對(duì)象。在函數(shù)內(nèi)部又調(diào)用了THREE.ImageLoader.load(paras)函數(shù),這個(gè)函數(shù)內(nèi)部又調(diào)用了THREE.Texture()構(gòu)造函數(shù),生成紋理。

相關(guān)文章

  • 微信小程序開(kāi)發(fā)之入門實(shí)例教程篇

    微信小程序開(kāi)發(fā)之入門實(shí)例教程篇

    2016年推出微信小程序,時(shí)至今日,歷經(jīng)幾個(gè)版本的更新,已形成了相對(duì)實(shí)用和穩(wěn)定的服務(wù)平臺(tái)。本文簡(jiǎn)單的介紹了微信小程序的入門用法,今后會(huì)繼續(xù)關(guān)注和實(shí)踐。需要的朋友可以參考學(xué)習(xí),下面來(lái)一起看看吧。
    2017-03-03
  • 使用Math.floor與Math.random取隨機(jī)整數(shù)的方法詳解

    使用Math.floor與Math.random取隨機(jī)整數(shù)的方法詳解

    本篇文章對(duì)使用Math.floor與Math.random取隨機(jī)整數(shù)的方法進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • 深入學(xué)習(xí)JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值

    深入學(xué)習(xí)JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值

    這篇文章主要介紹了深入學(xué)習(xí)JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值,是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-07-07
  • Javascript基礎(chǔ)教程之?dāng)?shù)組 array

    Javascript基礎(chǔ)教程之?dāng)?shù)組 array

    Array是JavaScript中常用的類型,并且JavaScript中的數(shù)組和其他語(yǔ)言的數(shù)組有比較大的區(qū)別。JavaScript中數(shù)組中存放的數(shù)據(jù)類型不一定相同,而且數(shù)組的長(zhǎng)度也是可改變的。
    2015-01-01
  • 淺談js中的bind

    淺談js中的bind

    這篇文章主要介紹了js中的bind應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • utf8的編碼算法 轉(zhuǎn)載

    utf8的編碼算法 轉(zhuǎn)載

    utf8的編碼算法 轉(zhuǎn)載...
    2006-12-12
  • Javascript中的幾種繼承方式對(duì)比分析

    Javascript中的幾種繼承方式對(duì)比分析

    下面小編就為大家?guī)?lái)一篇Javascript中的幾種繼承方式對(duì)比分析。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,希望能給大家一個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-03-03
  • 第一個(gè)JavaScript入門基礎(chǔ) document.write輸出

    第一個(gè)JavaScript入門基礎(chǔ) document.write輸出

    關(guān)于JavaScript,他是一個(gè)OOSP(面向?qū)ο竽_本語(yǔ)言)他是用來(lái)創(chuàng)建動(dòng)態(tài)網(wǎng)站,增強(qiáng)用戶界面的一門技術(shù)。如果你想了解更多關(guān)于JavaScript的信息,請(qǐng)去維基百科查詢。
    2010-02-02
  • JavaScript中的關(guān)聯(lián)數(shù)組問(wèn)題

    JavaScript中的關(guān)聯(lián)數(shù)組問(wèn)題

    這篇文章主要介紹了JavaScript中的關(guān)聯(lián)數(shù)組問(wèn)題的相關(guān)資料,需要的朋友可以參考下
    2015-03-03
  • 獲取body標(biāo)簽的兩種方法

    獲取body標(biāo)簽的兩種方法

    獲取body標(biāo)簽的兩種方法,有時(shí)候需要?jiǎng)討B(tài)的在body中添加內(nèi)容用得到。
    2011-10-10

最新評(píng)論