Skip to content

Commit 261e8ef

Browse files
committed
clusterizer: Use strided access in computeBoundingSphere
Instead of forcing a 3-float layout on all callers, pass a stride and apply it in all indexing operations; this allows us to remove allocations in newly added meshopt_computeSphereBounds.
1 parent ccaebbc commit 261e8ef

File tree

2 files changed

+22
-25
lines changed

2 files changed

+22
-25
lines changed

src/clusterizer.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -141,22 +141,24 @@ static void buildTriangleAdjacencySparse(TriangleAdjacency2& adjacency, const un
141141
}
142142
}
143143

144-
static void computeBoundingSphere(float result[4], const float points[][3], size_t count)
144+
static void computeBoundingSphere(float result[4], const float* points, size_t count, size_t points_stride)
145145
{
146146
assert(count > 0);
147147

148+
size_t points_stride_float = points_stride / sizeof(float);
149+
148150
// find extremum points along all 3 axes; for each axis we get a pair of points with min/max coordinates
149151
size_t pmin[3] = {0, 0, 0};
150152
size_t pmax[3] = {0, 0, 0};
151153

152154
for (size_t i = 0; i < count; ++i)
153155
{
154-
const float* p = points[i];
156+
const float* p = points + i * points_stride_float;
155157

156158
for (int axis = 0; axis < 3; ++axis)
157159
{
158-
pmin[axis] = (p[axis] < points[pmin[axis]][axis]) ? i : pmin[axis];
159-
pmax[axis] = (p[axis] > points[pmax[axis]][axis]) ? i : pmax[axis];
160+
pmin[axis] = (p[axis] < points[pmin[axis] * points_stride_float + axis]) ? i : pmin[axis];
161+
pmax[axis] = (p[axis] > points[pmax[axis] * points_stride_float + axis]) ? i : pmax[axis];
160162
}
161163
}
162164

@@ -166,8 +168,8 @@ static void computeBoundingSphere(float result[4], const float points[][3], size
166168

167169
for (int axis = 0; axis < 3; ++axis)
168170
{
169-
const float* p1 = points[pmin[axis]];
170-
const float* p2 = points[pmax[axis]];
171+
const float* p1 = points + pmin[axis] * points_stride_float;
172+
const float* p2 = points + pmax[axis] * points_stride_float;
171173

172174
float d2 = (p2[0] - p1[0]) * (p2[0] - p1[0]) + (p2[1] - p1[1]) * (p2[1] - p1[1]) + (p2[2] - p1[2]) * (p2[2] - p1[2]);
173175

@@ -179,16 +181,16 @@ static void computeBoundingSphere(float result[4], const float points[][3], size
179181
}
180182

181183
// use the longest segment as the initial sphere diameter
182-
const float* p1 = points[pmin[paxis]];
183-
const float* p2 = points[pmax[paxis]];
184+
const float* p1 = points + pmin[paxis] * points_stride_float;
185+
const float* p2 = points + pmax[paxis] * points_stride_float;
184186

185187
float center[3] = {(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2, (p1[2] + p2[2]) / 2};
186188
float radius = sqrtf(paxisd2) / 2;
187189

188190
// iteratively adjust the sphere up until all points fit
189191
for (size_t i = 0; i < count; ++i)
190192
{
191-
const float* p = points[i];
193+
const float* p = points + i * points_stride_float;
192194
float d2 = (p[0] - center[0]) * (p[0] - center[0]) + (p[1] - center[1]) * (p[1] - center[1]) + (p[2] - center[2]) * (p[2] - center[2]);
193195

194196
if (d2 > radius * radius)
@@ -857,13 +859,13 @@ meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t
857859

858860
// compute cluster bounding sphere; we'll use the center to determine normal cone apex as well
859861
float psphere[4] = {};
860-
computeBoundingSphere(psphere, corners[0], triangles * 3);
862+
computeBoundingSphere(psphere, corners[0][0], triangles * 3, sizeof(float) * 3);
861863

862864
float center[3] = {psphere[0], psphere[1], psphere[2]};
863865

864866
// treating triangle normals as points, find the bounding sphere - the sphere center determines the optimal cone axis
865867
float nsphere[4] = {};
866-
computeBoundingSphere(nsphere, normals, triangles);
868+
computeBoundingSphere(nsphere, normals[0], triangles, sizeof(float) * 3);
867869

868870
float axis[3] = {nsphere[0], nsphere[1], nsphere[2]};
869871
float axislength = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
@@ -987,20 +989,8 @@ meshopt_Bounds meshopt_computeSphereBounds(const float* positions, size_t count,
987989
if (count == 0)
988990
return bounds;
989991

990-
meshopt_Allocator allocator;
991-
float* centers = allocator.allocate<float>(count * 3); // TBD
992-
993-
for (size_t i = 0; i < count; ++i)
994-
{
995-
const float* position = positions + i * (positions_stride / sizeof(float));
996-
997-
centers[i * 3 + 0] = position[0];
998-
centers[i * 3 + 1] = position[1];
999-
centers[i * 3 + 2] = position[2];
1000-
}
1001-
1002992
float psphere[4] = {};
1003-
computeBoundingSphere(psphere, (float(*)[3])centers, count);
993+
computeBoundingSphere(psphere, positions, count, positions_stride);
1004994

1005995
float pradius = 0;
1006996

src/meshoptimizer.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destinati
434434
*
435435
* destination must contain enough space for the target index buffer (target_vertex_count elements)
436436
* vertex_positions should have float3 position in the first 12 bytes of each vertex
437-
* vertex_colors should can be NULL; when it's not NULL, it should have float3 color in the first 12 bytes of each vertex
437+
* vertex_colors can be NULL; when it's not NULL, it should have float3 color in the first 12 bytes of each vertex
438438
* color_weight determines relative priority of color wrt position; 1.0 is a safe default
439439
*/
440440
MESHOPTIMIZER_API size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_colors, size_t vertex_colors_stride, float color_weight, size_t target_vertex_count);
@@ -619,6 +619,13 @@ struct meshopt_Bounds
619619
MESHOPTIMIZER_API struct meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
620620
MESHOPTIMIZER_API struct meshopt_Bounds meshopt_computeMeshletBounds(const unsigned int* meshlet_vertices, const unsigned char* meshlet_triangles, size_t triangle_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
621621

622+
/**
623+
* Experimental: Sphere bounds generator
624+
* Creates bounding sphere around a set of points or a set of spheres; returns the center and radius of the sphere, with other fields of the result set to 0.
625+
*
626+
* positions should have float3 position in the first 12 bytes of each element
627+
* radii can be NULL; when it's not NULL, it should have a non-negative float radius in the first 4 bytes of each element
628+
*/
622629
MESHOPTIMIZER_EXPERIMENTAL struct meshopt_Bounds meshopt_computeSphereBounds(const float* positions, size_t count, size_t positions_stride, const float* radii, size_t radii_stride);
623630

624631
/**

0 commit comments

Comments
 (0)