106 lines
3.4 KiB
C++
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;
|
|
}
|