@@ -146,6 +146,107 @@ function Base.merge(meshes::AbstractVector{T}) where T <: MetaMesh
146
146
return MetaMesh (big_mesh, big_meta)
147
147
end
148
148
149
+ # TODO : naming
150
+ # synchronize_vertex_attributes
151
+ # merge_vertex_(attribute)_indices
152
+ # convert(Face, MultiFace)
153
+ # ...
154
+ function merge_vertex_indices (mesh)
155
+ attribs, fs, views = merge_vertex_indices (
156
+ vertex_attributes (mesh), faces (mesh), mesh. views)
157
+
158
+ return Mesh (attribs, fs, views)
159
+ end
160
+
161
+ function merge_vertex_indices (
162
+ attribs:: NamedTuple{Names} ,
163
+ faces:: AbstractVector{<: MultiFace{N, T, FT, Names}} ,
164
+ views:: Vector{UnitRange}
165
+ ) where {Names, N, T, FT}
166
+
167
+ # Note: typing checks for matching Names
168
+
169
+ if isempty (views)
170
+ new_faces, vertex_map = merge_vertex_indices (faces)
171
+ new_attribs = ntuple (n -> attribs[n][vertex_map[n]], length (Names))
172
+ return NamedTuple {Names} (new_attribs), new_faces, views
173
+ end
174
+
175
+ new_attribs = NamedTuple ((Pair (k, similar (v, 0 )) for (k, v) in pairs (attribs)))
176
+ new_faces = similar (faces, FT, 0 )
177
+ new_views = UnitRange[]
178
+
179
+ for idxs in views
180
+ # TODO : this depends on T in Face (1 based -> 1, 0 based -> 0)
181
+ vertex_index_counter = T (length (new_attribs[1 ]) + 1 )
182
+
183
+ # Generate new face from current view, with the first vertex_index
184
+ # corresponding to the first vertex attribute added in this iteration
185
+ face_view = view (faces, idxs)
186
+ new_faces_in_view, vertex_map = merge_vertex_indices (face_view, vertex_index_counter)
187
+
188
+ # update vertex attributes
189
+ for (name, indices) in pairs (vertex_map)
190
+ append! (new_attribs[name], view (attribs[name], indices))
191
+ end
192
+
193
+ # add new faces and new view
194
+ start = length (new_faces) + 1
195
+ append! (new_faces, new_faces_in_view)
196
+ append! (new_views, start: length (new_faces))
197
+ end
198
+
199
+ return new_attribs, new_faces, new_views
200
+ end
201
+
202
+ function merge_vertex_indices (
203
+ faces:: AbstractVector{<: MultiFace{N, T, FT, Names, N_Attrib}} ,
204
+ vertex_index_counter = T (1 )
205
+ ) where {N, T, FT <: AbstractFace{N, T} , Names, N_Attrib}
206
+
207
+ N_faces = length (faces)
208
+
209
+ # maps a combination of old indices in MultiFace to a new vertex_index
210
+ vertex_index_map = Dict {NTuple{N_Attrib, T}, T} ()
211
+
212
+ # Faces after conversion
213
+ new_faces = sizehint! (FT[], N_faces)
214
+
215
+ # indices that remap attributes
216
+ attribute_indices = ntuple (n -> sizehint! (UInt32[], N_faces), N_Attrib)
217
+
218
+ # keep track of the remmaped indices for one vertex so we don't have to
219
+ # query the dict twice
220
+ temp = zeros (N)
221
+
222
+ for multi_face in faces
223
+
224
+ for i in 1 : N
225
+ # get the i-th set of vertex indices from multi_face, i.e.
226
+ # (multi_face.position_index[i], multi_face.normal_index[i], ...)
227
+ vertex = ntuple (n -> multi_face. faces[n][i], N_Attrib)
228
+
229
+ # if the vertex exists, get it's index
230
+ # otherwise register it with the next available vertex index
231
+ temp[i] = get! (vertex_index_map, vertex) do
232
+ vertex_index_counter += 1
233
+ push! .(attribute_indices, vertex)
234
+ return vertex_index_counter - 1
235
+ end
236
+ end
237
+
238
+ # generate new face
239
+ push! (new_faces, FT (temp))
240
+ end
241
+
242
+ # in case we are reserving more than needed
243
+ sizehint! (new_faces, length (new_faces))
244
+
245
+ return new_faces, attribute_indices
246
+ end
247
+
248
+
249
+
149
250
150
251
function map_coordinates (f, mesh:: Mesh )
151
252
result = copy (mesh)
0 commit comments