1. 程式人生 > >Three.js 實現merge後顯示相應的材質

Three.js 實現merge後顯示相應的材質

之前,我使用merge實現過將多個網格合併成一個網格,當時只是簡單的實現了一下幾何體的merge,證明merge後的能夠提高很大的效能。merge的幾何體有弊端就是,merge以後,只是一個整體,無法再分開,也沒辦法判斷點選的哪個物體,這隻適合合併一些場景內不再修改的模型。
geometry.merge

由於現在的幾何體分為geometry和bufferGeometry,我們分別看一下這兩種幾何體的使用:

bufferGeometry.merge(bufferGeometry:BufferGeometry,offset:Integer):null

bufferGeometry的merge方法只是普通的幾何體合併。

geometry.merge ( geometry : Geometry, matrix : Matrix4, materialIndexOffset : Integer ) : null

geometry的合併方法我們發現,有一個第三項,這一項是設定當前使用材質的下標,因為我們建立網格的時候可以選擇在材質選項選擇傳入一個材質陣列,來實現當前網格可以同時使用多種材質。那麼接下來我們就可以通過geometry的merge方法實現多個不同材質的mesh合併。如果幾何體是bufferGeometry格式的,那我們只能先轉成geometry來實現了。
案例

  • 首先,在load回撥中獲取到gltf物件
var loader = new THREE.GLTFLoader();
loader.load( 'zhuozi.gltf', function ( gltf ) {}
  • 建立材質陣列和幾何體陣列
let meshArr = [];
let materialArr = [];

 

  • 遍歷獲取到所有網格的材質和幾何體
gltf.scene.traverse(function(child){
	if(child.isMesh){
		meshArr.push(child);
		materialArr.push(child.material);
	}
});
  • 融合幾何體,並設定幾何體的材質下標
let geometry = new THREE.Geometry();
for(var i=0; i<meshArr.length; i++){
	meshArr[i].updateMatrix();
	geometry.merge(new THREE.Geometry().fromBufferGeometry(meshArr[i].geometry), meshArr[i].matrix, i);
}
  • 通過當前的合併的幾何體和材質陣列建立新的網格
let mesh = new THREE.Mesh(geometry, materialArr);
import {Mesh, Geometry, ExtrudeGeometry} from 'three';

export default class Transformation {
  async createNewModel (result) {
    const array = await this.pushmaterial(result);
    const geometry = await this.createGeometry(array);
    return new Mesh(geometry, array.materialArr);
  }
  pushmaterial (result) {
    const meshArr = [];
    const materialArr = [];
    result.traverse(res => {
      if (res.isMesh) {
        meshArr.push(res);
        materialArr.push(res.material);
      }
    });
    return {'meshArr': meshArr, 'materialArr': materialArr}
  }
  createGeometry (e) {
    const geometry = new Geometry();
    e.meshArr.forEach((r, i) => {
      e.meshArr[i].updateMatrix();
      geometry.merge(new ExtrudeGeometry().fromBufferGeometry(e.meshArr[i].geometry, e.meshArr[i].matrix, i));
    });
    return geometry;
  }
}