在 Three.js 中为合并的几何图形使用多种材质

Posted

技术标签:

【中文标题】在 Three.js 中为合并的几何图形使用多种材质【英文标题】:Use multiple materials for merged geometries in Three.js 【发布时间】:2015-01-28 19:24:47 【问题描述】:

我想用 2 个网格创建一个 Pine,1 个用于树干,另一个用于灌木,这是我所做的:

var pine_geometry = new THREE.Geometry();

var pine_texture_1 = THREE.ImageUtils.loadTexture('./res/textures/4.jpg');
var pine_geometry_1 = new THREE.CylinderGeometry(25, 25, 50, 6);
var pine_material_1 = new THREE.MeshBasicMaterial(
  map : pine_texture_1
);

var pine_1 = new THREE.Mesh(pine_geometry_1);
pine_1.position.x = x;
pine_1.position.y = y + 25;
pine_1.position.z = z;

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

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);

var pine = new THREE.Mesh(pine_geometry, new THREE.MeshFaceMaterial([pine_material_1, pine_material_2]));
pine.geometry.computeFaceNormals();
pine.geometry.computeVertexNormals();

Game.scene.add(pine);

松树按照我的意愿正确定位,但是,整个合并的形状只使用 1 种材料而不是 2 种(整个形状被第 1 种覆盖),我希望每个网格在合并两者时都有各自的材料。

我做错了什么?有什么想法吗?

【问题讨论】:

MeshFaceMaterial 已被删除。请改用Array 【参考方案1】:

经过长时间的研究,我发现我缺少几何对象中“合并”方法的额外参数,最后一个参数是网格必须具有的 材质索引材料数组,例如:0 ->“材料”数组中的第一个材料......等等。

所以,我的最后一段代码如下:

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);

(注意我添加到每个合并中的最后一个数字)。

然而,我想澄清一下,这种做法只在我们处理来自同一类型的各种几何图形时才有效,在这种情况下,我们正在合并 两个 CylinderGeometry,但是如果我们想合并一个圆柱体和一个盒子并添加 MeshFaceMaterial,它不会被正确识别,控制台会抛出“无法读取未定义的属性映射/属性”,但我们仍然可以合并两种几何形状,但不提供多种材料(这是我犯的一个严重错误)。

希望这对任何人都有帮助。

【讨论】:

我正在尝试执行此操作,但收到错误 three.js:20820 Uncaught TypeError: Cannot read property 'visible' of undefined。有什么解决办法吗?【参考方案2】:

这是一个将网格与材质合并的通用函数,您也可以指定是否要将其作为缓冲区几何体返回。

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);

【讨论】:

以上是关于在 Three.js 中为合并的几何图形使用多种材质的主要内容,如果未能解决你的问题,请参考以下文章

three.js:挤出几何体的多种材质问题

Three.js开发指南---创建,加载高级网格和几何体(第八章)

6种常见三维曲面的Three.js实现

在 Three.js 中为加载的 glb 模型分配纹理

Three.js开发指南---使用three.js的材质(第四章)

Three.js Raycaster on WebWorker