mikedh / trimesh

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

Processing meshes with "holes" flips the inner normals #2082

Open tpank opened 1 year ago

tpank commented 1 year ago

Hi,

when processing meshes with hollow spaces, Trimesh.process(validate=True) behaves unexpectedly (at least to me):

It flips all surface normals pointing outwards. If a mesh contains hollow spaces (so basically submeshes with normals that correctly point inwards), this invalidates the mesh.

If this behaviour is intended, this could be documented in the docstring. Then an additional, separate flag for Trimesh.process to trigger the vertex merging and duplicate triangle removal without flipping the normals would be great. If this behaviour is not intended, I would propose to adapt the trimesh.repair.fix_inversion function to check for inner meshes.

Here is a little example code of the problem:

>>> import trimesh
>>> m1 = trimesh.creation.box((2,2,2)) # Outer mesh
>>> m1.volume
8.0
>>> m2 = trimesh.creation.box((1,1,1)) # Inner mesh (hole with inward pointing normals)
>>> m2.invert()
>>> m2.volume
-1.0
>>> concat = trimesh.util.concatenate((m1,m2))
>>> concat.volume
7.0
>>> concat.process(validate=True)
<trimesh.Trimesh(vertices.shape=(16, 3), faces.shape=(24, 3))>
>>> concat.volume
9.0
tpank commented 1 year ago

This might be a duplicate of https://github.com/mikedh/trimesh/issues/1789

mikedh commented 1 year ago

Yeah definitely a wart at best. My only put is that it seems like it is probably pretty expensive and potentially unreliable to do a mesh_a.contains(mesh_b) query? The points-contains function isn't as reliable as I might hope for since it relies on ray checks and surface normals. Maybe the python-fcl or manifold3d have a nice way of helping with this?

PR's super welcome!