Issue with exporting several materials from a scene
Hello and thanks for this amazing library. I am trying to convert GLB to OBJ. It works perfect when there is only one geometry in the scene.
The problems appears when the scene has more than one geometries. In that case, it stores only the latest material in the material_0.mtl. I also tried to load an OBJ and export it again as OBJ (so that I can check if the issue is the GLB to OBJ conversion) and the output was again wrong. I am not sure if this a bug or that exporting multiply materials is not supported.
I went a little deeper in the code and I saw that in the export_obj function, the resolver.write is outside of the loop for each mesh. Therefore, it makes sense that stores only the last material (not sure for that, I may have got it all wrong).
In any case, this is how I load and export the OBJ:
scene = trimesh.load(glb_kitchen)
scene .export(file_type="obj",
#resolver = trimesh.resolvers.nearby_names(save_path),
write_texture = True,
file_obj = os.path.join(save_path,save_name),
include_color=True,
include_texture=True)
Thanks!
I am also running into the same / similar problem. Here's an example mesh file (it contains two materials, one textured, one non-textured): original-40.zip
Doing
s = trimesh.load('original-40.obj')
s.export('/tmp/test.obj')
will lose the non-textured material information. (resulting files: material_0.jpeg material_0.mtl test.obj)
It seems that to ensure that both material files are exported, the following three things need to happen:
-
Pushing the material writer https://github.com/mikedh/trimesh/blob/e9c6327230b64f176e9e176f58a0f4a3d0334620/trimesh/exchange/obj.py#L905 into the mesh loop as suggested by @stasinak
-
Ensuring different materials name (otherwise files will be overwritten during export):
list(s.geometry.values())[0].visual.material.name = 'material_00'
list(s.geometry.values())[1].visual.material.name = 'material_01'
(is there a more elegant way?)
- Removing the recently introduced
and len(np.shape(getattr(mesh.visual, 'uv', None))) == 2: https://github.com/mikedh/trimesh/blob/e9c6327230b64f176e9e176f58a0f4a3d0334620/trimesh/exchange/obj.py#L854 Otherwise the non-textured material won't be written.
After doing this the output is as expected (two mtl files, one texture image, and obj). There's still the problem of the result not being exactly the same:
trimesh.load('/tmp/test.obj')
WARNING obj.py:197 index failed on UV coordinates, skipping!
DEBUG load.py:226 loaded <trimesh.Scene(len(geometry)=2)> using load_obj
But I'm not sure if this is related.
@mikedh Any advice on this? I'm sure I'm missing / misinterpreting something here.