#include "BaseOctreeBuilder.h" #include #include #include "../Voxelizer/VoxelInfo.h" #include "../Util/Stopwatch.h" #include "OctreeBuilderStatistics.h" #include "../Voxelizer/BaseVoxelizer.h" OctreeBuilderStatistics BaseOctreeBuilder::BuildOctree(BaseVoxelizer& voxelizer, unsigned8 level, unsigned8 maxSingle) { // Initialize some variables used for building unsigned8 singlePassDepth = (maxSingle < level) ? maxSingle : level; unsigned8 singlePassLevel = level - singlePassDepth; maxTreeDepth = level; maxSinglePassLayers = maxSingle; OctreeBuilderStatistics stats(level); stats.type = GetTreeType(); Stopwatch watch; Stopwatch mainWatch; mainWatch.Reset(); // Find out which subtrees to builds watch.Reset(); mValidCoords = voxelizer.GetValidCoords(singlePassLevel); std::sort(mValidCoords.begin(), mValidCoords.end(), [&](const glm::uvec3& coord1, const glm::uvec3& coord2) { return SubTreeCompare(coord1, coord2); }); stats.validCoordBuildtime = watch.GetTime(); // Do a pass through all voxels in the scene for preprocessing watch.Reset(); if (UsePreprocessing()) { Stopwatch smallWatch; InitPreprocessing(); unsigned i = 0; for (const glm::uvec3& coord : mValidCoords) { smallWatch.Reset(); if (verbose) printf("Preprocessing subtree %llu / %llu at coordinate (%u, %u, %u).\n", (unsigned64)(i + 1), (unsigned64)(mValidCoords.size()), coord.x, coord.y, coord.z); InitCurPreprocessPass(coord); voxelizer.Voxelize(level, singlePassDepth, coord, [&](const VoxelInfo& info, bool best) { if (best) PreProcessNode(info); else PreProcessMissingNode(info); }, RequiresColors(), RequiresNormals(), RequiresReflectivity()); FinalizeCurPreprocessPass(coord); if (verbose) printf("Subtree processed in %d ms.\n", (int)(watch.GetTime() * 1000)); i++; } FinalizePreprocessing(); } // Voxelize the scene and build the tree InitTree(); Stopwatch smallWatch; unsigned i = 0; for (const glm::uvec3& coord : mValidCoords) { smallWatch.Reset(); if (verbose) printf("Processing subtree %llu / %llu at coordinate (%u, %u, %u).\n", (unsigned64)(i + 1), (unsigned64)(mValidCoords.size()), coord.x, coord.y, coord.z); if (!IsSinglePass() && !mForceRebuild && CancelCurPassTree(coord)) { if (verbose) printf("Subtree processing cancelled.\n"); } else { InitCurPassTree(coord); watch.Reset(); voxelizer.Voxelize(level, singlePassDepth, coord, [&](const VoxelInfo& info, bool best) { if (best) AddNode(info); else AddMissingNode(info); }, RequiresColors(), RequiresNormals(), RequiresReflectivity()); stats.depthPeelingTime += watch.GetTime(); watch.Reset(); FinalizeCurPassTree(coord); stats.finalizationTime += watch.GetTime(); if (verbose) printf("Subtree processed in %d ms.\n", (int)(smallWatch.GetTime() * 1000)); } i++; } watch.Reset(); FinalizeTree(); stats.finalizationTime += watch.GetTime(); // Calculate and show statistics stats.totalTime = mainWatch.GetTime(); stats.octreeNodesPerLevel = GetOctreeNodesPerLevel(); stats.dagNodesPerLevel = GetNodesPerLevel(); if (verbose) stats.Print(); TerminateTree(); return stats; } bool BaseOctreeBuilder::SubTreeCompare(const glm::uvec3& coord1, const glm::uvec3& coord2) const { if (coord1.z != coord2.z) return coord1.z < coord2.z; if (coord1.y != coord2.y) return coord1.y < coord2.y; if (coord1.x != coord2.x) return coord1.x < coord2.x; return false; }