10 Loaders加載模型到Three.js

2018-10-08 17:19:08?專注前端30年?閱讀數(shù) 3049更多

分類(lèi)專欄:?達(dá)人課?three.js 基礎(chǔ)入門(mén)

版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/qq_30100043/article/details/80979604

現(xiàn)在市面上的3D模型有上百種,每一種的格式都有不同的用途,不同的功能和復(fù)雜程度。盡管Three.js提供了很多的加載器,但選擇正確的格式和工作流程將在以后節(jié)省時(shí)間和成本。而且某些格式難以使用,效率低下或者目前還未完全支持。

推薦使用的模型格式

官方推薦我們使用的3D模型的格式為glTF,由于glTF專注于傳輸,因此它的傳輸和解析的速度都很快。glTF模型功能包括:網(wǎng)格,材質(zhì),紋理,蒙皮,骨骼,變形動(dòng)畫(huà),骨骼動(dòng)畫(huà),燈光以及相機(jī)。

如果當(dāng)前的首選不是glTF格式,那么推薦Three.js定期維護(hù)并且流行的格式FBX,OBJ或者COLLADA格式,Three.js也有自己獨(dú)有的JSON格式。我們接下來(lái)將介紹這五種格式:

Three.js的JSON格式

這里的JSON格式指的是Three.js可以將其轉(zhuǎn)換為場(chǎng)景的3D對(duì)象的JSON格式模型。這種格式內(nèi)部一般必有的四項(xiàng)為:

metadata?當(dāng)前模型的相關(guān)信息以及生成的工具信息

geometries?存儲(chǔ)當(dāng)前模型所使用的幾何體的數(shù)組

materials?存儲(chǔ)當(dāng)前模型所使用的材質(zhì)的數(shù)組

object?當(dāng)前模型的結(jié)構(gòu)以及標(biāo)示所應(yīng)用到的材質(zhì)和幾何體標(biāo)示

所有的模型網(wǎng)格,幾何體和材質(zhì)都有一個(gè)固定的uuid標(biāo)識(shí)符,JSON格式中都是通過(guò)uuid作為引用。

3d對(duì)象轉(zhuǎn)成JSON

所有的THREE.Object3D對(duì)象都可以轉(zhuǎn)成JSON字符串保存成為文件,我們不能直接將對(duì)象轉(zhuǎn)成JSON是因?yàn)镴SON是無(wú)法保存函數(shù)的,所以,Three.js給我們提供了一個(gè)toJSON()的方法來(lái)讓我們轉(zhuǎn)換為可存儲(chǔ)的JSON格式。

var obj = scene.toJSON(); //將整個(gè)場(chǎng)景的內(nèi)容轉(zhuǎn)換成為json對(duì)象

var obj = group.toJSON(); //將一個(gè)模型組轉(zhuǎn)成json對(duì)象

var obj = mesh.toJSON(); //將一個(gè)模型網(wǎng)格轉(zhuǎn)成json對(duì)象

var JSONStr = JSON.stringify(obj); //將json對(duì)象轉(zhuǎn)換成json字符串

1

2

3

4

按照這種方式,我們就可以將生成的場(chǎng)景模型保存為文件。

使用ObjectLoader加載JSON模型

既然我們能夠?qū)耄隙ň涂梢詫?dǎo)入。這里我們將使用到Three.js內(nèi)置的對(duì)象THREE.ObjectLoader來(lái)加載模型:

直接加載Three.js生成的JSON對(duì)象:

var obj = scene.toJSON(); //將整個(gè)場(chǎng)景的內(nèi)容轉(zhuǎn)換成為json對(duì)象

let loader = new THREE.ObjectLoader(); //實(shí)例化ObjectLoader對(duì)象

let scene = loader.parse(obj); //將json對(duì)象再轉(zhuǎn)換成3D對(duì)象

1

2

3

4

加載外部的JSON文件:

let loader = new THREE.ObjectLoader(); //實(shí)例化ObjectLoader對(duì)象

//加載模型,并在回調(diào)中將生成的模型對(duì)象添加到場(chǎng)景中

loader.load("../js/models/json/file.json", function (group) {

? ? scene.add(group);

});

1

2

3

4

5

6

案例地址:點(diǎn)擊這里

案例的右上角有四個(gè)點(diǎn)擊事件:

添加模型:將在場(chǎng)景內(nèi)隨機(jī)生成一組立方體,每次都不相同。

導(dǎo)出模型:將場(chǎng)景內(nèi)這一組立方體可以導(dǎo)出到本地json文件。

導(dǎo)入模型:可以將選擇的符合JSON文件解析并導(dǎo)入到場(chǎng)景內(nèi)。

加載模型:將加載服務(wù)器上面的一個(gè)JSON文件。

案例代碼地址:點(diǎn)擊這里

glTF格式文件導(dǎo)入

glTF格式的3D格式文件是官方推薦的使用的格式,這種格式的文件我們可以在sketchfab官網(wǎng)下載,這是一個(gè)國(guó)外比較知名的模型網(wǎng)站,下載地址是:點(diǎn)擊這里,我們可以在這里下載一些免費(fèi)的glTF格式的模型。

這里我在官網(wǎng)上隨便找了一個(gè)不錯(cuò)的模型做了一個(gè)案例:點(diǎn)擊這里

模型加載的速度會(huì)有些慢,大家可以等待一下便能夠看到這個(gè)小汽車(chē)。

接下來(lái)我們便講解一下加載glTF模型的流程:

首先,將GLTFLoader加載器插件引入到頁(yè)面,插件在官方包的地址/examples/js/loaders/,一些文件的導(dǎo)入插件都在這一個(gè)文件夾內(nèi),大家有興趣可以研究一下:

<script src="../js/loaders/GLTFLoader.js"></script>

1

然后創(chuàng)建一個(gè)加載器:

var loader = new THREE.GLTFLoader();

1

使用加載器去加載模型,并調(diào)節(jié)一下模型大小在場(chǎng)景內(nèi)展示:

loader.load('../js/models/gltf/scene.gltf', function (gltf) {

? ? gltf.scene.scale.set(.1,.1,.1);

? ? scene.add(gltf.scene);

});

1

2

3

4

我們需要有時(shí)候不明白的是,我加載了一個(gè)模型,哪一部分是需要導(dǎo)入場(chǎng)景的模型呢?

這里我們可以先將解析的出來(lái)的模型對(duì)象打印一下,然后通過(guò)查看對(duì)象屬性來(lái)了解到底是導(dǎo)入場(chǎng)景內(nèi)的對(duì)象,就比如glTF模型轉(zhuǎn)換出來(lái)的對(duì)象的scene屬性就是需要導(dǎo)入場(chǎng)景的對(duì)象,而JSON格式的模型是直接可以導(dǎo)入的對(duì)象。

模型加載案例源碼:點(diǎn)擊這里

FBX模型導(dǎo)入

FBX最大的用途是用在諸如在max、maya、softimage等軟件間進(jìn)行模型、材質(zhì)、動(dòng)作和攝影機(jī)信息的互導(dǎo),這樣就可以發(fā)揮max和maya等軟件的優(yōu)勢(shì)??梢哉f(shuō),F(xiàn)BX方案是最好的互導(dǎo)方案。

接下來(lái)我們看一下FBX模型導(dǎo)入的案例,這是我在網(wǎng)上隨便下載的一個(gè)FBX格式的模型,導(dǎo)入到場(chǎng)景內(nèi)的效果,案例查看地址:點(diǎn)擊這里

實(shí)現(xiàn)過(guò)程:

首先我們需要導(dǎo)入FBXLoader插件,并且還需要額外增加一個(gè)解析二進(jìn)制文件的插件inflate.min.js,不導(dǎo)入這個(gè)文件的話,除了一些字符串存儲(chǔ)的FBX格式,別的格式都會(huì)報(bào)錯(cuò):

<script src="../js/loaders/inflate.min.js"></script>

<script src="../js/loaders/FBXLoader.js"></script>

1

2

創(chuàng)建FBX加載器

var loader = new THREE.FBXLoader();

1

修改模型大小,并設(shè)置每個(gè)模型網(wǎng)格可以投射陰影:

loader.load('../js/models/fbx/file.fbx', function (fbx) {

? ? fbx.scale.set(.1,.1,.1);

? ? fbx.traverse(function (item) {

? ? ? if(item instanceof THREE.Mesh){

? ? ? ? ? item.castShadow = true;

? ? ? ? ? item.receiveShadow = true;

? ? ? }

? ? });

? ? scene.add(fbx);

});

1

2

3

4

5

6

7

8

9

10

這樣就實(shí)現(xiàn)了FBX模型的導(dǎo)入。

案例源碼地址:點(diǎn)擊這里

OBJ格式模型導(dǎo)入

OBJ文件是3D模型文件格式。由Alias|Wavefront公司為3D建模和動(dòng)畫(huà)軟件"Advanced Visualizer"開(kāi)發(fā)的一種標(biāo)準(zhǔn),適合用于3D軟件模型之間的互導(dǎo),也可以通過(guò)Maya讀寫(xiě)。

OBJ文件是一種文本文件,可以直接用寫(xiě)字板打開(kāi)進(jìn)行查看和編輯修改,但不包含動(dòng)畫(huà)、材質(zhì)特性、貼圖路徑、動(dòng)力學(xué)、粒子等信息。

OBJ文件的導(dǎo)出通常會(huì)和MTL格式一同導(dǎo)出,MTL作為OBJ文件的附屬文件,卻有著OBJ文件需要貼圖材質(zhì),所以,我們通常使用時(shí),將它們兩個(gè)文件一同導(dǎo)入。

這是我使用官網(wǎng)提供的一個(gè)模型制作的一個(gè)案例,查看地址:點(diǎn)擊這里

實(shí)現(xiàn)導(dǎo)入的過(guò)程:

首先,我們需要將OBJLoader插件和MTLLoader插件引入頁(yè)面:

<script src="../js/loaders/OBJLoader.js"></script>

<script src="../js/loaders/MTLLoader.js"></script>

1

2

實(shí)例化MTLLoader:

//創(chuàng)建MTL加載器

var mtlLoader = new THREE.MTLLoader();

//設(shè)置文件路徑

mtlLoader.setPath('../js/models/obj/');

1

2

3

4

如果有需要,我們還可以設(shè)置紋理文件夾地址:

//設(shè)置紋理文件路徑

mtlLoader.setTexturePath('../js/models/obj/');

1

2

加載MTL文件,并在文件加載成功后,創(chuàng)建OBJLoader并設(shè)置對(duì)象應(yīng)用當(dāng)前的材質(zhì):

//加載mtl文件

mtlLoader.load('female02.mtl', function (material) {

? ? //創(chuàng)建OBJ加載器

? ? var objLoader = new THREE.OBJLoader();

? ? //設(shè)置當(dāng)前加載的紋理

? ? objLoader.setMaterials(material);

? ? objLoader.setPath('../js/models/obj/');

? ? objLoader.load('female02.obj', function (object) {

? ? ? ? //添加陰影

? ? ? ? object.traverse(function (item) {

? ? ? ? ? ? if(item instanceof THREE.Mesh){

? ? ? ? ? ? ? ? item.castShadow = true;

? ? ? ? ? ? ? ? item.receiveShadow = true;

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? //縮放

? ? ? ? object.scale.set(.3,.3,.3);

? ? ? ? scene.add(object);

? ? })

});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

我們?cè)偃ゼ虞dOBJ文件,加載成功的文件就是可以導(dǎo)入到場(chǎng)景內(nèi)的3D對(duì)象。

案例源碼查看地址:點(diǎn)擊這里

COLLADA模型導(dǎo)入

COLLADA是一個(gè)開(kāi)放的標(biāo)準(zhǔn),最初用于3D軟件數(shù)據(jù)交換,由SCEA發(fā)起,現(xiàn)在則被許多著名廠家支持如Autodesk、XSI等。COLLADA不僅僅可以用于建模工具之間交換數(shù)據(jù)之用,也可以作為場(chǎng)景描述語(yǔ)言用于小規(guī)模的實(shí)時(shí)渲染。因?yàn)镃OLLADA DOM擁有豐富的內(nèi)容用于表現(xiàn)場(chǎng)景中的各種元素,從多邊形幾何體到攝像機(jī)無(wú)所不包。我們可以通過(guò)COLLADA DOM庫(kù)來(lái)進(jìn)行場(chǎng)景文件的讀取與處理操作。

上面是我寫(xiě)的一個(gè)模型導(dǎo)入案例,案例地址:點(diǎn)擊這里

實(shí)現(xiàn)步驟,首先引入ColladaLoader插件:

<script src="../js/loaders/ColladaLoader.js"></script>

1

接著實(shí)例化ColladaLoader對(duì)象:

var loader = new THREE.ColladaLoader();

1

最后加載文件并調(diào)整文件大小,添加到場(chǎng)景內(nèi):

loader.load('../js/models/collada/elf.dae', function (collada) {

? ? //添加陰影

? ? collada.scene.traverse(function (item) {

? ? ? ? if(item instanceof THREE.Mesh){

? ? ? ? ? ? item.castShadow = true;

? ? ? ? ? ? item.receiveShadow = true;

? ? ? ? }

? ? });

? ? //縮放

? ? collada.scene.scale.set(5,5,5);

? ? scene.add(collada.scene);

});

1

2

3

4

5

6

7

8

9

10

11

12

13

案例源碼查看:點(diǎn)擊這里

注意事項(xiàng)

如何知道,加載完成的模型需要將哪部分導(dǎo)入到場(chǎng)景?

一般情況下都是將自身導(dǎo)入,比如FBX,OBJ,JSON等,還有一種,會(huì)在里面生成一個(gè)可導(dǎo)入scene屬性,如:glTF和COLLADA文件。如果導(dǎo)入的你無(wú)法確定,你就把模型對(duì)象打印到控制臺(tái)查看,然后嘗試往場(chǎng)景內(nèi)導(dǎo)入。

導(dǎo)入到場(chǎng)景內(nèi)的模型無(wú)法查看,而且也沒(méi)有報(bào)錯(cuò)

這種會(huì)有可能有多種情況造成的,一般情況下都是下面兩種情況造成的:

模型太小或者太大,這種情況可以嘗試放大一千倍或者縮小一千倍來(lái)查看效果。

模型的位置太偏,根本不在相機(jī)照射范圍內(nèi),這種問(wèn)題我們可以將模型居中到相機(jī)照射的焦點(diǎn)位置查看,如何居中我們將在后面的章節(jié)中講解。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容