|
10 | 10 | // Graham Wihlidal. Optimizing the Graphics Pipeline with Compute. 2016
|
11 | 11 | // Matthaeus Chajdas. GeometryFX 1.2 - Cluster Culling. 2016
|
12 | 12 | // Jack Ritter. An Efficient Bounding Sphere. 1990
|
| 13 | +// Thomas Larsson. Fast and Tight Fitting Bounding Spheres. 2008 |
13 | 14 | namespace meshopt
|
14 | 15 | {
|
15 | 16 |
|
@@ -147,37 +148,62 @@ static void buildTriangleAdjacencySparse(TriangleAdjacency2& adjacency, const un
|
147 | 148 | }
|
148 | 149 | }
|
149 | 150 |
|
150 |
| -static void computeBoundingSphere(float result[4], const float* points, size_t count, size_t points_stride, const float* radii, size_t radii_stride) |
| 151 | +static void computeBoundingSphere(float result[4], const float* points, size_t count, size_t points_stride, const float* radii, size_t radii_stride, size_t axis_count) |
151 | 152 | {
|
| 153 | + static const float kAxes[7][3] = { |
| 154 | + // X, Y, Z |
| 155 | + {1, 0, 0}, |
| 156 | + {0, 1, 0}, |
| 157 | + {0, 0, 1}, |
| 158 | + |
| 159 | + // XYZ, -XYZ, X-YZ, XY-Z; normalized to unit length |
| 160 | + {0.57735026f, 0.57735026f, 0.57735026f}, |
| 161 | + {-0.57735026f, 0.57735026f, 0.57735026f}, |
| 162 | + {0.57735026f, -0.57735026f, 0.57735026f}, |
| 163 | + {0.57735026f, 0.57735026f, -0.57735026f}, |
| 164 | + }; |
| 165 | + |
152 | 166 | assert(count > 0);
|
| 167 | + assert(axis_count <= sizeof(kAxes) / sizeof(kAxes[0])); |
153 | 168 |
|
154 | 169 | size_t points_stride_float = points_stride / sizeof(float);
|
155 | 170 | size_t radii_stride_float = radii_stride / sizeof(float);
|
156 | 171 |
|
157 |
| - // find extremum points along all 3 axes; for each axis we get a pair of points with min/max coordinates |
158 |
| - size_t pmin[3] = {0, 0, 0}; |
159 |
| - size_t pmax[3] = {0, 0, 0}; |
| 172 | + // find extremum points along all axes; for each axis we get a pair of points with min/max coordinates |
| 173 | + size_t pmin[7], pmax[7]; |
| 174 | + float tmin[7], tmax[7]; |
| 175 | + |
| 176 | + for (size_t axis = 0; axis < axis_count; ++axis) |
| 177 | + { |
| 178 | + pmin[axis] = pmax[axis] = 0; |
| 179 | + tmin[axis] = FLT_MAX; |
| 180 | + tmax[axis] = -FLT_MAX; |
| 181 | + } |
160 | 182 |
|
161 | 183 | for (size_t i = 0; i < count; ++i)
|
162 | 184 | {
|
163 | 185 | const float* p = points + i * points_stride_float;
|
164 | 186 | float r = radii[i * radii_stride_float];
|
165 | 187 |
|
166 |
| - for (int axis = 0; axis < 3; ++axis) |
| 188 | + for (size_t axis = 0; axis < axis_count; ++axis) |
167 | 189 | {
|
168 |
| - float bmin = points[pmin[axis] * points_stride_float + axis] - radii[pmin[axis] * radii_stride_float]; |
169 |
| - float bmax = points[pmax[axis] * points_stride_float + axis] + radii[pmax[axis] * radii_stride_float]; |
| 190 | + const float* ax = kAxes[axis]; |
| 191 | + |
| 192 | + float tp = ax[0] * p[0] + ax[1] * p[1] + ax[2] * p[2]; |
| 193 | + float tpmin = tp - r, tpmax = tp + r; |
170 | 194 |
|
171 |
| - pmin[axis] = (p[axis] - r < bmin) ? i : pmin[axis]; |
172 |
| - pmax[axis] = (p[axis] + r > bmax) ? i : pmax[axis]; |
| 195 | + pmin[axis] = (tpmin < tmin[axis]) ? i : pmin[axis]; |
| 196 | + pmax[axis] = (tpmax > tmax[axis]) ? i : pmax[axis]; |
| 197 | + tmin[axis] = (tpmin < tmin[axis]) ? tpmin : tmin[axis]; |
| 198 | + tmax[axis] = (tpmax > tmax[axis]) ? tpmax : tmax[axis]; |
173 | 199 | }
|
174 | 200 | }
|
175 | 201 |
|
176 | 202 | // find the pair of points with largest distance
|
177 |
| - int paxis = 0; |
| 203 | + size_t paxis = 0; |
178 | 204 | float paxisdr = 0;
|
179 | 205 |
|
180 |
| - for (int axis = 0; axis < 3; ++axis) |
| 206 | + for (size_t axis = 0; axis < axis_count; ++axis) |
181 | 207 | {
|
182 | 208 | const float* p1 = points + pmin[axis] * points_stride_float;
|
183 | 209 | const float* p2 = points + pmax[axis] * points_stride_float;
|
@@ -1435,13 +1461,13 @@ meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t
|
1435 | 1461 |
|
1436 | 1462 | // compute cluster bounding sphere; we'll use the center to determine normal cone apex as well
|
1437 | 1463 | float psphere[4] = {};
|
1438 |
| - computeBoundingSphere(psphere, corners[0][0], triangles * 3, sizeof(float) * 3, &rzero, 0); |
| 1464 | + computeBoundingSphere(psphere, corners[0][0], triangles * 3, sizeof(float) * 3, &rzero, 0, 7); |
1439 | 1465 |
|
1440 | 1466 | float center[3] = {psphere[0], psphere[1], psphere[2]};
|
1441 | 1467 |
|
1442 | 1468 | // treating triangle normals as points, find the bounding sphere - the sphere center determines the optimal cone axis
|
1443 | 1469 | float nsphere[4] = {};
|
1444 |
| - computeBoundingSphere(nsphere, normals[0], triangles, sizeof(float) * 3, &rzero, 0); |
| 1470 | + computeBoundingSphere(nsphere, normals[0], triangles, sizeof(float) * 3, &rzero, 0, 3); |
1445 | 1471 |
|
1446 | 1472 | float axis[3] = {nsphere[0], nsphere[1], nsphere[2]};
|
1447 | 1473 | float axislength = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
|
@@ -1568,7 +1594,7 @@ meshopt_Bounds meshopt_computeSphereBounds(const float* positions, size_t count,
|
1568 | 1594 | const float rzero = 0.f;
|
1569 | 1595 |
|
1570 | 1596 | float psphere[4] = {};
|
1571 |
| - computeBoundingSphere(psphere, positions, count, positions_stride, radii ? radii : &rzero, radii ? radii_stride : 0); |
| 1597 | + computeBoundingSphere(psphere, positions, count, positions_stride, radii ? radii : &rzero, radii ? radii_stride : 0, 7); |
1572 | 1598 |
|
1573 | 1599 | bounds.center[0] = psphere[0];
|
1574 | 1600 | bounds.center[1] = psphere[1];
|
|
0 commit comments