2
2
#include " meshoptimizer.h"
3
3
4
4
#include < assert.h>
5
+ #include < math.h>
5
6
#include < string.h>
6
7
7
8
namespace meshopt
8
9
{
9
10
10
- static const unsigned int kGroupSizeBias = 3 ;
11
-
12
11
struct ClusterAdjacency
13
12
{
14
13
unsigned int * offsets;
@@ -264,12 +263,14 @@ static unsigned int countShared(const ClusterGroup* groups, int group1, int grou
264
263
return total;
265
264
}
266
265
267
- static int pickGroupToMerge (const ClusterGroup* groups, int id, const ClusterAdjacency& adjacency, size_t max_group_size )
266
+ static int pickGroupToMerge (const ClusterGroup* groups, int id, const ClusterAdjacency& adjacency, size_t max_partition_size )
268
267
{
269
268
assert (groups[id].size > 0 );
270
269
270
+ float group_rsqrt = 1 .f / sqrtf (float (int (groups[id].vertices )));
271
+
271
272
int best_group = -1 ;
272
- unsigned int best_score = 0 ;
273
+ float best_score = 0 ;
273
274
274
275
for (int ci = id; ci >= 0 ; ci = groups[ci].next )
275
276
{
@@ -280,13 +281,14 @@ static int pickGroupToMerge(const ClusterGroup* groups, int id, const ClusterAdj
280
281
continue ;
281
282
282
283
assert (groups[other].size > 0 );
283
- if (groups[id].size + groups[other].size > max_group_size )
284
+ if (groups[id].size + groups[other].size > max_partition_size )
284
285
continue ;
285
286
286
- unsigned int score = countShared (groups, id, other, adjacency);
287
+ unsigned int shared = countShared (groups, id, other, adjacency);
288
+ float other_rsqrt = 1 .f / sqrtf (float (int (groups[other].vertices )));
287
289
288
- // favor smaller target groups
289
- score += ( unsigned (max_group_size) - groups[other]. size ) * kGroupSizeBias ;
290
+ // normalize shared count by the expected boundary of each group (+ keeps scoring symmetric)
291
+ float score = float ( int (shared) ) * (group_rsqrt + other_rsqrt) ;
290
292
291
293
if (score > best_score)
292
294
{
@@ -307,6 +309,8 @@ size_t meshopt_partitionClusters(unsigned int* destination, const unsigned int*
307
309
308
310
assert (target_partition_size > 0 );
309
311
312
+ size_t max_partition_size = target_partition_size + target_partition_size * 3 / 8 ;
313
+
310
314
meshopt_Allocator allocator;
311
315
312
316
unsigned char * used = allocator.allocate <unsigned char >(vertex_count);
@@ -318,6 +322,8 @@ size_t meshopt_partitionClusters(unsigned int* destination, const unsigned int*
318
322
319
323
for (size_t i = 0 ; i < cluster_count; ++i)
320
324
{
325
+ assert (cluster_index_counts[i] > 0 );
326
+
321
327
cluster_offsets[i] = cluster_nextoffset;
322
328
cluster_nextoffset += cluster_index_counts[i];
323
329
}
@@ -369,7 +375,7 @@ size_t meshopt_partitionClusters(unsigned int* destination, const unsigned int*
369
375
if (groups[top.id ].size >= target_partition_size)
370
376
continue ;
371
377
372
- int best_group = pickGroupToMerge (groups, top.id , adjacency, target_partition_size + target_partition_size / 2 );
378
+ int best_group = pickGroupToMerge (groups, top.id , adjacency, max_partition_size );
373
379
374
380
// we can't grow the group any more, emit as is
375
381
if (best_group == -1 )
@@ -391,7 +397,7 @@ size_t meshopt_partitionClusters(unsigned int* destination, const unsigned int*
391
397
// update group sizes; note, the vertex update is an approximation which avoids recomputing the true size via countTotal
392
398
groups[top.id ].size += groups[best_group].size ;
393
399
groups[top.id ].vertices += groups[best_group].vertices ;
394
- groups[top.id ].vertices -= shared;
400
+ groups[top.id ].vertices = (groups[top. id ]. vertices > shared) ? groups[top. id ]. vertices - shared : 1 ;
395
401
396
402
groups[best_group].size = 0 ;
397
403
groups[best_group].vertices = 0 ;
0 commit comments