Open3D icon indicating copy to clipboard operation
Open3D copied to clipboard

When simplify_quadric_decimation is used, the UVs and maps of OBJ are missing. What should I do with this?

Open mumumomo opened this issue 3 years ago • 3 comments

Checklist

My Question

When simplify_quadric_decimation is used, OBJ's UVs and maps disappear And there is a warning[Open3D WARNING] [SimplifyQuadricDecimation] This mesh contains triangle uvs that are not handled in this function How can I solve this problem?

mumumomo avatar Jun 13 '22 07:06 mumumomo

Same here, any solution?

tomhsiao1260 avatar Nov 08 '23 15:11 tomhsiao1260

same.

blackjacket996 avatar Aug 05 '24 01:08 blackjacket996

I had the same issue. I worked around it by computing the vertex_colors from the original mesh according to the textures then created a new texture from the vertex_colors of the decimated mesh.

def create_vertex_colors(mesh, verbose=False):
    vertex_colors = np.zeros((len(mesh.vertices), 3), dtype=np.float64)
    
    if verbose:
        print("Creating vertex colors, please wait...")
    
    num_triangles = len(mesh.triangles)
    progress_step = max(1, num_triangles // 100)
    
    for triangle_index in range(num_triangles):
        # Choose the texture corresponding to this triangle based on its material id
        texture_index = mesh.triangle_material_ids[triangle_index]
        texture_image = mesh.textures[texture_index]
        texture_np = np.asarray(texture_image)
        height, width, _ = texture_np.shape
        
        # Process each vertex of the triangle
        for local_vertex in range(3):
            u, v = mesh.triangle_uvs[triangle_index * 3 + local_vertex]
            x = int(u * (width - 1))
            y = int(v * (height - 1))
            global_vertex_index = mesh.triangles[triangle_index][local_vertex]
            vertex_colors[global_vertex_index] = texture_np[y, x] / 255.0
        
        if verbose and (triangle_index % progress_step) == 0:
            print('#', end='', flush=True)
    
    if verbose:
        print()
    
    return o3d.utility.Vector3dVector(vertex_colors)


def create_texture_from_vertex_colors(mesh):
    vertex_colors = np.asarray(mesh.vertex_colors)

    texture_dimension = int(np.ceil(np.sqrt(len(mesh.triangles) * 3)))

    texture = np.full((texture_dimension, texture_dimension, 3), 0, dtype=np.float32)
    triangle_uvs = np.full((len(mesh.triangles) * 3, 2), 0, dtype=np.float64)

    for triangle_index, triangle in enumerate(mesh.triangles):
        for vertex_sub_index in range(3):
            UV_index = 3 * triangle_index + vertex_sub_index
            U = UV_index % texture_dimension
            V = UV_index // texture_dimension
            texture[V, U] = vertex_colors[triangle[vertex_sub_index]]
            triangle_uvs[UV_index] = (
                (U + 0.5) / texture_dimension,
                (V + 0.5) / texture_dimension
            )
    mesh.textures = [o3d.geometry.Image(texture)]
    mesh.triangle_uvs = o3d.utility.Vector2dVector(triangle_uvs)
    mesh.triangle_material_ids = o3d.utility.IntVector([0] * len(mesh.triangles))
    return mesh


mesh.vertex_colors = create_vertex_colors(mesh, verbose=True)
target_number_of_triangles = 50000
mesh.simplify_quadric_decimation(target_number_of_triangles=target_number_of_triangles)
mesh = create_texture_from_vertex_colors(mesh)

hope this helps

ghost avatar May 27 '25 09:05 ghost