Skip to content

Commit c48346b

Browse files
committed
Subdiv - small refactoring of SubdivShape::MaxEdgeScreenSize
1 parent 9f70ef8 commit c48346b

File tree

1 file changed

+65
-43
lines changed

1 file changed

+65
-43
lines changed

src/slg/shapes/subdiv.cpp

Lines changed: 65 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -741,10 +741,7 @@ struct Surface {
741741

742742
// Check
743743
SDL_LOG(
744-
"Subdivision (enhanced) - Tessellating "
745-
<< FACE_COUNT
746-
<< " faces / " << topology.GetNumVertices()
747-
<< " points with factor N="
744+
"Subdivision (enhanced) - Tessellating with factor N = "
748745
<< N
749746
);
750747
if (FACE_COUNT * N * N >= std::numeric_limits<int>::max()) {
@@ -1308,7 +1305,7 @@ ExtTriangleMesh *ApplySubdiv(
13081305
// mesh)
13091306
SDL_LOG(
13101307
"Subdivision (enhanced) - Building new mesh: "
1311-
<< numPoints << " points, "
1308+
<< numPoints << " points / "
13121309
<< numTriangles << " triangles"
13131310
);
13141311

@@ -1357,21 +1354,40 @@ SubdivShape::SubdivShape(
13571354

13581355
if (maxLevel > 0) {
13591356
if (camera && (maxEdgeScreenSize > 0.f)) {
1360-
SDL_LOG("Subdividing shape " << srcMesh->GetName() << " max. at level: " << maxLevel);
1357+
SDL_LOG("Subdividing shape " << srcMesh->GetName()
1358+
<< " - Adaptive subdivision");
13611359

13621360
mesh = srcMesh->Copy();
13631361

13641362
for (u_int i = 0; i < maxLevel; ++i) {
1363+
SDL_LOG("Subdividing - Adaptive - Computing max edge size");
13651364
// Check the size of the longest mesh edge on film image plane
13661365
const float edgeScreenSize = MaxEdgeScreenSize(camera, mesh);
1367-
SDL_LOG("Subdividing shape current max. edge screen size: " << edgeScreenSize);
13681366

13691367
if (edgeScreenSize <= maxEdgeScreenSize)
13701368
break;
13711369

1372-
// Subdivide by one level and re-try
1373-
ExtTriangleMesh *newMesh = ApplySubdiv(mesh, 1, enhanced);
1374-
SDL_LOG("Subdivided shape step #" << i << " from " << mesh->GetTotalTriangleCount() << " to " << newMesh->GetTotalTriangleCount() << " faces");
1370+
SDL_LOG(
1371+
"Subdivision - Adaptive - Step #" << i << " - "
1372+
<< "Current maximum edge size on screen = "
1373+
<< edgeScreenSize
1374+
<< ", target = "
1375+
<< maxEdgeScreenSize
1376+
);
1377+
1378+
1379+
int optimizedLevel =
1380+
static_cast<int>(std::ceil(std::log2f(edgeScreenSize / maxEdgeScreenSize)));
1381+
SDL_LOG("Subdividing adapted level = " << optimizedLevel);
1382+
1383+
// Subdivide and re-try
1384+
ExtTriangleMesh *newMesh = ApplySubdiv(mesh, optimizedLevel, enhanced);
1385+
SDL_LOG(
1386+
"Done step #" << i
1387+
<< " from " << mesh->GetTotalTriangleCount()
1388+
<< " to " << newMesh->GetTotalTriangleCount() << " faces "
1389+
<< "(level=" << optimizedLevel << ")"
1390+
);
13751391

13761392
// Replace old mesh with new one
13771393
delete mesh;
@@ -1409,48 +1425,47 @@ float SubdivShape::MaxEdgeScreenSize(const Camera *camera, ExtTriangleMesh *srcM
14091425
// Note VisualStudio doesn't support:
14101426
//#pragma omp parallel for reduction(max:maxEdgeSize)
14111427

1412-
const u_int threadCount =
1413-
#if defined(_OPENMP)
1414-
omp_get_max_threads()
1415-
#else
1416-
0
1417-
#endif
1418-
;
1428+
const u_int threadCount = omp_get_max_threads();
14191429

14201430
const Transform worldToScreen = Inverse(camera->GetScreenToWorld());
14211431

14221432
std::vector<float> maxEdgeSizes(threadCount, 0.f);
1423-
for(
1424-
// Visual C++ 2013 supports only OpenMP 2.5
1425-
#if _OPENMP >= 200805
1426-
unsigned
1427-
#endif
1428-
int i = 0; i < triCount; ++i) {
1429-
const int tid =
1430-
#if defined(_OPENMP)
1431-
omp_get_thread_num()
1432-
#else
1433-
0
1434-
#endif
1435-
;
1433+
1434+
std::vector<Point> projectedPoints(srcMesh->GetTotalVertexCount());
1435+
#pragma omp parallel for
1436+
for(int i = 0; i < srcMesh->GetTotalVertexCount(); ++i) {
1437+
projectedPoints[i] = worldToScreen * verts[i];
1438+
projectedPoints[i] /= projectedPoints[i].z;
1439+
}
1440+
1441+
// Visual C++ 2013 supports only OpenMP 2.5, with int loop indices
1442+
// At any rate, opensubdiv indices are of type 'int', so no regret...
1443+
//
1444+
// We use LengthSquared for max search, sparing one operation per iteration (sqrt)
1445+
#pragma omp parallel for
1446+
for(int i = 0; i < triCount; ++i) {
1447+
const int tid = omp_get_thread_num();
1448+
//const int tid = 0;
14361449

14371450
const Triangle &tri = tris[i];
1438-
const Point p0 = worldToScreen * verts[tri.v[0]];
1439-
const Point p1 = worldToScreen * verts[tri.v[1]];
1440-
const Point p2 = worldToScreen * verts[tri.v[2]];
1451+
const Point p0 = projectedPoints[tri.v[0]];
1452+
const Point p1 = projectedPoints[tri.v[1]];
1453+
const Point p2 = projectedPoints[tri.v[2]];
1454+
1455+
std::array<float, 4> triMaxEdgeSize;
1456+
triMaxEdgeSize[0] = (p1 - p0).LengthSquared();
1457+
triMaxEdgeSize[1] = (p2 - p1).LengthSquared();
1458+
triMaxEdgeSize[2] = (p0 - p2).LengthSquared();
1459+
triMaxEdgeSize[3] = maxEdgeSizes[tid];
14411460

1442-
float maxEdgeSize = (p1 - p0).Length();
1443-
maxEdgeSize = Max(maxEdgeSize, (p2 - p1).Length());
1444-
maxEdgeSize = Max(maxEdgeSize, (p0 - p2).Length());
1461+
maxEdgeSizes[tid] =
1462+
*std::max_element(triMaxEdgeSize.begin(), triMaxEdgeSize.end());
14451463

1446-
maxEdgeSizes[tid] = Max(maxEdgeSizes[tid], maxEdgeSize);
14471464
}
14481465

1449-
float maxEdgeSize = 0.f;
1450-
for (u_int i = 0; i < threadCount; ++i)
1451-
maxEdgeSize = Max(maxEdgeSize, maxEdgeSizes[i]);
1466+
float maxEdgeSize = *std::max_element(maxEdgeSizes.begin(), maxEdgeSizes.end());
14521467

1453-
return maxEdgeSize;
1468+
return sqrtf(maxEdgeSize);
14541469
}
14551470

14561471

@@ -1468,12 +1483,19 @@ ExtTriangleMesh *SubdivShape::ApplySubdiv(
14681483
assert(srcMesh->GetTotalTriangleCount() <= std::numeric_limits<int>::max());
14691484

14701485
if (enhanced) {
1471-
SDL_LOG("Subdivision (enhanced) - Starting");
1486+
SDL_LOG(
1487+
"Subdivision (enhanced) - Starting - "
1488+
<< srcMesh->GetTotalVertexCount() << " points / "
1489+
<< srcMesh->GetTotalTriangleCount() << " triangles"
1490+
);
14721491

14731492
return enhanced::ApplySubdiv(srcMesh, maxLevel);
14741493
}
14751494
else {
1476-
SDL_LOG("Subdivision - Starting");
1495+
SDL_LOG("Subdivision - Starting - "
1496+
<< srcMesh->GetTotalVertexCount() << " points / "
1497+
<< srcMesh->GetTotalTriangleCount() << " triangles"
1498+
);
14771499

14781500
return simple::ApplySubdiv(srcMesh, maxLevel);
14791501
}

0 commit comments

Comments
 (0)