在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个模型,且保留了各自之前所在的位置,旋转等信息。