第八章 創建、加載高級網格和幾何體
對象的組合
當從一個幾何體中創建網格,並使用多種材質時,Three.js就會創建一個組。
該幾何體的多個副本就會添加到這個組裏,每份副本都有自己特定的材質。
我們看到的結果是,一個網格擁有多個材質,實際上它是一個包含多個網格的組。
sphere = createMesh(new THREE.SphereGeometry(5,10,10));
cube = createMesh(new THREE.CubeGeometry(6,6,6));
group = new THREE.Object3D();
group.add(sphere);
group.add(cube);
scene.add(group);
如果旋轉一個組,不是旋轉組中的每個對象,而是旋轉整個組。
爲了方便觀察,在組的中心放置一個箭頭。
var arrow = new THREE.ArrowHelper (new THREE.Vector3(0,1,0),group.position,10,0x0000ff);
scene.add(arrow);
使用組的時候,依然可以引用和修改組中的一個單獨的幾何體。
將多個網格合併成一個網格
當渲染的對象比較多時,即使在組中,每個對象還是獨立的,需要對它們分別進行處理和渲染。
通過THREE.GeometryUtils.merge函數可以將多個幾何體合併起來,創建一個聯合體。
var geometry = new THREE.Geometry();
for(var i = 0 ;i<controls.numberOfObject;i++){
//addCube()返回一個THREE.CubeGeometry對象
THREE.GeometryUtils.merge(geometry,addCube());
//最大的缺點:不能對單獨的對象進行控制。
}
scene.add(new THREE.Mesh(geometry,cubeMaterial));
從外部資源加載幾何體
JSON:Three.js有它自己的json格式,你可以使用它以聲明的方式定義幾何體和場景。但是它不是一種正式的格式。
OBJ和MTL:OBJ是一種簡單的三維文件格式,用來定義對象的幾何體。MTL文件通常和OBJ文件一起使用,在一個MTL文件中,定義對象的材質。
Collada:用來定義XML類文件中數字內容的格式。差不多所有的三維軟件和渲染引擎都支持這個格式。
STL:立體成型術 。 廣泛用於快速成型。例如,三維打印機的模型文件通常是STL文件。Three.js有一個可定製的STL導出工具,STLExporter.js。可以將Three.js中的模型導出到一個STL文件。
CTM:由openCTM創建的格式。可以用來壓縮存儲表示三維網格的三角形面片。
VTK:Visualization Tookit 定義的文件格式,用來指定頂點和麪。VTK有兩種格式,Three.js支持舊的格式,即Asscii格式。
PDB:特別的數據格式,由 蛋白質數據銀行 場景,用來定義蛋白質的形狀。Three.js可以加載並顯示這種描述格式的蛋白質。
PLY:多邊形文件格式。通常保存三維掃描儀的數據。
Three.js的json格式
1.保存和加載幾何體
HTML5本地存儲API,通過這個API可以很容易將持久化信息保存在客戶端的瀏覽器中,以後還可以讀取,即使瀏覽器關閉,重啓之後也可以。
示例:
1.引入GeometryExporter.js。
2.保存幾何體到瀏覽器本地存儲中。
var exporter = new THREE.GeometryExporter();
var result = exporter.parse(knot.geometry);
localStorage.setItem("json",JSON.stringfy(result));
//將一個json對象轉換爲一個字符串
JSON.stringfy(result);
json對象的格式如下:
{
'metadata':{
'version':4,
'type':'geometry',
'generator':GeometryExporter''
},
'vertices':[14.00044545,-0.0065944,...],
'nvs':[
[]
],
'faces':[49,0,8,...]
}
Three.js保存的是原始的幾何體。它將所有頂點和麪的信息保存起來,但是你並不知道這到底是一個怎樣的幾何體。
加載保存的幾何體到場景中。
var json = localStorage.getItem('json');
if(json){
var localGeometry = JSON.parse(json);
var loader = new THREE.JSONLoader();
var geom = loader.parse(localGeometry);
loadedMesh = createMesh(geom.geometry);
loadedMesh.position.x = -35;
loadedMesh.position.z = -5;
scene.add(loadedMesh);
}
JSONLoader還提供了一個load函數,可以傳遞一個url地址,改地址指向一個含有json定義的文件。
這裏,我們只保存了幾何體,其他的信息都丟失了,比如材質、光源、位置等。我們可以使用SceneExporter保存這些信息。
保存和加載場景
1.引入SceneExporter.js
2.導出場景
var exporter = new THREE.SceneExporter();
var sceneJson = JSON.stringfy(exporter.parse(scene));
localStorage.setItem('scene',sceneJson);
3.加載場景
var json = localStorage.getItem('scene');
var sceneLoader = new THREE.SceneLoader();
sceneLoader.parse(JSON.parse(json),function(e){
scene = e.scene;
},'.');
傳遞給loader的最後一個參數”.”是一個URL相對地址。例如,在材質中使用的紋理,就可以從這個相對地址中獲取。本例中,我們沒有使用紋理,所以傳遞但其概念目錄即可。
同GeometryLoader一樣,你也可以使用load函數直接加載一個JSON文件。
使用Blender
在blender中安裝Three.js導出器:
G:\Study\WebGL\three.js-r73\utils\exporters\blender\addons中的io_three目錄拷貝到Blender安裝目錄下的addons目錄下。
激活導出器:
打開Blender->File->User Preferences->Addons->搜索three->勾選複選框
在Blender里加載和導出模型
File->Open->assets/models/misc_chair01.blend
File->Export->Three.js
導出的json文件中引用了紋理圖片,所以我們要確保Three.js能夠找到這個紋理文件。
在Blend中打開UV/Image Editor視圖。File->…
Image->Save as Image 保存到和json模型相同的文件夾下。
在Three.js中加載模型:
var loader = new THREE.JsonLoader();
loader.load('../assets/models/misc_chair01.js',function(geometry,material){
mesh = new THREE.Mesh(geometry,material[0]);
mesh.scale.x = 15;
mesh.scale.y = 15;
mesh.scale.z = 15;
scene.add(mesh);
},'../assets/models');
Three.js導入三維文件格式
1.OBJ和MTL格式
兩種格式相互配合。OBJ定義幾何體格式,而MTL定義所用的材質。兩者都是文本格式。
在Three.js中如果只加載幾何體,則只需引入OBJLoader.js
var loader = new THREE.OBJLoader();
loader.load('../assets/models/pinecone.obj',function(geometry){
var material = new THREE.MeshLambertMaterial({
color:0x5C3A21
});
geometry.children.forEach(function(child){
if(child.children.length==1){
if(child.children[0] instanceof THREE.Mesh){
child.children[0].material = material;
}
}
});
geometry.scale.set(100,100,100);
geometry.rotation.x = -0.3;
scene.add(geometry);
});
如果加載幾何體並直接賦予材質,需要引入:
OBJLoader.js
MTLLoader.js
OBJMTLLoader.js
var loader = new THREE.OBJMTLLoader();
loader.load('load',function(event){
var object = event.content;
var wing2 = object.children[5].children[0];
var wing1 = object.children[4].children[0];
wing1.material.alphaTest = 0.5;
wing1.material.opacity = 0.6;
wing1.material.transparent = true;
wing2.material.alphaTest = 0.5;
wing2.material.opacity = 0.6;
wing2.material.transparent = true;
object.scale.set(140,140,140);
object.rotation.x = 0.2;
object.rotation.y = -1.3;
scene.add(object);
});
loader.load('../assets/models/butterfly.obj','../assets/models/butterfly.mtl');
有時間加載的模型源文件中材質的設置可能有問題,爲此我們不得不去檢查模型材質的定義,並修改一些屬性。
2.加載Collada模型
擴展名.dae ,是另一種通用的、定義場景和模型(以及動畫)的文件格式。
Collada不僅可以定義幾何體,也定義了材質,甚至還可以定義光源。
引入js庫:ColladaLoader.js
var mesh ;
loader.load('../assets/models/dae/Trunck_dae.dae',function(result){
mesh = result.scene.children[0].children[0].clone();
mesh.scale.set(4,4,4);
scene.add(mesh);
});
result對象的結構如下:
var result = {
scene:scene,
morphs:morphs,
skins:skins,
animations:animData,
dar:{
...
}
};
第一次加載該模型的時候,材質不能正確的渲染。因爲材質的紋理使用TGA格式,而Three.js不支持該格式。
所以我們將TGA格式轉換爲PNG格式,再修改.dar模型文件中的xml元素,使其指向轉換後的PNG文件。
3.加載STL、CTM和VTK模型
<1>引入[NameOfFormat]Loader.js文件
<2>使用[NameOfFormat]Loader.load()函數從URL中加載。
<3>檢查回調函數的返回結果,並對它進行渲染。
4.展示蛋白質數據銀行中的蛋白質
蛋白質數據銀行收集了很多分子、蛋白質的詳細信息。還可以以PDB格式下載這些分子的數據結構。
Three.js中解析PDB文件:
引入:PDBLoader.js
var loader = new THREE.PDBLoader();
var group = new THREE.Obeject3D();
loader.load('../assets/models/diamond.pdb',function(geometry,geometryBonds){
var i = 0;
//每個頂點代表頂點的位置
geometry.vertices.forEach(function(position){
var sphere = new THREE.SphereGeometry(0.2);
var material = new THREE.MeshPhongMaterial({
color:geometry.colors[i++];
});
var mesh = new THREE.Mesh(sphere,material);
mesh.position = position;
group.add(mesh);
});
//定義原子之間的鍵
for(var j = 0 ;j<geometryBonds.vertices.length;j+=2){
//創建一條三維路徑,作爲原子鍵
var path = new THREE.SplineCurve3([
geometryBonds.vertices[j],
geometryBonds.vertices[j+1]
]);
var tube = new THREE.TubeGeometry(path,1,0.04);
var material = new THREE.MeshPhongMaterial({
color:0xcccccc
});
var mesh = new THREE.Mesh(tube,material);
group.add(mesh);
}
console.log(geometry);
console.log(geometryBonds);
scene.add(group);
});
- 從PLY模型中創建粒子系統
引入:PLYLoader.js
var loader = new THREE.PLYLoader();
var group = new THREE.Object3D();
loader.load('../assets/models/test.ply',function(geometry){
var material = new THREE.ParticleBasicMaterial({
color:0xffffff,
size:0.4,
opacity:0.6,
transparent:true,
blending:THREE.AdditiveBlending,
map:generateSprite()
});
group = new THREE.ParticleSystem(geometry,material);
group.sortParticles = true;
console.log(group);
scene.add(group);
});