Open3D技术问询:如何将图像纹理投影到地形3D网格?
解决Open3D地形网格无法贴PNG图像的问题
你的问题核心是STL格式的地形网格没有UV坐标——STL本身只存储顶点和三角形信息,不包含UV映射数据,而你测试的立方体因为开启了create_uv_map=True,所以自带UV,自然能成功贴图。
下面给两种可行的解决方案:
方案1:用Open3D自动生成UV坐标
Open3D内置了compute_vertex_uvs()方法,可以基于网格的轴对齐边界框自动生成UV,适合大多数通用场景:
import open3d as o3d import open3d.visualization.rendering as rendering material = rendering.MaterialRecord() material.shader = 'defaultUnlit' material.albedo_img = o3d.io.read_image('terrain_image.png') mesh = o3d.io.read_triangle_mesh("terrain_mesh_file.stl") mesh.compute_vertex_normals() # 自动生成UV坐标 mesh.compute_vertex_uvs() # 可以用这个检查UV是否生成成功 print("是否已生成UV:", mesh.has_vertex_uvs()) o3d.visualization.draw({'name': 'terrain', 'geometry': mesh, 'material': material})
方案2:手动计算UV(适合规则地形)
如果你的地形是基于XY平面的高度场(比如从高度图生成,顶点的XY对应平面坐标、Z对应高度),手动计算UV能得到更精准的映射效果,避免自动生成可能出现的拉伸问题:
import open3d as o3d import numpy as np import open3d.visualization.rendering as rendering material = rendering.MaterialRecord() material.shader = 'defaultUnlit' material.albedo_img = o3d.io.read_image('terrain_image.png') mesh = o3d.io.read_triangle_mesh("terrain_mesh_file.stl") mesh.compute_vertex_normals() # 获取所有顶点的坐标数组 vertices = np.asarray(mesh.vertices) # 计算XY轴的最小/最大值,用于归一化 x_min, x_max = vertices[:, 0].min(), vertices[:, 0].max() y_min, y_max = vertices[:, 1].min(), vertices[:, 1].max() # 手动生成UV:将XY坐标缩放到0-1区间 uvs = np.zeros((len(vertices), 2)) uvs[:, 0] = (vertices[:, 0] - x_min) / (x_max - x_min) # 反转V轴(图像的Y轴和地形的Y轴方向通常相反,按需调整) uvs[:, 1] = 1.0 - (vertices[:, 1] - y_min) / (y_max - y_min) # 将UV数组赋值给网格 mesh.vertex_uvs = o3d.utility.Vector2dVector(uvs) o3d.visualization.draw({'name': 'terrain', 'geometry': mesh, 'material': material})
关键说明
- 执行完UV生成步骤后,一定要确认
mesh.has_vertex_uvs()返回True,否则贴图仍会失败。 - 如果自动生成的UV效果不佳,优先考虑手动计算——尤其是规则地形,手动UV能完美匹配图像的平面布局。
内容的提问来源于stack exchange,提问作者Cody
相关产品推荐
相关产品推荐

