trimesh
trimesh copied to clipboard
Inconsistency in mesh loading after 4.6.0
I noticed that after version 4.6.0 meshes are loaded differently from the previous versions introducing a breaking change. I noticed in the change logs that some big changes has been made to the i/o modules, but I'm wondering if the following behaviour is expected.
Here is the script I used:
import tempfile
import numpy as np
import open3d as o3d
import trimesh
mesh_o3d = o3d.geometry.TriangleMesh.create_sphere()
mesh_o3d.compute_vertex_normals()
mesh_o3d.compute_triangle_normals()
vertices_1 = np.asarray(mesh_o3d.vertices)
triangles_1 = np.asarray(mesh_o3d.triangles)
vertices_normals_1 = np.asarray(mesh_o3d.vertex_normals)
triangles_normals_1 = np.asarray(mesh_o3d.triangle_normals)
mesh_1 = trimesh.Trimesh()
mesh_1.vertices = vertices_1
mesh_1.faces = triangles_1
mesh_1.vertex_normals = vertices_normals_1
mesh_1.face_normals = triangles_normals_1
with tempfile.NamedTemporaryFile(suffix=".ply") as tmp_file:
mesh_1.export(tmp_file.name)
mesh_2 = trimesh.load(tmp_file.name)
# mesh_2 = trimesh.load(tmp_file.name, force="mesh")
vertices_2 = np.asarray(mesh_2.vertices)
triangles_2 = np.asarray(mesh_2.faces)
vertices_normals_2 = np.asarray(mesh_2.vertex_normals)
triangles_normals_2 = np.asarray(mesh_2.face_normals)
assert np.allclose(vertices_1, vertices_2)
assert np.allclose(triangles_1, triangles_2)
assert np.allclose(vertices_normals_1, vertices_normals_2)
assert np.allclose(triangles_normals_1, triangles_normals_2)
It creates a sphere with open3d, then it converts to trimesh and after writing and loading the same mesh I obtain different meshes.
If I use trimesh.load(tmp_file.name,) it always works.
If I use trimesh.load(tmp_file.name, force="mesh") it only works with trimesh<4.6. Specifically only the vertices normals are loaded incorrectly, the other things are ok.
Hey, yeah there was a major refactor of the loading system, and the full details are in https://github.com/mikedh/trimesh/pull/2241
The recommended new usage is trimesh.load_mesh(...) which generally the same as force=mesh. Although in order to always return a mesh it may have to call trimesh.util.concatenate, which may be dropping the vertex normals depending on the inputs. PR's with tests would be super welcome to make concatenate more consistent!
I think the problem is related to the fact that the method copy is called (inside trimesh.util.concatenate) and it copies only vertices and faces but not the normals.