如何在 jsc3d 中使用多个纹理将纹理分配给 OBJ 文件

Al *_*lad 2 3d textures jsc3d

我使用 jsc3d 查看器以 .obj 格式导入 3d 对象的一组部分,并定义了纹理。我希望能够为每个单独的部分分配新的纹理。例如,我加载了 .obj 文件,其中包含 10 个不同的部分。所有部件都是完全白色的。我有 3 个 .png 格式的纹理(红色、蓝色和绿色)。我想将纹理“红色”分配给某些部分,将纹理“蓝色”和“绿色”分配给其他部分。我希望能够修改它们。怎么做?

感谢您的帮助

deb*_*ker 5

让我们从 obj 格式开始:这是一个简单立方体的示例,其相对面应用了 3 种不同的纹理:

# OBJ File Generated by Meshlab    
# Vertices: 8
# Faces: 12
mtllib ./tex_cube.obj.mtl
v -50.00 -50.00 50.00
v -50.00 50.00 50.00
v 50.00 -50.00 50.00
v 50.00 50.00 50.00
v 50.00 -50.00 -50.00
v 50.00 50.00 -50.00
v -50.00 -50.00 -50.00
v -50.00 50.00 -50.00
Run Code Online (Sandbox Code Playgroud)

注意mtl文件的路径,大多数问题是因为找不到该文件,而且有些3d工具不允许mtl文件或纹理的相对路径。我建议您将其与 obj 文件并排放置。

有 12 个三角形,因为立方体的每条边都已被三角化。vt(顶点纹理)标签定义了纹理的映射方式,在本例中是通过 UV(对于每个面来说都是简单的):

vt 1.00 1.00
vt 0.00 1.00
vt 0.00 0.00
vt 1.00 0.00
Run Code Online (Sandbox Code Playgroud)

JSC3D 将读取 vt 标签、f(faces)标签和 usemtl 标签来构建 3d 对象:

usemtl material_0
f 4/1 2/2 1/3
f 3/4 4/1 1/3
f 8/1 6/2 5/3
f 7/4 8/1 5/3

usemtl material_1
f 6/1 4/2 3/3
f 5/4 6/1 3/3
f 2/1 8/2 7/3
f 1/4 2/1 7/3

usemtl material_2
f 6/1 8/2 2/3
f 4/4 6/1 2/3
f 3/1 1/2 7/3
f 5/4 3/1 7/3
Run Code Online (Sandbox Code Playgroud)

材质被重新映射到mtl文件中相应的png文件:

newmtl material_0
Ka 0.200000 0.200000 0.200000
Kd 1.000000 1.000000 1.000000
Ks 1.000000 1.000000 1.000000
map_Kd red_tex.png
Run Code Online (Sandbox Code Playgroud)

...其他两种纹理(绿色和蓝色)依此类推。

该文件是从 MeshLab 中的以下导出设置中获得的,只是为了指出您不需要导出法线,JSC3D 将即时重新创建它们:

在此输入图像描述

抱歉对 obj 测试文件的无聊解释。

如果您在 JSC3D 查看器中加载此立方体并检查viewer.scene.children[],您将发现 3 个网格,因为 JSC3D 已将立方体的 12 个三角形分为 3 个独立的部分,每个部分对应已找到的usemtl 标签obj 文件内。

现在,您可以通过 PickInfo 结构通过选择查看器内的一个面(通过单击鼠标或触摸)或通过代码来获取此零件之一的引用。

例如,如果您需要将蓝色纹理替换为另一个纹理:

function replaceBlueTexture() {
    objParts = []; // you can also replace more than one part
    objParts[0] = viewer.scene.children[2];
    objLoader.setupTexture(objParts, "models/obj/aluminum.png");
}
Run Code Online (Sandbox Code Playgroud)

结果如下(加载后左,右,纹理更改后右):

在此输入图像描述

现在,这个立方体的顶面和底面都是铝质感的。

编辑:

ReplaceBlueTexture 函数假设您已经知道应替换哪个网格。

如果您必须用网格的名称替换其材质(或纹理)怎么办?

首先加载并解析 obj 文件,在 obj 文件之后加载 mtl 文件,但在解析 obj 文件期间,jsc3d 已捕获材质名称并将其存储在 Mesh 对象中。

如果您查看viewer.scene对象,您将看到上面描述的网格以及相关的材质和纹理:

在此输入图像描述

您需要的只是检查 mesh.mtl (或者可能是 mesh.material.name - 两者之一应填写在最新版本的 jsc3d 中):

function replaceBlueTextureByName() {
    var scene = viewer.getScene();
    var meshes = scene.getChildren();
    for (var i=0, l=meshes.length; i<l; i++) {
        var mesh = meshes[i];
        var mat = mesh.material;
        if (mat.name == 'mat_blue_tex') {
            var objParts = [];
            objParts[0] = mesh;
            loader.setupTexture(objParts, "models/obj/aluminum.png");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,请确保渲染模式可以显示纹理:

viewer.setParameter('RenderMode', 'texturesmooth');
Run Code Online (Sandbox Code Playgroud)