Skip to content

Commit 01e8309

Browse files
committed
Don't convert primitive models into trimeshes on way to manifolds
1 parent 4f35f36 commit 01e8309

File tree

2 files changed

+54
-32
lines changed

2 files changed

+54
-32
lines changed

src/flitter/render/window/models.pyx

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ cdef uint64_t MIX = HASH_UPDATE(HASH_START, HASH_STRING('mix'))
4848
cdef tuple build_arrays_from_trimesh(trimesh_model):
4949
if trimesh_model is None:
5050
return None
51+
vertex_data = np.zeros((len(trimesh_model.vertices), 8), dtype='f4')
52+
vertex_data[:, :3] = trimesh_model.vertices
53+
vertex_data[:, 3:6] = trimesh_model.vertex_normals
5154
if (visual := trimesh_model.visual) is not None and isinstance(visual, trimesh.visual.texture.TextureVisuals) \
5255
and visual.uv is not None and len(visual.uv) == len(trimesh_model.vertices):
53-
vertex_uvs = visual.uv
54-
else:
55-
vertex_uvs = np.zeros((len(trimesh_model.vertices), 2))
56-
vertex_data = np.hstack((trimesh_model.vertices, trimesh_model.vertex_normals, vertex_uvs)).astype('f4', copy=False)
57-
index_data = trimesh_model.faces.astype('i4', copy=False)
56+
vertex_data[:, 6:8] = visual.uv
57+
index_data = np.array(trimesh_model.faces, dtype='i4')
5858
return vertex_data, index_data
5959

6060

@@ -188,6 +188,7 @@ cdef class Model:
188188
if trimesh_model is not None:
189189
trimesh_model._cache.clear()
190190
full_collect = True
191+
logger.trace("Discarded trimesh model for {}", self.name)
191192
if all or 'bounds' not in self.cache:
192193
self.cache = None
193194
elif len(self.cache) > 1:
@@ -224,31 +225,19 @@ cdef class Model:
224225
faces=faces_array, visual=visual, process=False)
225226

226227
cpdef object build_manifold(self):
227-
cdef bint merged=False, filled=False, hull=False
228-
trimesh_model = self.get_trimesh()
229-
if trimesh_model is None:
230-
return None
231-
if not trimesh_model.is_watertight:
232-
trimesh_model = trimesh_model.copy()
233-
trimesh_model.merge_vertices(merge_tex=True, merge_norm=True)
234-
merged = True
235-
if not trimesh_model.is_watertight:
236-
if trimesh_model.fill_holes():
237-
filled = True
238-
else:
239-
trimesh_model = trimesh_model.convex_hull
240-
hull = True
241-
if not trimesh_model.is_volume:
242-
logger.error("Mesh is not a volume: {}", self.name)
228+
cdef tuple arrays = self.get_arrays()
229+
if arrays is None:
243230
return None
244-
elif hull:
245-
logger.warning("Computed convex hull of non-manifold mesh: {}", self.name)
246-
elif filled:
247-
logger.debug("Filled holes in non-manifold mesh: {}", self.name)
248-
elif merged:
249-
logger.trace("Merged vertices of non-manifold mesh: {}", self.name)
250-
return manifold3d.Manifold(mesh=manifold3d.Mesh(vert_properties=np.array(trimesh_model.vertices, dtype='f4'),
251-
tri_verts=np.array(trimesh_model.faces, dtype=np.uint32)))
231+
vertices_array, faces_array = arrays
232+
mesh = manifold3d.Mesh(vert_properties=vertices_array[:, :3].astype('f4'), tri_verts=faces_array.astype('i4'))
233+
cdef bint merged = mesh.merge()
234+
manifold = manifold3d.Manifold(mesh=mesh)
235+
if manifold.status() == manifold3d.Error.NoError:
236+
if merged:
237+
logger.trace("Merged vertices of non-manifold mesh: {}", self.name)
238+
return manifold
239+
logger.error("Mesh is not a volume: {}", self.name)
240+
return None
252241

253242
cpdef void add_dependent(self, Model model):
254243
if self.dependents is None:
@@ -1165,6 +1154,13 @@ cdef class PrimitiveModel(Model):
11651154
cpdef void check_for_changes(self):
11661155
pass
11671156

1157+
cpdef object build_manifold(self):
1158+
cdef tuple arrays = self.get_arrays()
1159+
vertices_array, faces_array = arrays
1160+
mesh = manifold3d.Mesh(vert_properties=vertices_array[:, :3], tri_verts=faces_array)
1161+
mesh.merge()
1162+
return manifold3d.Manifold(mesh=mesh)
1163+
11681164

11691165
cdef class Box(PrimitiveModel):
11701166
cdef str uv_map
@@ -1550,6 +1546,33 @@ cdef class ExternalModel(Model):
15501546
cpdef object build_trimesh(self):
15511547
return self.cache_path.read_trimesh_model()
15521548

1549+
cpdef object build_manifold(self):
1550+
cdef bint merged=False, filled=False, hull=False
1551+
trimesh_model = self.get_trimesh()
1552+
if trimesh_model is None:
1553+
return None
1554+
if not trimesh_model.is_watertight:
1555+
trimesh_model = trimesh_model.copy()
1556+
trimesh_model.merge_vertices(merge_tex=True, merge_norm=True)
1557+
merged = True
1558+
if not trimesh_model.is_watertight:
1559+
if trimesh_model.fill_holes():
1560+
filled = True
1561+
else:
1562+
trimesh_model = trimesh_model.convex_hull
1563+
hull = True
1564+
if not trimesh_model.is_volume:
1565+
logger.error("Mesh is not a volume: {}", self.name)
1566+
return None
1567+
elif hull:
1568+
logger.warning("Computed convex hull of non-manifold mesh: {}", self.name)
1569+
elif filled:
1570+
logger.debug("Filled holes in non-manifold mesh: {}", self.name)
1571+
elif merged:
1572+
logger.trace("Merged vertices of non-manifold mesh: {}", self.name)
1573+
return manifold3d.Manifold(mesh=manifold3d.Mesh(vert_properties=np.array(trimesh_model.vertices, dtype='f4'),
1574+
tri_verts=np.array(trimesh_model.faces, dtype=np.uint32)))
1575+
15531576

15541577
cdef class VectorModel(Model):
15551578
cdef Vector vertices

tests/test_models.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,8 @@ def is_manifold(self):
132132
def check_for_changes(self):
133133
pass
134134

135-
def build_trimesh(self):
136-
return trimesh.Trimesh(vertices=[[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]],
137-
faces=[[0, 1, 2], [2, 3, 0]])
135+
def build_arrays(self):
136+
return np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], dtype='f4'), np.array([[0, 1, 2], [2, 3, 0]], dtype='i4')
138137

139138

140139
class TestSubclassing(utils.TestCase):

0 commit comments

Comments
 (0)