在three.js中,合並模型可以通過它的擴展庫ThreeBsp.js來辦到。不過當模型稍微較復雜時,操作時間會延長,且瀏覽器容易崩潰。其實three.js自己也提供了這個功能,那就是通過THREE.GeometryUtils.merge來實現。
具體實現:
假如要合並模型A、B、C。
var mesh = new THREE.Geometry(); THREE.GeometryUtils.merge(mesh,A); THREE.GeometryUtils.merge(mesh,B); THREE.GeometryUtils.merge(mesh,C);
var material = new THREE.MeshLambertMaterial({ color: '0xff074f' });
var result = new THREE.Mesh(mesh, material);
此時的result便是合並后的模型了。
但是,存在一個問題,對於類型為BufferGeometry的模型來說,此方法是無效的。
幸運的是,在THREE.BufferGeometry中也存在着merge方法,因此試着將代碼改為了
var mesh = new THREE.BufferGeometry(); mesh.merge(A.geometry); mesh.merge(B.geometry); mesh.merge(C.geometry); var material = new THREE.MeshLambertMaterial({ color: '0xff074f' }); var result = new THREE.Mesh(mesh, material);
結果報了錯
試了幾種方法,都失敗了,然后在網上找到了一種解決方法:
var model = [A, B, C]; var mesh = new THREE.BufferGeometry(); var posLen = 0; var normLen = 0; var sumPosCursor = 0; var sumNormCursor = 0; for (var i=0;i<model.length;i++) { posLen += model[i].geometry.getAttribute('position').array.length; normLen += model[i].geometry.getAttribute('normal').array.length; } var sumPosArr = new Float32Array(posLen); var sumNormArr = new Float32Array(normLen); for (var i=0;i<model.length;i++) { var posAttArr = model[i].geometry.getAttribute('position').array; for (var j=0;j<posAttArr.length;j++) { sumPosArr[j+sumPosCursor] = posAttArr[j]; } sumPosCursor += posAttArr.length; var numAttArr = model[i].geometry.getAttribute('normal').array; for (var j=0;j<numAttArr.length;j++) { sumNormArr[j+sumNormCursor] = numAttArr[j]; } sumNormCursor += numAttArr.length; } mesh.addAttribute('position', new THREE.BufferAttribute(sumPosArr, 3 )); mesh.addAttribute('normal', new THREE.BufferAttribute(sumNormArr, 3 ));
var material = new THREE.MeshLambertMaterial({
color: '0xff074f'
});
var result = new THREE.Mesh(mesh, material);
3個BufferGeometry類型的模型成功合並,但是,存在一個問題,合並后的模型丟失了之前3個模型的獨自的位置信息,導致合並之后3個模型重合到了一起。
因此,選擇了另外一種方案:首先將這三個模型都轉換為Geometry類型的模型,然后進行合並。
var model = [A, B, C]; for(var i=0;i<model.length;i++){ model[i].geometry = new THREE.Geometry().fromBufferGeometry(model[i].geometry); } var mesh = new THREE.Geometry(); for(var i=0;i<model.length;i++){ THREE.GeometryUtils.merge(mesh,model[i]); } var material = new THREE.MeshLambertMaterial({ color: '0xff074f' }); var result = new THREE.Mesh(mesh, material);
測試發現,成功合並了3個模型,且保留了各自之前所在的位置,旋轉等信息。