Files
CDAG/Research/core/OctreeBuilder/BaseOctreeBuilder.cpp

106 lines
3.4 KiB
C++

#include "BaseOctreeBuilder.h"
#include <stdio.h>
#include <algorithm>
#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;
}