如何在 jsc3d 中使用多个纹理将纹理分配给 OBJ 文件
How to assign a texture to an OBJ file using multiple textures in jsc3d
我使用 jsc3d 查看器以定义了纹理的 .obj 格式导入 3d 对象的一组部分。我希望能够为每个单独的部分分配新的纹理。
例如,我加载了包含 10 个不同部分的 .obj 文件。所有的部分都是完全白色的。我有 3 个 .png 格式的纹理(红色、蓝色和绿色)。我想将纹理 "red" 分配给某些部分,将纹理 "blue" 和 "green" 分配给其他部分。我希望能够修改它们。怎么做?
感谢您的帮助
让我们从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
注意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
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
材质重新映射到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
... 以此类推其他两种纹理,绿色和蓝色。
此文件是从 MeshLab 中的以下导出设置中获得的,只是指出您不需要导出法线,JSC3D 会即时重新创建它们:
抱歉,obj 测试文件的解释很无聊。
如果你在 JSC3D 查看器中加载这个立方体并检查 viewer.scene.children[] 你会发现 3 个网格,因为 JSC3D 已经将立方体的 12 个三角形分组为 3 个独立的部分,一个用于在 obj 文件中找到的每个 usemtl 标记。
现在,您可以通过 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");
}
结果如下(加载后左图右图,贴图变化后右图):
现在,这个立方体的顶面和底面都是铝质的。
编辑:
replaceBlueTexture 函数假定您已经知道应替换哪个网格。
如果您必须用其名称替换网格的 material(或纹理)怎么办?
obj文件先加载解析,mtl文件在obj文件之后加载,但是material名称在解析obj文件时已经被jsc3d捕获并存储在Mesh对象中。
如果您查看 viewer.scene 对象,您将看到上面描述的网格以及相关的 material 和纹理:
你只需要检查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");
}
}
}
顺便说一句,确保渲染模式可以显示纹理:
viewer.setParameter('RenderMode', 'texturesmooth');
我使用 jsc3d 查看器以定义了纹理的 .obj 格式导入 3d 对象的一组部分。我希望能够为每个单独的部分分配新的纹理。 例如,我加载了包含 10 个不同部分的 .obj 文件。所有的部分都是完全白色的。我有 3 个 .png 格式的纹理(红色、蓝色和绿色)。我想将纹理 "red" 分配给某些部分,将纹理 "blue" 和 "green" 分配给其他部分。我希望能够修改它们。怎么做?
感谢您的帮助
让我们从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
注意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
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
材质重新映射到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
... 以此类推其他两种纹理,绿色和蓝色。
此文件是从 MeshLab 中的以下导出设置中获得的,只是指出您不需要导出法线,JSC3D 会即时重新创建它们:
抱歉,obj 测试文件的解释很无聊。
如果你在 JSC3D 查看器中加载这个立方体并检查 viewer.scene.children[] 你会发现 3 个网格,因为 JSC3D 已经将立方体的 12 个三角形分组为 3 个独立的部分,一个用于在 obj 文件中找到的每个 usemtl 标记。
现在,您可以通过 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");
}
结果如下(加载后左图右图,贴图变化后右图):
现在,这个立方体的顶面和底面都是铝质的。
编辑:
replaceBlueTexture 函数假定您已经知道应替换哪个网格。
如果您必须用其名称替换网格的 material(或纹理)怎么办?
obj文件先加载解析,mtl文件在obj文件之后加载,但是material名称在解析obj文件时已经被jsc3d捕获并存储在Mesh对象中。
如果您查看 viewer.scene 对象,您将看到上面描述的网格以及相关的 material 和纹理:
你只需要检查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");
}
}
}
顺便说一句,确保渲染模式可以显示纹理:
viewer.setParameter('RenderMode', 'texturesmooth');