2018-10-08 17:19:08?專注前端30年?閱讀數(shù) 3049更多
分類專欄:?達人課?three.js 基礎入門
版權聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權協(xié)議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_30100043/article/details/80979604
現(xiàn)在市面上的3D模型有上百種,每一種的格式都有不同的用途,不同的功能和復雜程度。盡管Three.js提供了很多的加載器,但選擇正確的格式和工作流程將在以后節(jié)省時間和成本。而且某些格式難以使用,效率低下或者目前還未完全支持。
官方推薦我們使用的3D模型的格式為glTF,由于glTF專注于傳輸,因此它的傳輸和解析的速度都很快。glTF模型功能包括:網(wǎng)格,材質,紋理,蒙皮,骨骼,變形動畫,骨骼動畫,燈光以及相機。
如果當前的首選不是glTF格式,那么推薦Three.js定期維護并且流行的格式FBX,OBJ或者COLLADA格式,Three.js也有自己獨有的JSON格式。我們接下來將介紹這五種格式:
這里的JSON格式指的是Three.js可以將其轉換為場景的3D對象的JSON格式模型。這種格式內(nèi)部一般必有的四項為:
metadata?當前模型的相關信息以及生成的工具信息
geometries?存儲當前模型所使用的幾何體的數(shù)組
materials?存儲當前模型所使用的材質的數(shù)組
object?當前模型的結構以及標示所應用到的材質和幾何體標示
所有的模型網(wǎng)格,幾何體和材質都有一個固定的uuid標識符,JSON格式中都是通過uuid作為引用。
所有的THREE.Object3D對象都可以轉成JSON字符串保存成為文件,我們不能直接將對象轉成JSON是因為JSON是無法保存函數(shù)的,所以,Three.js給我們提供了一個toJSON()的方法來讓我們轉換為可存儲的JSON格式。
var obj = scene.toJSON(); //將整個場景的內(nèi)容轉換成為json對象
var obj = group.toJSON(); //將一個模型組轉成json對象
var obj = mesh.toJSON(); //將一個模型網(wǎng)格轉成json對象
var JSONStr = JSON.stringify(obj); //將json對象轉換成json字符串
1
2
3
4
按照這種方式,我們就可以將生成的場景模型保存為文件。
既然我們能夠導入,肯定就可以導入。這里我們將使用到Three.js內(nèi)置的對象THREE.ObjectLoader來加載模型:
直接加載Three.js生成的JSON對象:
var obj = scene.toJSON(); //將整個場景的內(nèi)容轉換成為json對象
let loader = new THREE.ObjectLoader(); //實例化ObjectLoader對象
let scene = loader.parse(obj); //將json對象再轉換成3D對象
1
2
3
4
加載外部的JSON文件:
let loader = new THREE.ObjectLoader(); //實例化ObjectLoader對象
//加載模型,并在回調(diào)中將生成的模型對象添加到場景中
loader.load("../js/models/json/file.json", function (group) {
? ? scene.add(group);
});
1
2
3
4
5
6
案例地址:點擊這里
案例的右上角有四個點擊事件:
添加模型:將在場景內(nèi)隨機生成一組立方體,每次都不相同。
導出模型:將場景內(nèi)這一組立方體可以導出到本地json文件。
導入模型:可以將選擇的符合JSON文件解析并導入到場景內(nèi)。
加載模型:將加載服務器上面的一個JSON文件。
案例代碼地址:點擊這里
glTF格式的3D格式文件是官方推薦的使用的格式,這種格式的文件我們可以在sketchfab官網(wǎng)下載,這是一個國外比較知名的模型網(wǎng)站,下載地址是:點擊這里,我們可以在這里下載一些免費的glTF格式的模型。
這里我在官網(wǎng)上隨便找了一個不錯的模型做了一個案例:點擊這里
模型加載的速度會有些慢,大家可以等待一下便能夠看到這個小汽車。
接下來我們便講解一下加載glTF模型的流程:
首先,將GLTFLoader加載器插件引入到頁面,插件在官方包的地址/examples/js/loaders/,一些文件的導入插件都在這一個文件夾內(nèi),大家有興趣可以研究一下:
<script src="../js/loaders/GLTFLoader.js"></script>
1
然后創(chuàng)建一個加載器:
var loader = new THREE.GLTFLoader();
1
使用加載器去加載模型,并調(diào)節(jié)一下模型大小在場景內(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
我們需要有時候不明白的是,我加載了一個模型,哪一部分是需要導入場景的模型呢?
這里我們可以先將解析的出來的模型對象打印一下,然后通過查看對象屬性來了解到底是導入場景內(nèi)的對象,就比如glTF模型轉換出來的對象的scene屬性就是需要導入場景的對象,而JSON格式的模型是直接可以導入的對象。
模型加載案例源碼:點擊這里
FBX最大的用途是用在諸如在max、maya、softimage等軟件間進行模型、材質、動作和攝影機信息的互導,這樣就可以發(fā)揮max和maya等軟件的優(yōu)勢。可以說,F(xiàn)BX方案是最好的互導方案。
接下來我們看一下FBX模型導入的案例,這是我在網(wǎng)上隨便下載的一個FBX格式的模型,導入到場景內(nèi)的效果,案例查看地址:點擊這里
實現(xiàn)過程:
首先我們需要導入FBXLoader插件,并且還需要額外增加一個解析二進制文件的插件inflate.min.js,不導入這個文件的話,除了一些字符串存儲的FBX格式,別的格式都會報錯:
<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
修改模型大小,并設置每個模型網(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
這樣就實現(xiàn)了FBX模型的導入。
案例源碼地址:點擊這里
OBJ文件是3D模型文件格式。由Alias|Wavefront公司為3D建模和動畫軟件"Advanced Visualizer"開發(fā)的一種標準,適合用于3D軟件模型之間的互導,也可以通過Maya讀寫。
OBJ文件是一種文本文件,可以直接用寫字板打開進行查看和編輯修改,但不包含動畫、材質特性、貼圖路徑、動力學、粒子等信息。
OBJ文件的導出通常會和MTL格式一同導出,MTL作為OBJ文件的附屬文件,卻有著OBJ文件需要貼圖材質,所以,我們通常使用時,將它們兩個文件一同導入。
這是我使用官網(wǎng)提供的一個模型制作的一個案例,查看地址:點擊這里
實現(xiàn)導入的過程:
首先,我們需要將OBJLoader插件和MTLLoader插件引入頁面:
<script src="../js/loaders/OBJLoader.js"></script>
<script src="../js/loaders/MTLLoader.js"></script>
1
2
實例化MTLLoader:
//創(chuàng)建MTL加載器
var mtlLoader = new THREE.MTLLoader();
//設置文件路徑
mtlLoader.setPath('../js/models/obj/');
1
2
3
4
如果有需要,我們還可以設置紋理文件夾地址:
//設置紋理文件路徑
mtlLoader.setTexturePath('../js/models/obj/');
1
2
加載MTL文件,并在文件加載成功后,創(chuàng)建OBJLoader并設置對象應用當前的材質:
//加載mtl文件
mtlLoader.load('female02.mtl', function (material) {
? ? //創(chuàng)建OBJ加載器
? ? var objLoader = new THREE.OBJLoader();
? ? //設置當前加載的紋理
? ? 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
我們再去加載OBJ文件,加載成功的文件就是可以導入到場景內(nèi)的3D對象。
案例源碼查看地址:點擊這里
COLLADA是一個開放的標準,最初用于3D軟件數(shù)據(jù)交換,由SCEA發(fā)起,現(xiàn)在則被許多著名廠家支持如Autodesk、XSI等。COLLADA不僅僅可以用于建模工具之間交換數(shù)據(jù)之用,也可以作為場景描述語言用于小規(guī)模的實時渲染。因為COLLADA DOM擁有豐富的內(nèi)容用于表現(xiàn)場景中的各種元素,從多邊形幾何體到攝像機無所不包。我們可以通過COLLADA DOM庫來進行場景文件的讀取與處理操作。
上面是我寫的一個模型導入案例,案例地址:點擊這里
實現(xiàn)步驟,首先引入ColladaLoader插件:
<script src="../js/loaders/ColladaLoader.js"></script>
1
接著實例化ColladaLoader對象:
var loader = new THREE.ColladaLoader();
1
最后加載文件并調(diào)整文件大小,添加到場景內(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
案例源碼查看:點擊這里
如何知道,加載完成的模型需要將哪部分導入到場景?
一般情況下都是將自身導入,比如FBX,OBJ,JSON等,還有一種,會在里面生成一個可導入scene屬性,如:glTF和COLLADA文件。如果導入的你無法確定,你就把模型對象打印到控制臺查看,然后嘗試往場景內(nèi)導入。
導入到場景內(nèi)的模型無法查看,而且也沒有報錯
這種會有可能有多種情況造成的,一般情況下都是下面兩種情況造成的:
模型太小或者太大,這種情況可以嘗試放大一千倍或者縮小一千倍來查看效果。
模型的位置太偏,根本不在相機照射范圍內(nèi),這種問題我們可以將模型居中到相機照射的焦點位置查看,如何居中我們將在后面的章節(jié)中講解。