@@ -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