mikedh / trimesh

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

Difficulty in making a mesh watertight (Human Hand Mesh) #1760

Open LahkarBK opened 1 year ago

LahkarBK commented 1 year ago

Hi great 'Trimesh' community, particularly developers

I have two hand meshes, one for the right hand and one for the left. These meshes are not watertight as they are not enclosed from the distal end (as shown below for right hand where one can see the boundary vertices). image

To close the mesh for the right hand, a surface mesh has been created using the boundary vertices along with a centroid vertex (below is the surface mesh) image

Then, I performed meshA.union(meshB) to create a single mesh out of these two. This beautifully produced a watertight mesh for the right hand (below image)

image

But if I apply the same process for the left hand, the mesh is not watertight. To diagnose what might go wrong, I performed mesh.repair.broken_faces, which gave indices of broken faces. These faces are nothing but the boundary faces highlighted in green in the below image.

image

If I apply mesh.repair.fill_holes, it cannot provide a watertight mesh. Even other available repair commands are not working. I also tried using trimesh.util.concatenate(meshA, meshB) instead of union , but miserably failed.

I cannot also manually repair the mesh either in Meshlab or Blender, because thousands of hand meshes for different subjects.

Please provide a solution. If someone needs the Hand mesh, I can provide.

Thanks

Kiord commented 1 year ago

If the hand meshes for the thousands subjects share the same topology, you can "manually" add a vertex in the centroid of the border vertices and add the faces needed to fill the hole.

Say you have all the indices of the border vertices in the array border_vertex_indices in the loop order

centroid = mesh.vertices[border_vertex_indices].mean(axis=0)
vertices = np.append(vertices, centroid[None, :], axis=0)

new_faces = []
for i in range(len(border_vertex_indices)):
   next_i = i + 1 % len(border_vertex_indices)
   new_faces.append([len(vertices) - 1, border_vertex_indices[i], border_vertex_indices[next_i]])

faces = np.append(faces, new_faces, axis=0)

Of course, this is only possible if the topology is constant, though.