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

122 lines
3.8 KiB
C++

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