Use multiple materials for merged geometries in Three.js

戏子无情 提交于 2019-11-30 09:41:28

After a long research I discovered that I was missing an extra parameter for the method 'merge' from the Geometry object, the last parameter is the index of the material that the mesh must have from the materials array, ex: 0 -> first material in 'materials' array... and so on.

So, my final piece of code looks like:

pine_geometry.merge(pine_1.geometry, pine_1.matrix, 0);

var pine_texture_2 = THREE.ImageUtils.loadTexture('./res/textures/5.jpg');
var pine_geometry_2 = new THREE.CylinderGeometry(0, 70, 250, 8);
var pine_material_2 = new THREE.MeshBasicMaterial({
  map : pine_texture_2
});

var pine_2 = new THREE.Mesh(pine_geometry_2);
pine_2.position.x = x;
pine_2.position.y = y + 175;
pine_2.position.z = z;

pine_2.updateMatrix();
pine_geometry.merge(pine_2.geometry, pine_2.matrix, 1);

(Note the last numbers I add to each merge).

However, I want to clarify that this practice only works when we are dealing with various geometries that are from the same type, in this case, we're merging two CylinderGeometry, but if we wanted to merge for example a Cylinder with a Box AND add the MeshFaceMaterial, it wouldn't be recognized properly and the console will throw us 'Cannot read property map/attributes from undefined', nevertheless we can still merge both geometries but not providing multiple materials (that's a terrible mistake I made).

Hope this helps to anyone.

arpo

Here's a general function to merge meshes with materials, You can also specify if you want it to return it as a buffer geometry.

function _mergeMeshes(meshes, toBufferGeometry) {

    var finalGeometry,
        materials = [],
        mergedGeometry = new THREE.Geometry(),
        mergeMaterial,
        mergedMesh;

    meshes.forEach(function(mesh, index) {
        mesh.updateMatrix();
        mesh.geometry.faces.forEach(function(face) {face.materialIndex = 0;});
        mergedGeometry.merge(mesh.geometry, mesh.matrix, index);
        materials.push(mesh.material);
    });

    mergedGeometry.groupsNeedUpdate = true;
    mergeMaterial = new THREE.MeshFaceMaterial(materials);

    if (toBufferGeometry) {
        finalGeometry = new THREE.BufferGeometry().fromGeometry(mergedGeometry);
    } else {
        finalGeometry = mergedGeometry;
    }

    mergedMesh = new THREE.Mesh(finalGeometry, mergeMaterial);
    mergedMesh.geometry.computeFaceNormals();
    mergedMesh.geometry.computeVertexNormals();

    return mergedMesh;

}

var mergedMesh = _mergeMeshes([trunkMesh, treeTopMesh], true);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!