mikedh / trimesh

Python library for loading and using triangular meshes.
https://trimesh.org
MIT License
3k stars 581 forks source link

Breaking change in 3.10.8 causing materials not to load #2059

Open aminya opened 1 year ago

aminya commented 1 year ago

I have a library that uses Trimesh for mesh loading and modification. After I updated Trimesh to the latest version from 3.9.34 to 4.0.0 I noticed that the materials are no longer loaded correctly. They are replaced with material_0.

The issue is that when I reexport an obj file loaded by trimesh using export, it loses its material properties, and instead material_0 is added.

Here's a minimal reproduction of the bug https://github.com/aminya/trimesh-bug

import trimesh

def main():
    """
    Load a obj mesh that has a material and export it back to obj.
    """

    asset_dir = "./trimesh-bug/assets"

    mesh = trimesh.load_mesh(f"{asset_dir}/cube.obj")

    if isinstance(mesh, list):
        raise RuntimeError("Multiple meshes found.")

    # cast Geometry to the more specific Trimesh type
    if not isinstance(mesh, trimesh.Trimesh) and not isinstance(mesh, trimesh.Scene):
        raise RuntimeError(
            "The mesh geometry is not a trimesh.Trimesh or trimesh.Scene."
        )

    obj_content = mesh.export(file_type="obj")
    if not isinstance(obj_content, str):
        raise RuntimeError("The obj_content is not a string.")

    with open(f"{asset_dir}/cube_rexport.obj", "w", encoding="utf-8") as f:
        f.write(obj_content)

if __name__ == "__main__":
    main()

Reexported-mesh

# https://github.com/mikedh/trimesh
mtllib material.mtl
usemtl material_0
v 1.00000000 1.00000000 -1.00000000
v 1.00000000 -1.00000000 -1.00000000
v 1.00000000 1.00000000 1.00000000
v 1.00000000 -1.00000000 1.00000000
v -1.00000000 1.00000000 -1.00000000
v -1.00000000 -1.00000000 -1.00000000
v -1.00000000 1.00000000 1.00000000
v -1.00000000 -1.00000000 1.00000000
f 1 5 7
f 4 3 7
f 8 7 5
f 6 2 4
f 2 1 3
f 6 5 1
f 7 3 1
f 7 8 4
f 5 6 8
f 4 8 6
f 3 4 2
f 1 2 6

Original mesh

mtllib cube.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.125000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl green
s off
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6

After spending an hour trying all the versions by doing a bisect, I found the buggy version: 3.10.8. The changes in this version break the material loading for me compared to 3.10.7:

https://github.com/mikedh/trimesh/compare/3.10.7...3.10.8

Workaround

I have temporarily fixed the issue by setting mesh.export(file_type="obj", include_texture=False) in obj export.

Another option is pinning the version in

[tool.poetry.dependencies]
trimesh = "=3.10.7" # 3.10.8 breaks the material loading resulting in no colours

Do you know if this breaking change was documented anywhere or was it unexpected? Is there a way I can resolve this or get more information about how the changes affect the materials?

mikedh commented 1 year ago

It looks like that corresponds to #1543, which format are you trying to load? Can you share the model in question?

aminya commented 1 year ago

I think among those changes, #1537 could be the issue.

aminya commented 5 months ago

The issue is with this line where it exports the textures even if the uv size is not 2 (introduced in #1537 cc: @clemense)

https://github.com/mikedh/trimesh/blob/7853a5ebae3b35275f4d8d65cbc48bcd3a3c8a40/trimesh/exchange/obj.py#L867

My workaround has been to set include_texture=False when exporting the obj meshes.

I don't know why exporting the texture breaks the mlt file colors causing them to be material_0!

clemense commented 5 months ago

Just to understand better: The initial report states that load_mesh behaves differently but the referenced line above points to the export function. Could you write down an MWE?

aminya commented 5 months ago

The OP was outdated, not matching my latest findings about the bug. I have added a minimal reproduction of the bug in this repository and the OP:

https://github.com/aminya/trimesh-bug

clemense commented 5 months ago

I still don't fully understand the problem, the material property is preserved:

In [1]: import trimesh

In [2]: x = trimesh.load('cube.obj')

In [3]: !cat cube.obj
mtllib cube.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.125000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl green
s off
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6

In [4]: !cat cube.mtl
newmtl green

Ka 0.0000 0.0000 0.0000
Kd 0.0 1.0 0.0
Ks 0.0000 0.0000 0.0000
Tf 0.0000 0.0000 0.0000
d 1
Ns 0

In [5]: _ = x.export('/tmp/test.obj')

In [6]: !cat /tmp/test.obj
# https://github.com/mikedh/trimesh
mtllib material.mtl
usemtl material_0
v 1.00000000 1.00000000 -1.00000000
v 1.00000000 -1.00000000 -1.00000000
v 1.00000000 1.00000000 1.00000000
v 1.00000000 -1.00000000 1.00000000
v -1.00000000 1.00000000 -1.00000000
v -1.00000000 -1.00000000 -1.00000000
v -1.00000000 1.00000000 1.00000000
v -1.00000000 -1.00000000 1.00000000
f 1 5 7
f 4 3 7
f 8 7 5
f 6 2 4
f 2 1 3
f 6 5 1
f 7 3 1
f 7 8 4
f 5 6 8
f 4 8 6
f 3 4 2
f 1 2 6

In [7]: !cat /tmp/material.mtl
# https://github.com/mikedh/trimesh

newmtl material_0
Ka 0.00000000 0.00000000 0.00000000
Kd 0.00000000 1.00000000 0.00000000
Ks 0.00000000 0.00000000 0.00000000
Ns 0.00000000

It's true that vt is not exported. But that's because it's not used. There's no texture.