cnr-isti-vclab / PyMeshLab

The open source mesh processing python library
GNU General Public License v3.0
784 stars 64 forks source link

Saving OBJ file with colors after merging meshes not working #258

Closed han16nah closed 1 year ago

han16nah commented 2 years ago

Hi, I am trying to merge two meshes and save the output as OBJ. I have multiple issues and hope it is okay to collect them here.

Ideally, I would like to preserve the original materials with their names, but at least, I would like to have the correct colors in my output (no matter how the materials are named). Neither of those is working.

OS: Windows 10 version: pymeshlab 2022.2.post2 python version: 3.9.13

Issue 1: Full file path to mtl file instead of relative file path is written

####
#
# OBJ File Generated by Meshlab
#
####
# Object I:\Hessigheim3D\Epoch_March18\Mesh\z-merged_tiles\51382_542679.obj
#
# Vertices: 182978
# Faces: 364938
#
####
mtllib ./I:\Hessigheim3D\Epoch_March18\Mesh\z-merged_tiles\51382_542679.obj.mtl

Hence, material is not found when, e.g., loading to CloudCompare. Has to be changed manually.. or I guess the relative path has to be given as the OBJ file path to save to.. See also #207

Issue 2: Colours in mtlfile do not correspond to colour in original mtl file of imported files. Example: Input:

# ifp custom obj exporter
newmtl Low Vegetation
Ka 0.698039 0.796078 0.184314
Kd 0.698039 0.796078 0.184314
Ks 0.698039 0.796078 0.184314
illum 2
Ns 136.430000

newmtl Impervious Surface
Ka 0.717647 0.698039 0.666667
Kd 0.717647 0.698039 0.666667
Ks 0.717647 0.698039 0.666667
illum 2
Ns 136.430000

newmtl Vehicle
Ka 0.125490 0.592157 0.639216
Kd 0.125490 0.592157 0.639216
Ks 0.125490 0.592157 0.639216
illum 2
Ns 136.430000

newmtl Urban Furniture
Ka 0.658824 0.129412 0.419608
Kd 0.658824 0.129412 0.419608
Ks 0.658824 0.129412 0.419608
illum 2
Ns 136.430000

...

Output:

#
# Wavefront material file
# Converted by Meshlab Group
#

newmtl material_0
Ka 0.200000 0.200000 0.200000
Kd 0.000000 0.501961 0.254902
Ks 1.000000 1.000000 1.000000
Tr 1.000000
illum 2
Ns 0.000000

newmtl material_1
Ka 0.200000 0.200000 0.200000
Kd 0.000000 0.000000 0.000000
Ks 1.000000 1.000000 1.000000
Tr 1.000000
illum 2
Ns 0.000000

newmtl material_2
Ka 0.200000 0.200000 0.200000
Kd 0.694118 0.792157 0.184314
Ks 1.000000 1.000000 1.000000
Tr 1.000000
illum 2
Ns 0.000000

newmtl material_3
Ka 0.200000 0.200000 0.200000
Kd 0.658824 0.129412 0.419608
Ks 1.000000 1.000000 1.000000
Tr 1.000000
illum 2
Ns 0.000000

However, colours are displayed correctly when using show_polyscope.

Issue 3: I hoped that at least the classes were simply renamed in the correct order and I could just use my old mtlfile and replace the original material name by the ones Meshlab uses, i.e., material_0, material_1, etc. in the order listed. However, the order seems to be different, so this is also not working ...


Code I'm using: (Background: Iterating to list of files, checking if they have the same x-y-extent (indicated in filenames) and then merging if they have different z-extents.)

# inputs
mesh_tiles = list(Path(r"Mesh\per-tile\train").glob("*/*_labeled.obj"))
out_dir_mesh = "I:\Hessigheim3D\Epoch_March18\Mesh\z-merged_tiles"

id_list = [f.stem[:12] for f in mesh_tiles]

tname = ""
ms = pymeshlab.MeshSet()

# note: tiles which should be merged only differ in the last bit of the filenames, corresponding to z coords
# e.g., 51398_542673_20_labeled.obj and 51398_542673_25_labeled.obj should be merged
# there are not always two tiles which have to be merged vertically
for m in mesh_tiles:
    if not m.stem[:12] in tname:
        print("New mesh, MeshSet cleared.")
        ms.clear()
    print("Loading Mesh to MeshSet")
    ms.load_new_mesh(str(m))
    if id_list.count(m.stem[:12]) == 2 and m.stem[:12] not in tname:
        print("Tile has second part. Continuing.")
        tname = str(m.stem).replace("_labeled", "")
        continue
    elif id_list.count(m.stem[:12]) == 2 and m.stem[:12] in tname:
        print(f"Merging {m.stem} and {tname}")
        ms.generate_by_merging_visible_meshes()
    tname = str(m.stem).replace("_labeled", "")
    print("Saving mesh.")
    outpath_mesh = str(Path(out_dir_mesh) / f"{tname[:12]}.obj")
    ms.compute_color_transfer_face_to_vertex()
    ms.show_polyscope()  # colors are correct here
    ms.save_current_mesh(outpath_mesh)
han16nah commented 2 years ago

Issue 2: appears to me when using MeshLab GUI as well. Does not write correct face colours to OBJ..

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. The resources of the VCLab team are limited, and so we are asking for your help. If this is a bug and you can still reproduce this error on the last release of PyMeshLab, please reply with all of the information you have about it in order to keep the issue open. If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

alemuntoni commented 1 year ago

Hi, sorry for the late reply.

Issue 1: duplicate of #207, it should be solved in the next version of pymeshlab. You can try it by downloading and installing the last nightly from here.

Issue 2: this issue cannot be solved easily, I'm sorry. VCGLib, which is the core library used by meshlab and pymeshlab, does not store materials as they are organized in obj files. It stores just colors and texture coordinates (per vertex, per face). It does not store material names and other features (e.g. Ka and Kd values in the output mesh are standard values). Therefore, when loading obj files, everything that cannot be stored in a VCG mesh, will be lost.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. The resources of the VCLab team are limited, and so we are asking for your help. If this is a bug and you can still reproduce this error on the last release of PyMeshLab, please reply with all of the information you have about it in order to keep the issue open. If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.