kleinhe
init
c3d0293
import trimesh
import torch
import numpy as np
def subdivide(vertices, faces, attributes=None, face_index=None):
"""
Subdivide a mesh into smaller triangles.
Note that if `face_index` is passed, only those faces will
be subdivided and their neighbors won't be modified making
the mesh no longer "watertight."
Parameters
----------
vertices : (n, 3) float
Vertices in space
faces : (n, 3) int
Indexes of vertices which make up triangular faces
attributes: (n, d) float
vertices attributes
face_index : faces to subdivide.
if None: all faces of mesh will be subdivided
if (n,) int array of indices: only specified faces
Returns
----------
new_vertices : (n, 3) float
Vertices in space
new_faces : (n, 3) int
Remeshed faces
"""
if face_index is None:
face_index = np.arange(len(faces))
else:
face_index = np.asanyarray(face_index)
# the (c,3) int set of vertex indices
faces = faces[face_index]
# the (c, 3, 3) float set of points in the triangles
triangles = vertices[faces]
# the 3 midpoints of each triangle edge
# stacked to a (3 * c, 3) float
mid = np.vstack([triangles[:, g, :].mean(axis=1) for g in [[0, 1], [1, 2], [2, 0]]])
# for adjacent faces we are going to be generating
# the same midpoint twice so merge them here
mid_idx = (np.arange(len(face_index) * 3)).reshape((3, -1)).T
unique, inverse = trimesh.grouping.unique_rows(mid)
mid = mid[unique]
mid_idx = inverse[mid_idx] + len(vertices)
# the new faces with correct winding
f = np.column_stack([faces[:, 0],
mid_idx[:, 0],
mid_idx[:, 2],
mid_idx[:, 0],
faces[:, 1],
mid_idx[:, 1],
mid_idx[:, 2],
mid_idx[:, 1],
faces[:, 2],
mid_idx[:, 0],
mid_idx[:, 1],
mid_idx[:, 2]]).reshape((-1, 3))
# add the 3 new faces per old face
new_faces = np.vstack((faces, f[len(face_index):]))
# replace the old face with a smaller face
new_faces[face_index] = f[:len(face_index)]
new_vertices = np.vstack((vertices, mid))
if attributes is not None:
tri_att = attributes[faces]
mid_att = np.vstack([tri_att[:, g, :].mean(axis=1) for g in [[0, 1], [1, 2], [2, 0]]])
mid_att = mid_att[unique]
new_attributes = np.vstack((attributes, mid_att))
return new_vertices, new_faces, new_attributes, unique
return new_vertices, new_faces, unique
def subdivide_inorder(vertices, faces, unique):
triangles = vertices[faces]
mid = torch.vstack([triangles[:, g, :].mean(1) for g in [[0, 1], [1, 2], [2, 0]]])
mid = mid[unique]
new_vertices = torch.vstack((vertices, mid))
return new_vertices