@@ -217,12 +217,25 @@ struct Cone
217
217
float nx, ny, nz;
218
218
};
219
219
220
- static float getMeshletScore (float distance2 , float spread , float cone_weight, float expected_radius )
220
+ static float getDistance (float dx , float dy , float dz, bool aa )
221
221
{
222
+ if (!aa)
223
+ return sqrtf (dx * dx + dy * dy + dz * dz);
224
+
225
+ float rx = fabsf (dx), ry = fabsf (dy), rz = fabsf (dz);
226
+ float rxy = rx >= ry ? rx : ry;
227
+ return rxy >= rz ? rxy : rz;
228
+ }
229
+
230
+ static float getMeshletScore (float distance, float spread, float cone_weight, float expected_radius)
231
+ {
232
+ if (cone_weight < 0 )
233
+ return 1 + distance / expected_radius;
234
+
222
235
float cone = 1 .f - spread * cone_weight;
223
236
float cone_clamped = cone < 1e-3f ? 1e-3f : cone;
224
237
225
- return (1 + sqrtf (distance2) / expected_radius * (1 - cone_weight)) * cone_clamped;
238
+ return (1 + distance / expected_radius * (1 - cone_weight)) * cone_clamped;
226
239
}
227
240
228
241
static Cone getMeshletCone (const Cone& acc, unsigned int triangle_count)
@@ -296,7 +309,7 @@ static void finishMeshlet(meshopt_Meshlet& meshlet, unsigned char* meshlet_trian
296
309
meshlet_triangles[offset++] = 0 ;
297
310
}
298
311
299
- static bool appendMeshlet (meshopt_Meshlet& meshlet, unsigned int a, unsigned int b, unsigned int c, unsigned char * used, meshopt_Meshlet* meshlets, unsigned int * meshlet_vertices, unsigned char * meshlet_triangles, size_t meshlet_offset, size_t max_vertices, size_t max_triangles)
312
+ static bool appendMeshlet (meshopt_Meshlet& meshlet, unsigned int a, unsigned int b, unsigned int c, unsigned char * used, meshopt_Meshlet* meshlets, unsigned int * meshlet_vertices, unsigned char * meshlet_triangles, size_t meshlet_offset, size_t max_vertices, size_t max_triangles, bool split = false )
300
313
{
301
314
unsigned char & av = used[a];
302
315
unsigned char & bv = used[b];
@@ -306,7 +319,7 @@ static bool appendMeshlet(meshopt_Meshlet& meshlet, unsigned int a, unsigned int
306
319
307
320
int used_extra = (av == 0xff ) + (bv == 0xff ) + (cv == 0xff );
308
321
309
- if (meshlet.vertex_count + used_extra > max_vertices || meshlet.triangle_count >= max_triangles)
322
+ if (meshlet.vertex_count + used_extra > max_vertices || meshlet.triangle_count >= max_triangles || split )
310
323
{
311
324
meshlets[meshlet_offset] = meshlet;
312
325
@@ -396,14 +409,11 @@ static unsigned int getNeighborTriangle(const meshopt_Meshlet& meshlet, const Co
396
409
{
397
410
const Cone& tri_cone = triangles[triangle];
398
411
399
- float distance2 =
400
- (tri_cone.px - meshlet_cone->px ) * (tri_cone.px - meshlet_cone->px ) +
401
- (tri_cone.py - meshlet_cone->py ) * (tri_cone.py - meshlet_cone->py ) +
402
- (tri_cone.pz - meshlet_cone->pz ) * (tri_cone.pz - meshlet_cone->pz );
403
-
412
+ float dx = tri_cone.px - meshlet_cone->px , dy = tri_cone.py - meshlet_cone->py , dz = tri_cone.pz - meshlet_cone->pz ;
413
+ float distance = getDistance (dx, dy, dz, cone_weight < 0 );
404
414
float spread = tri_cone.nx * meshlet_cone->nx + tri_cone.ny * meshlet_cone->ny + tri_cone.nz * meshlet_cone->nz ;
405
415
406
- score = getMeshletScore (distance2 , spread, cone_weight, meshlet_expected_radius);
416
+ score = getMeshletScore (distance , spread, cone_weight, meshlet_expected_radius);
407
417
}
408
418
else
409
419
{
@@ -533,7 +543,7 @@ static size_t kdtreeBuild(size_t offset, KDNode* nodes, size_t node_count, const
533
543
return kdtreeBuild (next_offset, nodes, node_count, points, stride, indices + middle, count - middle, leaf_size);
534
544
}
535
545
536
- static void kdtreeNearest (KDNode* nodes, unsigned int root, const float * points, size_t stride, const unsigned char * emitted_flags, const float * position, unsigned int & result, float & limit)
546
+ static void kdtreeNearest (KDNode* nodes, unsigned int root, const float * points, size_t stride, const unsigned char * emitted_flags, const float * position, bool aa, unsigned int & result, float & limit)
537
547
{
538
548
const KDNode& node = nodes[root];
539
549
@@ -549,11 +559,8 @@ static void kdtreeNearest(KDNode* nodes, unsigned int root, const float* points,
549
559
550
560
const float * point = points + index * stride;
551
561
552
- float distance2 =
553
- (point[0 ] - position[0 ]) * (point[0 ] - position[0 ]) +
554
- (point[1 ] - position[1 ]) * (point[1 ] - position[1 ]) +
555
- (point[2 ] - position[2 ]) * (point[2 ] - position[2 ]);
556
- float distance = sqrtf (distance2);
562
+ float dx = point[0 ] - position[0 ], dy = point[1 ] - position[1 ], dz = point[2 ] - position[2 ];
563
+ float distance = getDistance (dx, dy, dz, aa);
557
564
558
565
if (distance < limit)
559
566
{
@@ -569,11 +576,11 @@ static void kdtreeNearest(KDNode* nodes, unsigned int root, const float* points,
569
576
unsigned int first = (delta <= 0 ) ? 0 : node.children ;
570
577
unsigned int second = first ^ node.children ;
571
578
572
- kdtreeNearest (nodes, root + 1 + first, points, stride, emitted_flags, position, result, limit);
579
+ kdtreeNearest (nodes, root + 1 + first, points, stride, emitted_flags, position, aa, result, limit);
573
580
574
581
// only process the other node if it can have a match based on closest distance so far
575
582
if (fabsf (delta) <= limit)
576
- kdtreeNearest (nodes, root + 1 + second, points, stride, emitted_flags, position, result, limit);
583
+ kdtreeNearest (nodes, root + 1 + second, points, stride, emitted_flags, position, aa, result, limit);
577
584
}
578
585
}
579
586
@@ -601,7 +608,7 @@ size_t meshopt_buildMeshletsBound(size_t index_count, size_t max_vertices, size_
601
608
return meshlet_limit_vertices > meshlet_limit_triangles ? meshlet_limit_vertices : meshlet_limit_triangles;
602
609
}
603
610
604
- size_t meshopt_buildMeshlets (meshopt_Meshlet* meshlets, unsigned int * meshlet_vertices, unsigned char * meshlet_triangles, const unsigned int * indices, size_t index_count, const float * vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t max_vertices, size_t max_triangles, float cone_weight)
611
+ size_t meshopt_buildMeshletsFlex (meshopt_Meshlet* meshlets, unsigned int * meshlet_vertices, unsigned char * meshlet_triangles, const unsigned int * indices, size_t index_count, const float * vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t max_vertices, size_t min_triangles, size_t max_triangles, float cone_weight, float split_factor )
605
612
{
606
613
using namespace meshopt ;
607
614
@@ -610,10 +617,11 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve
610
617
assert (vertex_positions_stride % sizeof (float ) == 0 );
611
618
612
619
assert (max_vertices >= 3 && max_vertices <= kMeshletMaxVertices );
613
- assert (max_triangles >= 1 && max_triangles <= kMeshletMaxTriangles );
614
- assert (max_triangles % 4 == 0 ); // ensures the caller will compute output space properly as index data is 4b aligned
620
+ assert (min_triangles >= 1 && min_triangles <= max_triangles && max_triangles <= kMeshletMaxTriangles );
621
+ assert (min_triangles % 4 == 0 && max_triangles % 4 == 0 ); // ensures the caller will compute output space properly as index data is 4b aligned
615
622
616
- assert (cone_weight >= 0 && cone_weight <= 1 );
623
+ assert (cone_weight <= 1 ); // negative cone weight switches metric to optimize for axis-aligned meshlets
624
+ assert (split_factor >= 0 );
617
625
618
626
if (index_count == 0 )
619
627
return 0 ;
@@ -672,16 +680,19 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve
672
680
best_triangle = getNeighborTriangle (meshlet, NULL , meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, 0 .f );
673
681
}
674
682
683
+ bool split = false ;
684
+
675
685
// when we run out of neighboring triangles we need to switch to spatial search; we currently just pick the closest triangle irrespective of connectivity
676
686
if (best_triangle == ~0u )
677
687
{
678
688
float position[3 ] = {meshlet_cone.px , meshlet_cone.py , meshlet_cone.pz };
679
689
unsigned int index = ~0u ;
680
- float limit = FLT_MAX;
690
+ float distance = FLT_MAX;
681
691
682
- kdtreeNearest (nodes, 0 , &triangles[0 ].px , sizeof (Cone) / sizeof (float ), emitted_flags, position, index , limit );
692
+ kdtreeNearest (nodes, 0 , &triangles[0 ].px , sizeof (Cone) / sizeof (float ), emitted_flags, position, cone_weight < 0 . f , index , distance );
683
693
684
694
best_triangle = index ;
695
+ split = meshlet.triangle_count >= min_triangles && split_factor > 0 && distance > meshlet_expected_radius * split_factor;
685
696
}
686
697
687
698
if (best_triangle == ~0u )
@@ -691,7 +702,7 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve
691
702
assert (a < vertex_count && b < vertex_count && c < vertex_count);
692
703
693
704
// add meshlet to the output; when the current meshlet is full we reset the accumulated bounds
694
- if (appendMeshlet (meshlet, a, b, c, used, meshlets, meshlet_vertices, meshlet_triangles, meshlet_offset, max_vertices, max_triangles))
705
+ if (appendMeshlet (meshlet, a, b, c, used, meshlets, meshlet_vertices, meshlet_triangles, meshlet_offset, max_vertices, max_triangles, split ))
695
706
{
696
707
meshlet_offset++;
697
708
memset (&meshlet_cone_acc, 0 , sizeof (meshlet_cone_acc));
@@ -738,10 +749,17 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve
738
749
meshlets[meshlet_offset++] = meshlet;
739
750
}
740
751
741
- assert (meshlet_offset <= meshopt_buildMeshletsBound (index_count, max_vertices, max_triangles ));
752
+ assert (meshlet_offset <= meshopt_buildMeshletsBound (index_count, max_vertices, min_triangles ));
742
753
return meshlet_offset;
743
754
}
744
755
756
+ size_t meshopt_buildMeshlets (meshopt_Meshlet* meshlets, unsigned int * meshlet_vertices, unsigned char * meshlet_triangles, const unsigned int * indices, size_t index_count, const float * vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t max_vertices, size_t max_triangles, float cone_weight)
757
+ {
758
+ assert (cone_weight >= 0 ); // to use negative cone weight, use meshopt_buildMeshletsFlex
759
+
760
+ return meshopt_buildMeshletsFlex (meshlets, meshlet_vertices, meshlet_triangles, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, max_vertices, max_triangles, max_triangles, cone_weight, 0 .0f );
761
+ }
762
+
745
763
size_t meshopt_buildMeshletsScan (meshopt_Meshlet* meshlets, unsigned int * meshlet_vertices, unsigned char * meshlet_triangles, const unsigned int * indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles)
746
764
{
747
765
using namespace meshopt ;
0 commit comments