#include "StandardOctreeBuilder.h" #include "../Util/Stopwatch.h" #include "OctreeLoader.h" #define DAGFINALTREE StandardOctreeBuilder::StandardOctreeBuilder() : BaseStandardOctreeBuilder(), mTree(NULL) {} StandardOctreeBuilder::~StandardOctreeBuilder() {} std::string StandardOctreeBuilder::GetTreeType() { return "s"; } void StandardOctreeBuilder::FinalizeTree() { // Read all subtrees from cache and append them if (!IsSinglePass()) { Stopwatch watch; mTree = new Tree<>(GetTreeDepth()); int i = 1; for (const glm::uvec3& coord : GetValidCoords()) { if (verbose) printf("Reading subtree %u / %u at (%u, %u, %u) from cache...\n", i, (unsigned32)(GetValidCoords().size()), coord.x, coord.y, coord.z); Tree<>* subTree = (Tree<>*)OctreeLoader::ReadCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord), verbose); if (subTree != NULL) { if (verbose) printf("Appending subtree... "); watch.Reset(); mTree->AppendAndMerge(coord, GetAppendedTreeLevel(), subTree); //mTree->Append(mCurPassTreeCoord, mainTreeLevel, mCurPassTree); delete subTree; if (verbose) printf("Appended subtree in %d ms.\n", (int)(watch.GetTime() * 1000)); } //mTree->SortNodes(); //#ifdef DAGFINALTREE // if (verbose) printf("Converting current tree to DAG...\n"); // mTree->ToDAG(mainTreeLevel); //#endif i++; } // Delete the cache files if (verbose) printf("Deleting cache..."); watch.Reset(); for (const glm::uvec3& coord : GetValidCoords()) OctreeLoader::DeleteCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord)); if (verbose) printf("Cache deleted in %d ms\n", (int)(watch.GetTime() * 1000)); } } void StandardOctreeBuilder::TerminateTree() { OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), GetVerbose()); delete mTree; } bool StandardOctreeBuilder::CancelCurPassTree(const glm::uvec3& coord) { return OctreeLoader::VerifyCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord)); } void StandardOctreeBuilder::InitCurPassTree(glm::uvec3 coord) { mTree = new Tree<>(GetSinglePassTreeDepth()); } void StandardOctreeBuilder::FinalizeCurPassTree(glm::uvec3 coord) { Stopwatch watch; if (!mTree->IsEmpty()) // Only append the tree (and compress) if it is not empty { // Convert the subtree to a DAG first, this saved time when appending and converting the total tree. // If it is a single pass tree it needs to be converted anyway :) // Benchmark (Total build time for subtrees of depth 10, final tree of depth 12, run in Release mode with pool): // 209.922 seconds without early converting // 163.645 seconds with early converting if (verbose) printf("Converting %s to DAG...\n", IsSinglePass() ? "tree" : "subtree"); watch.Reset(); //mCurPassTree->SortNodes(); mTree->ToDAG(); if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000)); if (!IsSinglePass()) { if (verbose) printf("Writing subtree to cache..."); watch.Reset(); OctreeLoader::WriteCache(mTree, GetTreeType(), GetSinglePassTreeFilename(coord), verbose); if (verbose) printf("Wrote cache in %d ms.\n", (int)(watch.GetTime() * 1000)); delete mTree; mTree = NULL; } } } void StandardOctreeBuilder::AddNode(const glm::uvec3& coordinate) { mTree->AddLeafNode(coordinate); } std::vector StandardOctreeBuilder::GetOctreeNodesPerLevel() { return mTree->GetOctreeNodesPerLevel(); } std::vector StandardOctreeBuilder::GetNodesPerLevel() { return mTree->GetNodesPerLevel(); } std::string StandardOctreeBuilder::GetSinglePassTreeFilename(const glm::uvec3& coord) const { char buffer[255]; sprintf(buffer, "%s_%u_(%u_%u_%u)", GetOutputFile().c_str(), GetTreeDepth(), coord.x, coord.y, coord.z); return std::string(buffer); }