@@ -9,7 +9,7 @@ use bevy_render::{
9
9
} ;
10
10
use bevy_utils:: HashMap ;
11
11
use bitvec:: { order:: Lsb0 , vec:: BitVec , view:: BitView } ;
12
- use core:: iter;
12
+ use core:: { iter, ops :: Range } ;
13
13
use half:: f16;
14
14
use itertools:: Itertools ;
15
15
use meshopt:: {
@@ -105,20 +105,22 @@ impl MeshletMesh {
105
105
let mut vertex_locks = vec ! [ false ; vertices. vertex_count] ;
106
106
107
107
// Build further LODs
108
- let mut simplification_queue = Vec :: from_iter ( 0 ..meshlets. len ( ) ) ;
109
- let mut retry_queue = Vec :: new ( ) ;
108
+ let mut simplification_queue = 0 ..meshlets. len ( ) ;
110
109
while simplification_queue. len ( ) > 1 {
111
110
// For each meshlet build a list of connected meshlets (meshlets that share a vertex)
112
111
let connected_meshlets_per_meshlet = find_connected_meshlets (
113
- & simplification_queue,
112
+ simplification_queue. clone ( ) ,
114
113
& meshlets,
115
114
& position_only_vertex_remap,
116
115
position_only_vertex_count,
117
116
) ;
118
117
119
118
// Group meshlets into roughly groups of size TARGET_MESHLETS_PER_GROUP,
120
119
// grouping meshlets with a high number of shared vertices
121
- let groups = group_meshlets ( & connected_meshlets_per_meshlet, & simplification_queue) ;
120
+ let groups = group_meshlets (
121
+ & connected_meshlets_per_meshlet,
122
+ simplification_queue. clone ( ) ,
123
+ ) ;
122
124
123
125
// Lock borders between groups to prevent cracks when simplifying
124
126
lock_group_borders (
@@ -131,9 +133,8 @@ impl MeshletMesh {
131
133
132
134
let next_lod_start = meshlets. len ( ) ;
133
135
for group_meshlets in groups. into_iter ( ) {
134
- // If the group only has a single meshlet, we can't simplify it well, so retry later
136
+ // If the group only has a single meshlet we can't simplify it
135
137
if group_meshlets. len ( ) == 1 {
136
- retry_queue. push ( group_meshlets[ 0 ] ) ;
137
138
continue ;
138
139
}
139
140
@@ -146,8 +147,7 @@ impl MeshletMesh {
146
147
vertex_stride,
147
148
& vertex_locks,
148
149
) else {
149
- // Couldn't simplify the group enough, retry its meshlets later
150
- retry_queue. extend_from_slice ( & group_meshlets) ;
150
+ // Couldn't simplify the group enough
151
151
continue ;
152
152
} ;
153
153
@@ -187,12 +187,8 @@ impl MeshletMesh {
187
187
) ;
188
188
}
189
189
190
- // Set simplification queue to the list of newly created (and retrying) meshlets
191
- simplification_queue. clear ( ) ;
192
- simplification_queue. extend ( next_lod_start..meshlets. len ( ) ) ;
193
- if !simplification_queue. is_empty ( ) {
194
- simplification_queue. append ( & mut retry_queue) ;
195
- }
190
+ // Set simplification queue to the list of newly created meshlets
191
+ simplification_queue = next_lod_start..meshlets. len ( ) ;
196
192
}
197
193
198
194
// Copy vertex attributes per meshlet and compress
@@ -252,50 +248,45 @@ fn compute_meshlets(indices: &[u32], vertices: &VertexDataAdapter) -> Meshlets {
252
248
}
253
249
254
250
fn find_connected_meshlets (
255
- simplification_queue : & [ usize ] ,
251
+ simplification_queue : Range < usize > ,
256
252
meshlets : & Meshlets ,
257
253
position_only_vertex_remap : & [ u32 ] ,
258
254
position_only_vertex_count : usize ,
259
255
) -> Vec < Vec < ( usize , usize ) > > {
260
256
// For each vertex, build a list of all meshlets that use it
261
257
let mut vertices_to_meshlets = vec ! [ Vec :: new( ) ; position_only_vertex_count] ;
262
- for ( meshlet_queue_id , meshlet_id) in simplification_queue. iter ( ) . enumerate ( ) {
263
- let meshlet = meshlets. get ( * meshlet_id) ;
258
+ for meshlet_id in simplification_queue. clone ( ) {
259
+ let meshlet = meshlets. get ( meshlet_id) ;
264
260
for index in meshlet. triangles {
265
261
let vertex_id = position_only_vertex_remap[ meshlet. vertices [ * index as usize ] as usize ] ;
266
262
let vertex_to_meshlets = & mut vertices_to_meshlets[ vertex_id as usize ] ;
267
263
// Meshlets are added in order, so we can just check the last element to deduplicate,
268
264
// in the case of two triangles sharing the same vertex within a single meshlet
269
- if vertex_to_meshlets. last ( ) != Some ( & meshlet_queue_id ) {
270
- vertex_to_meshlets. push ( meshlet_queue_id ) ;
265
+ if vertex_to_meshlets. last ( ) != Some ( & meshlet_id ) {
266
+ vertex_to_meshlets. push ( meshlet_id ) ;
271
267
}
272
268
}
273
269
}
274
270
275
271
// For each meshlet pair, count how many vertices they share
276
272
let mut meshlet_pair_to_shared_vertex_count = <HashMap < _ , _ > >:: default ( ) ;
277
273
for vertex_meshlet_ids in vertices_to_meshlets {
278
- for ( meshlet_queue_id1, meshlet_queue_id2) in
279
- vertex_meshlet_ids. into_iter ( ) . tuple_combinations ( )
280
- {
274
+ for ( meshlet_id1, meshlet_id2) in vertex_meshlet_ids. into_iter ( ) . tuple_combinations ( ) {
281
275
let count = meshlet_pair_to_shared_vertex_count
282
- . entry ( (
283
- meshlet_queue_id1. min ( meshlet_queue_id2) ,
284
- meshlet_queue_id1. max ( meshlet_queue_id2) ,
285
- ) )
276
+ . entry ( ( meshlet_id1. min ( meshlet_id2) , meshlet_id1. max ( meshlet_id2) ) )
286
277
. or_insert ( 0 ) ;
287
278
* count += 1 ;
288
279
}
289
280
}
290
281
291
282
// For each meshlet, gather all other meshlets that share at least one vertex along with their shared vertex count
292
283
let mut connected_meshlets_per_meshlet = vec ! [ Vec :: new( ) ; simplification_queue. len( ) ] ;
293
- for ( ( meshlet_queue_id1, meshlet_queue_id2) , shared_count) in
294
- meshlet_pair_to_shared_vertex_count
295
- {
284
+ for ( ( meshlet_id1, meshlet_id2) , shared_vertex_count) in meshlet_pair_to_shared_vertex_count {
296
285
// We record both id1->id2 and id2->id1 as adjacency is symmetrical
297
- connected_meshlets_per_meshlet[ meshlet_queue_id1] . push ( ( meshlet_queue_id2, shared_count) ) ;
298
- connected_meshlets_per_meshlet[ meshlet_queue_id2] . push ( ( meshlet_queue_id1, shared_count) ) ;
286
+ connected_meshlets_per_meshlet[ meshlet_id1 - simplification_queue. start ]
287
+ . push ( ( meshlet_id2, shared_vertex_count) ) ;
288
+ connected_meshlets_per_meshlet[ meshlet_id2 - simplification_queue. start ]
289
+ . push ( ( meshlet_id1, shared_vertex_count) ) ;
299
290
}
300
291
301
292
// The order of meshlets depends on hash traversal order; to produce deterministic results, sort them
@@ -309,15 +300,15 @@ fn find_connected_meshlets(
309
300
// METIS manual: https://github.com/KarypisLab/METIS/blob/e0f1b88b8efcb24ffa0ec55eabb78fbe61e58ae7/manual/manual.pdf
310
301
fn group_meshlets (
311
302
connected_meshlets_per_meshlet : & [ Vec < ( usize , usize ) > ] ,
312
- simplification_queue : & [ usize ] ,
303
+ simplification_queue : Range < usize > ,
313
304
) -> Vec < SmallVec < [ usize ; TARGET_MESHLETS_PER_GROUP ] > > {
314
305
let mut xadj = Vec :: with_capacity ( simplification_queue. len ( ) + 1 ) ;
315
306
let mut adjncy = Vec :: new ( ) ;
316
307
let mut adjwgt = Vec :: new ( ) ;
317
308
for connected_meshlets in connected_meshlets_per_meshlet {
318
309
xadj. push ( adjncy. len ( ) as i32 ) ;
319
- for ( connected_meshlet_queue_id , shared_vertex_count) in connected_meshlets {
320
- adjncy. push ( * connected_meshlet_queue_id as i32 ) ;
310
+ for ( connected_meshlet_id , shared_vertex_count) in connected_meshlets {
311
+ adjncy. push ( ( connected_meshlet_id - simplification_queue . start ) as i32 ) ;
321
312
adjwgt. push ( * shared_vertex_count as i32 ) ;
322
313
// TODO: Additional weight based on meshlet spatial proximity
323
314
}
@@ -336,8 +327,8 @@ fn group_meshlets(
336
327
. unwrap ( ) ;
337
328
338
329
let mut groups = vec ! [ SmallVec :: new( ) ; partition_count] ;
339
- for ( meshlet_queue_id , meshlet_group) in group_per_meshlet. into_iter ( ) . enumerate ( ) {
340
- groups[ meshlet_group as usize ] . push ( simplification_queue[ meshlet_queue_id ] ) ;
330
+ for ( i , meshlet_group) in group_per_meshlet. into_iter ( ) . enumerate ( ) {
331
+ groups[ meshlet_group as usize ] . push ( i + simplification_queue. start ) ;
341
332
}
342
333
groups
343
334
}
0 commit comments