#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 MultiRootOctreeBuilder::GetOctreeNodesPerLevel() { return mTree->GetOctreeNodesPerLevel(); } std::vector MultiRootOctreeBuilder::GetNodesPerLevel() { return mTree->GetNodesPerLevel(); }