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

121 lines
3.4 KiB
C++

#include "MultiRootOctreeBuilder.h"
#include "../../scene/Octree/MultiRootTree.h"
#include "../Util/Stopwatch.h"
#include "OctreeLoader.h"
MultiRootOctreeBuilder::MultiRootOctreeBuilder(unsigned8 bitsPerChannel) :
BaseMaterialOctreeBuilder(),
mTree(NULL),
mCurPassTree(NULL),
mBitsPerChannel(bitsPerChannel)
{}
MultiRootOctreeBuilder::MultiRootOctreeBuilder() : MultiRootOctreeBuilder(8)
{}
MultiRootOctreeBuilder::~MultiRootOctreeBuilder() {}
std::string MultiRootOctreeBuilder::GetTreeType() { return "m" + std::to_string(mBitsPerChannel); }
void MultiRootOctreeBuilder::InitTree()
{
mTree = new MultiRootTree<>(GetTreeDepth(), 3 * mBitsPerChannel);
}
void MultiRootOctreeBuilder::FinalizeTree()
{
// Convert the final tree to a DAG
Stopwatch watch;
if (verbose) printf("Converting final tree to DAG...\n");
watch.Reset();
mTree->ToDAG();
if (verbose) printf("Done in %u ms, %llu nodes left.\n", (unsigned)(watch.GetTime() * 1000), (unsigned64)mTree->GetNodeCount());
}
void MultiRootOctreeBuilder::TerminateTree()
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
}
void MultiRootOctreeBuilder::InitCurPassTree(glm::uvec3 coord)
{
mCurPassTree = new MultiRootTree<>(GetSinglePassTreeDepth(), 3 * mBitsPerChannel);
}
void MultiRootOctreeBuilder::FinalizeCurPassTree(glm::uvec3 coord)
{
Stopwatch watch;
if (mCurPassTree->GetNodeCount() > 1) // Only append the tree (and compress) if it is not empty
{
if (IsSinglePass()) // Means we just constructed the root, so no need to append
{
delete mTree;
mTree = mCurPassTree;
}
else
{
// Convert the subtree to a DAG first, this saved time when appending and converting the total tree
// Benchmark (Total build time for subtrees of depth 10, final tree of depth 12, Release mode with pool):
// 209.922 seconds without early converting
// 163.645 seconds with early converting
if (verbose) printf("Converting subtree to DAG...\n");
watch.Reset();
mCurPassTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
if (verbose) printf("Appending subtree... ");
mTree->Append(coord, GetAppendedTreeLevel(), mCurPassTree);
delete mCurPassTree;
if (verbose) printf("Converting current tree to DAG...\n");
mTree->ToDAG(GetAppendedTreeLevel());
}
}
else
{
delete mCurPassTree;
}
}
void MultiRootOctreeBuilder::UpdateMultiRoot(glm::uvec3 coord, glm::u8 color, unsigned32 slaveRootOffset)
{
//glm::u8 testColor = 0;
// Add nodes to the tree for the color
for (unsigned8 i = 0; i < mBitsPerChannel; i++)
{
glm::u8 mask = 1 << i;
if ((color & mask) == mask)
{
mCurPassTree->AddLeafNode(coord, slaveRootOffset + i);
//testColor += mask;
}
}
}
void MultiRootOctreeBuilder::AddMissingNode(const glm::uvec3& coordinate, const Color& color)
{
if (!mCurPassTree->HasLeaf(coordinate))
AddNode(coordinate, color);
}
void MultiRootOctreeBuilder::AddNode(const glm::uvec3& coordinate, const Color& color)
{
mCurPassTree->AddLeafNode(coordinate);
UpdateMultiRoot(coordinate, color.GetR(), 0);
UpdateMultiRoot(coordinate, color.GetG(), mBitsPerChannel);
UpdateMultiRoot(coordinate, color.GetB(), 2 * mBitsPerChannel);
}
std::vector<size_t> MultiRootOctreeBuilder::GetOctreeNodesPerLevel()
{
return mTree->GetOctreeNodesPerLevel();
}
std::vector<size_t> MultiRootOctreeBuilder::GetNodesPerLevel()
{
return mTree->GetNodesPerLevel();
}