@@ -70,11 +70,77 @@ static void buildTriangleAdjacency(TriangleAdjacency2& adjacency, const unsigned
70
70
for (size_t i = 0 ; i < vertex_count; ++i)
71
71
{
72
72
assert (adjacency.offsets [i] >= adjacency.counts [i]);
73
-
74
73
adjacency.offsets [i] -= adjacency.counts [i];
75
74
}
76
75
}
77
76
77
+ static void buildTriangleAdjacencySparse (TriangleAdjacency2& adjacency, const unsigned int * indices, size_t index_count, size_t vertex_count, meshopt_Allocator& allocator)
78
+ {
79
+ size_t face_count = index_count / 3 ;
80
+
81
+ // sparse mode can build adjacency more quickly by ignoring unused vertices, using a bit to mark visited vertices
82
+ const unsigned int sparse_seen = 1u << 31 ;
83
+ assert (index_count < sparse_seen);
84
+
85
+ // allocate arrays
86
+ adjacency.counts = allocator.allocate <unsigned int >(vertex_count);
87
+ adjacency.offsets = allocator.allocate <unsigned int >(vertex_count);
88
+ adjacency.data = allocator.allocate <unsigned int >(index_count);
89
+
90
+ // fill triangle counts
91
+ for (size_t i = 0 ; i < index_count; ++i)
92
+ assert (indices[i] < vertex_count);
93
+
94
+ for (size_t i = 0 ; i < index_count; ++i)
95
+ adjacency.counts [indices[i]] = 0 ;
96
+
97
+ for (size_t i = 0 ; i < index_count; ++i)
98
+ adjacency.counts [indices[i]]++;
99
+
100
+ // fill offset table
101
+ unsigned int offset = 0 ;
102
+
103
+ // when using sparse mode this pass uses sparse_seen bit to tag visited vertices
104
+ for (size_t i = 0 ; i < index_count; ++i)
105
+ {
106
+ unsigned int v = indices[i];
107
+
108
+ if ((adjacency.counts [v] & sparse_seen) == 0 )
109
+ {
110
+ adjacency.offsets [v] = offset;
111
+ offset += adjacency.counts [v];
112
+ adjacency.counts [v] |= sparse_seen;
113
+ }
114
+ }
115
+
116
+ assert (offset == index_count);
117
+
118
+ // fill triangle data
119
+ for (size_t i = 0 ; i < face_count; ++i)
120
+ {
121
+ unsigned int a = indices[i * 3 + 0 ], b = indices[i * 3 + 1 ], c = indices[i * 3 + 2 ];
122
+
123
+ adjacency.data [adjacency.offsets [a]++] = unsigned (i);
124
+ adjacency.data [adjacency.offsets [b]++] = unsigned (i);
125
+ adjacency.data [adjacency.offsets [c]++] = unsigned (i);
126
+ }
127
+
128
+ // fix offsets that have been disturbed by the previous pass
129
+ // when using sparse mode this pass also fixes counts (that were marked with sparse_seen)
130
+ for (size_t i = 0 ; i < index_count; ++i)
131
+ {
132
+ unsigned int v = indices[i];
133
+
134
+ if (adjacency.counts [v] & sparse_seen)
135
+ {
136
+ adjacency.counts [v] &= ~sparse_seen;
137
+
138
+ assert (adjacency.offsets [v] >= adjacency.counts [v]);
139
+ adjacency.offsets [v] -= adjacency.counts [v];
140
+ }
141
+ }
142
+ }
143
+
78
144
static void computeBoundingSphere (float result[4 ], const float points[][3 ], size_t count)
79
145
{
80
146
assert (count > 0 );
@@ -552,10 +618,13 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve
552
618
meshopt_Allocator allocator;
553
619
554
620
TriangleAdjacency2 adjacency = {};
555
- buildTriangleAdjacency (adjacency, indices, index_count, vertex_count, allocator);
621
+ if (vertex_count > index_count && index_count < (1u << 31 ))
622
+ buildTriangleAdjacencySparse (adjacency, indices, index_count, vertex_count, allocator);
623
+ else
624
+ buildTriangleAdjacency (adjacency, indices, index_count, vertex_count, allocator);
556
625
557
- unsigned int * live_triangles = allocator. allocate < unsigned int >(vertex_count);
558
- memcpy ( live_triangles, adjacency.counts , vertex_count * sizeof ( unsigned int )) ;
626
+ // live triangle counts; note, we alias adjacency.counts as we remove triangles after emitting them so the counts always match
627
+ unsigned int * live_triangles = adjacency.counts ;
559
628
560
629
size_t face_count = index_count / 3 ;
561
630
@@ -625,12 +694,9 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve
625
694
memset (&meshlet_cone_acc, 0 , sizeof (meshlet_cone_acc));
626
695
}
627
696
628
- live_triangles[a]--;
629
- live_triangles[b]--;
630
- live_triangles[c]--;
631
-
632
697
// remove emitted triangle from adjacency data
633
698
// this makes sure that we spend less time traversing these lists on subsequent iterations
699
+ // live triangle counts are updated as a byproduct of these adjustments
634
700
for (size_t k = 0 ; k < 3 ; ++k)
635
701
{
636
702
unsigned int index = indices[best_triangle * 3 + k];
0 commit comments