782 lines
34 KiB
C++
782 lines
34 KiB
C++
#include "OctreeLoader.h"
|
|
|
|
#include "TreeTypeParser.h"
|
|
#include "SettingsParser.h"
|
|
|
|
#include "../../scene/Material/Color.h"
|
|
#include "../../scene/Material/SmallNormal.h"
|
|
#include "../../scene/Material/ColorAndNormal.h"
|
|
#include "../../scene/Material/ColorAndNormalAndValue.h"
|
|
#include "../../scene/Material/ColorAndOpacity.h"
|
|
|
|
#include "../../scene/Octree/BaseTree.h"
|
|
#include "../../scene/Octree/Tree.h"
|
|
#include "../../scene/Octree/MaterialTree.h"
|
|
#include "../../scene/Octree/MultiRootTree.h"
|
|
#include "../../scene/Octree/ColorChannelMultiRootTree.h"
|
|
#include "../../scene/Octree/MultiRootBitsTree.h"
|
|
#include "../../scene/Octree/MaterialLibraryTree.h"
|
|
#include "../../scene/Octree/HierarchicalShiftingColoredTree.h"
|
|
#include "../../scene/Octree/HierarchicalColorsOnlyTree.h"
|
|
#include "../../scene/Octree/MaterialLibraryUniqueIndexTree.h"
|
|
#include "../../scene/Octree/UniqueIndexShiftTree.h"
|
|
#include "../../scene/Octree/MaterialLibraryMultiRootTree.h"
|
|
#include "../../scene/Octree/IMaterialTexture.h"
|
|
#include "../../scene/Octree/IBlockTexture.h"
|
|
|
|
#include "../../scene/PoolBuilder/StandardPoolBuilder.h"
|
|
|
|
#include "CompressedTextureFactory.h"
|
|
#include "PoolBuilderFactory.h"
|
|
#include "../../scene/Material/MaterialLibraryPointer.h"
|
|
#include "../../scene/Material/SignedIntMaterial.h"
|
|
|
|
#include "ColorQuantizerFactory.h"
|
|
|
|
#include "../../PropertyLoader.h"
|
|
#include "../Util/Stopwatch.h"
|
|
#include "../StringHelper.h"
|
|
#include "../MathHelper.h"
|
|
|
|
bool OctreeLoader::VerifyCache()
|
|
{
|
|
bool useCache = SettingsParser::GetUseCacheFromSettings();
|
|
if (!useCache)
|
|
return false;
|
|
|
|
bool verbose = SettingsParser::GetVerboseFromSettings();
|
|
if (verbose) printf("Verifying cache... ");
|
|
Stopwatch watch; watch.Reset();
|
|
|
|
auto octreeType = SettingsParser::GetTreeTypeFromSettings();
|
|
unsigned8 maxLevel = SettingsParser::GetMaxLevelFromSettings();
|
|
std::string filename = SettingsParser::GetFilenameFromSettings();
|
|
|
|
bool cacheValid = VerifyCache(octreeType, maxLevel, filename);
|
|
|
|
if (verbose) printf("Cache is %s, confirmed in %d ms\n", cacheValid ? "valid" : "invalid", (int)(watch.GetTime() * 1000));
|
|
|
|
return cacheValid;
|
|
}
|
|
|
|
bool OctreeLoader::VerifyCache(std::string treeType, unsigned8 maxLevel, std::string filename)
|
|
{
|
|
std::string outputFile = GetFullFilename(treeType, maxLevel, filename);
|
|
auto tree = CreateTree(treeType, maxLevel);
|
|
bool cacheValid = tree->VerifyTree(outputFile.c_str());
|
|
delete tree;
|
|
return cacheValid;
|
|
}
|
|
|
|
BaseTree* OctreeLoader::ReadCache()
|
|
{
|
|
bool verbose = SettingsParser::GetVerboseFromSettings();
|
|
if (verbose) printf("Reading cache... ");
|
|
Stopwatch watch; watch.Reset();
|
|
|
|
auto octreeType = SettingsParser::GetTreeTypeFromSettings();
|
|
unsigned8 maxLevel = SettingsParser::GetMaxLevelFromSettings();
|
|
std::string filename = SettingsParser::GetFilenameFromSettings();
|
|
|
|
auto tree = ReadCache(octreeType, maxLevel, filename);
|
|
|
|
if (verbose) printf("Read tree with %llu nodes succesfully in %u ms\n", (unsigned64)tree->GetNodeCount(), (unsigned)(watch.GetTime() * 1000));
|
|
|
|
return tree;
|
|
}
|
|
|
|
BaseTree* OctreeLoader::ReadCache(std::string treeType, unsigned8 maxLevel, std::string filename, bool verbose)
|
|
{
|
|
Stopwatch watch;
|
|
watch.Reset();
|
|
|
|
std::string outputFile = GetFullFilename(treeType, maxLevel, filename);
|
|
if (verbose) printf("Reading file %s.oct.", outputFile.c_str());
|
|
|
|
auto tree = CreateTree(treeType, maxLevel);
|
|
bool readSuccessful = tree->ReadTree(outputFile.c_str());
|
|
if (!readSuccessful)
|
|
{
|
|
delete tree;
|
|
if (verbose) printf("Reading .oct file failed.\n");
|
|
return NULL;
|
|
}
|
|
if (verbose) printf("Read .oct file in %u ms.\n", (unsigned)(watch.GetTime() * 1000));
|
|
|
|
if (verbose) tree->PrintDebugInfo();
|
|
|
|
return tree;
|
|
}
|
|
|
|
void OctreeLoader::DeleteCache(std::string treeType, unsigned8 maxLevel, std::string filename)
|
|
{
|
|
try
|
|
{
|
|
std::remove(Tree<>::GetOctreeFileName(GetFullFilename(treeType, maxLevel, filename).c_str()).c_str());
|
|
}
|
|
catch (...)
|
|
{
|
|
printf("Deleting cache file %s failed", GetFullFilename(treeType.c_str(), maxLevel, filename).c_str());
|
|
}
|
|
}
|
|
|
|
bool OctreeLoader::WriteCache(BaseTree* tree, std::string treeType, std::string filename, bool verbose)
|
|
{
|
|
std::string outputFile = GetFullFilename(treeType, tree->GetMaxLevel(), filename);
|
|
// Write the final tree to a file
|
|
Stopwatch watch; watch.Reset();
|
|
|
|
if (verbose) printf("Writing DAG to \"%s\"... ", outputFile.c_str());
|
|
|
|
bool res = tree->WriteTree(outputFile.c_str());
|
|
|
|
if (verbose) printf("Writing took %d ms\n", (int)(watch.GetTime() * 1000));
|
|
return res;
|
|
}
|
|
|
|
bool OctreeLoader::VerifyPool()
|
|
{
|
|
bool useCache = SettingsParser::GetUsePoolCacheFromSettings();
|
|
if (!useCache)
|
|
return false;
|
|
|
|
std::string filename = SettingsParser::GetFilenameFromSettings();
|
|
unsigned8 maxLevel = SettingsParser::GetMaxLevelFromSettings();
|
|
std::string treeType = SettingsParser::GetTreeTypeFromSettings();
|
|
|
|
return VerifyPool(treeType, maxLevel, filename);
|
|
}
|
|
|
|
bool OctreeLoader::VerifyPool(std::string treeType, unsigned8 maxLevel, std::string filename)
|
|
{
|
|
auto fullFileName = GetFullFilename(treeType, maxLevel, filename);
|
|
StandardPoolBuilder builder;
|
|
return builder.VerifyCachedPool(fullFileName, maxLevel);
|
|
}
|
|
|
|
bool OctreeLoader::BuildNodePool(BaseTree* tree, std::string poolType, std::string poolFullFilename, std::vector<unsigned8>& outPool, unsigned& outPoolSize, bool verbose)
|
|
{
|
|
Stopwatch watch;
|
|
if (verbose) printf("Building node pool (%s)...", PoolBuilderFactory::GetReadableName(poolType).c_str());
|
|
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
|
|
watch.Reset();
|
|
builder->BuildPool(tree, outPool);
|
|
outPoolSize = (unsigned32)MathHelper::DivideRoundUp(outPool.size(), TEXTURESIZE * TEXTURESIZE);
|
|
// Try and write the nodepool
|
|
builder->WritePool(poolFullFilename, outPool);
|
|
delete builder;
|
|
|
|
tree->WriteAdditionalPool(poolFullFilename.c_str());
|
|
//if (outPoolSize < 16) outPoolSize = 16;
|
|
outPool.resize(TEXTURESIZE * TEXTURESIZE * outPoolSize);
|
|
if (verbose) printf("Nodepool of size %u generated in %u ms.\n", outPoolSize, (unsigned)(watch.GetTime() * 1000));
|
|
return true;
|
|
}
|
|
|
|
bool OctreeLoader::ReadNodePool(BaseTree* tree, std::string poolType, std::string poolFileName, std::vector<unsigned8>& outPool, unsigned& outPoolSize, bool verbose)
|
|
{
|
|
Stopwatch watch;
|
|
watch.Reset();
|
|
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
|
|
if (verbose) printf("Reading node pool (%s) directly... ", PoolBuilderFactory::GetReadableName(poolType).c_str());
|
|
bool success = builder->ReadPool(poolFileName, outPool);
|
|
if (success)
|
|
{
|
|
// if reading succeeded, return the
|
|
outPoolSize = (unsigned32)MathHelper::DivideRoundUp(outPool.size(), TEXTURESIZE * TEXTURESIZE);
|
|
//if (outPoolSize < 16) outPoolSize = 16;
|
|
outPool.resize(TEXTURESIZE * TEXTURESIZE * outPoolSize);
|
|
tree->ReadAdditionalPool(poolFileName.c_str());
|
|
if (verbose) printf("Reading node pool succeeded in %u ms.\n", (unsigned)(watch.GetTime() * 1000));
|
|
} else
|
|
if (verbose) printf("Reading directly failed.\n");
|
|
delete builder;
|
|
return success;
|
|
}
|
|
|
|
bool OctreeLoader::HasMaterialTexture(BaseTree* tree)
|
|
{
|
|
// If the tree can be cast to an IMaterialTexture interface, it has a material texture
|
|
return dynamic_cast<IMaterialTexture*>(tree) != NULL;
|
|
}
|
|
|
|
bool OctreeLoader::GetMaterialTexture(BaseTree* tree, std::string treeType, std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize)
|
|
{
|
|
if (HasMaterialTexture(tree))
|
|
{
|
|
auto materialTextureTree = dynamic_cast<IMaterialTexture*>(tree);
|
|
outMaterialTexture = materialTextureTree->GetMaterialTexture();
|
|
outMaterialTextureSize = materialTextureTree->GetMaterialTextureSize();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool OctreeLoader::HasBlockTexture(BaseTree* tree)
|
|
{
|
|
return dynamic_cast<IBlockTexture*>(tree) != NULL;
|
|
}
|
|
|
|
bool OctreeLoader::GetBlockPointerPool(BaseTree* tree, std::string treeType, std::vector<unsigned8>& outBlockPointerPool)
|
|
{
|
|
if (HasBlockTexture(tree))
|
|
{
|
|
auto uTree = dynamic_cast<IBlockTexture*>(tree);
|
|
outBlockPointerPool = uTree->GetBlockPointerPool();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool OctreeLoader::GetBlockPool(BaseTree* tree, std::string treeType, std::vector<unsigned8>& outBlockPool)
|
|
{
|
|
if (HasBlockTexture(tree))
|
|
{
|
|
auto uTree = dynamic_cast<IBlockTexture*>(tree);
|
|
outBlockPool = uTree->GetBlockPool();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool OctreeLoader::HasAdditionalProperties(BaseTree* tree)
|
|
{
|
|
return dynamic_cast<IAdditionalProperties*>(tree) != NULL;
|
|
}
|
|
|
|
bool OctreeLoader::GetAdditionalProperties(BaseTree* tree, std::string treeType, std::string poolType, std::map<std::string, std::string>& outAdditionalProperties)
|
|
{
|
|
if (HasAdditionalProperties(tree))
|
|
{
|
|
auto uTree = dynamic_cast<IAdditionalProperties*>(tree);
|
|
outAdditionalProperties = uTree->GetAdditionalProperties();
|
|
}
|
|
// Some types have specific additional properties:
|
|
auto descr = TreeTypeParser::GetTreeTypeDescriptor(treeType);
|
|
|
|
std::string material = "MT_NONE";
|
|
if (descr.material == "c") material = "MT_COLOR";
|
|
else if (descr.material == "n") material = "MT_NORMAL";
|
|
else if (descr.material == "cn") material = "MT_COLORNORMAL";
|
|
else if (descr.material == "cnr") material = "MT_COLORNORMALREFLECTIVITY";
|
|
else if (descr.material == "co") material = "MT_COLOROPACITY";
|
|
outAdditionalProperties.insert(std::make_pair("Material", material));
|
|
|
|
if (descr.material == "n" || descr.material == "cn" || descr.material == "cnr") outAdditionalProperties.insert(std::make_pair("NormalSize", std::to_string(SmallNormal::BITS)));
|
|
|
|
std::string globalTypeString;
|
|
switch (descr.globalType)
|
|
{
|
|
case MULTIROOT: globalTypeString = "TT_MULTIROOT"; break;
|
|
case HIERARCHICAL: globalTypeString = (descr.additionalTypeInfo == "s") ? "TT_HIERARCHICALSHIFT" : "TT_HIERARCHICAL"; break;
|
|
case ONLYMATERIAL: globalTypeString = "TT_ONLYMATERIAL"; break;
|
|
case UNIQUEINDEX: globalTypeString = (descr.additionalTypeInfo != "" && descr.additionalTypeInfo[0] == 's') ? "TT_UNIQUEINDEXSHIFT" : "TT_UNIQUEINDEX"; break;
|
|
case RANDOM: globalTypeString = "TT_RANDOM"; break;
|
|
case BITTREES: globalTypeString = "TT_BITTREES"; break;
|
|
case STANDARD: default: globalTypeString = "TT_STANDARD"; break;
|
|
}
|
|
outAdditionalProperties.insert(std::pair<std::string, std::string>("TreeType", globalTypeString));
|
|
|
|
std::string poolTypeString;
|
|
PoolBuilderType poolTypeEnum = PoolBuilderFactory::GetType(poolType);
|
|
switch (poolTypeEnum)
|
|
{
|
|
case ORIGINAL: poolTypeString = "PT_ORIGINAL"; break;
|
|
case STANDARDPOOL: poolTypeString = "PT_STANDARD"; break;
|
|
case ADAPTIVEDIRECT1: poolTypeString = "PT_ADAPTIVEDIRECT1"; break;
|
|
case ADAPTIVELOOKUP1: poolTypeString = "PT_ADAPTIVELOOKUP1"; break;
|
|
case ADAPTIVEDIRECT2: poolTypeString = "PT_ADAPTIVEDIRECT2"; break;
|
|
case ADAPTIVELOOKUP2: poolTypeString = "PT_ADAPTIVELOOKUP2"; break;
|
|
case VIRTUALNODES: poolTypeString = "PT_VIRTUALNODES"; break;
|
|
}
|
|
outAdditionalProperties.insert(std::make_pair("PoolType", poolTypeString));
|
|
|
|
if (descr.globalType == UNIQUEINDEX)
|
|
{
|
|
std::string compressionType = "";
|
|
CompressionType cType = CompressedTextureFactory<MaterialLibraryPointer>::GetCompressionType(descr.textureCompressor);
|
|
if (cType == BASIC)
|
|
compressionType = "BASIC_PACK";
|
|
else if (cType == TIGHT)
|
|
compressionType = "TIGHT_PACK";
|
|
else if (cType == BLOCK)
|
|
compressionType = "BLOCK_PACK";
|
|
else if (cType == TIGHTBLOCK)
|
|
compressionType = "TIGHTBLOCK_PACK";
|
|
else if (cType == PALETTEBLOCK)
|
|
compressionType = "PALETTE_PACK";
|
|
else if (cType == DAGBASED)
|
|
compressionType = "DAGBASED_PACK";
|
|
else if (cType == MULTIROOTBASED)
|
|
compressionType = "MULTIROOTBASED_PACK";
|
|
outAdditionalProperties.insert(std::pair<std::string, std::string>("TextureCompression", compressionType));
|
|
}
|
|
|
|
if (descr.globalType == MULTIROOT)
|
|
{
|
|
outAdditionalProperties.insert(std::pair<std::string, std::string>("BitsPerTree", std::to_string(TreeTypeParser::GetBitsPerTree(descr))));
|
|
outAdditionalProperties.insert(std::pair<std::string, std::string>("BitsPerChannel", std::to_string(TreeTypeParser::GetBitsPerChannel(descr))));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool OctreeLoader::GetPool(
|
|
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
|
|
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
|
|
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
|
|
std::map<std::string, std::string>& outAdditionalProperties)
|
|
{
|
|
return GetPool(SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
|
|
outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outMaterialPool, outMaterialPoolSize,
|
|
outBlockPointerPool, outBlockPool,
|
|
outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
|
|
}
|
|
bool OctreeLoader::GetPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
|
|
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
|
|
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
|
|
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
|
|
std::map<std::string, std::string>& outAdditionalProperties,
|
|
bool verbose)
|
|
{
|
|
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
|
|
bool succes = false;
|
|
switch (globalType)
|
|
{
|
|
case HIERARCHICAL: case BITTREES:
|
|
succes = OctreeLoader::GetHierarchicalPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, verbose); break;
|
|
case ONLYMATERIAL:
|
|
succes = OctreeLoader::GetOnlyMaterialPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outMaterialPool, outMaterialPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, verbose); break;
|
|
case UNIQUEINDEX:
|
|
succes = OctreeLoader::GetUniqueIndexPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outBlockPointerPool, outBlockPool, outAdditionalProperties, verbose); break;
|
|
default:
|
|
succes = OctreeLoader::GetStandardPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outAdditionalProperties, verbose); break;
|
|
}
|
|
return succes;
|
|
}
|
|
|
|
bool OctreeLoader::GetStandardPool(std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::map<std::string, std::string>& outAdditionalProperties)
|
|
{
|
|
return GetStandardPool(
|
|
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
|
|
outPool, outPoolSize, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
|
|
}
|
|
|
|
|
|
bool OctreeLoader::GetStandardPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
|
|
std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::map<std::string, std::string>& outAdditionalProperties, bool verbose)
|
|
{
|
|
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
|
|
// Standard, Colored and Multiroot all use the same type of pool
|
|
if (globalType != STANDARD && globalType != MULTIROOT && globalType != RANDOM)
|
|
return false;
|
|
|
|
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
|
|
if (usePoolCache)
|
|
{
|
|
// Try and read the pool cache
|
|
// Create a root of the correct type to try and read the pool
|
|
BaseTree* tree = CreateTree(treeType, maxLevel);
|
|
bool readSucces = ReadNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
|
|
if (readSucces) readSucces &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
|
|
if (readSucces && verbose) PrintGPUMemoryRequirements(outPool.size(), 0, 0, 0);
|
|
delete tree;
|
|
if (readSucces)
|
|
return true;
|
|
}
|
|
|
|
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
|
|
BaseTree* tree = ReadCache(treeType, maxLevel, filename, verbose);
|
|
if (tree == NULL)
|
|
return false;
|
|
bool succes = BuildNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
|
|
if (succes) succes &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
|
|
if (verbose && succes) PrintGPUMemoryRequirements(treeType, poolType, maxLevel, tree);
|
|
delete tree;
|
|
return succes;
|
|
}
|
|
|
|
bool OctreeLoader::GetHierarchicalPool(std::vector<unsigned8>& outPool, unsigned& outPoolSize,
|
|
std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::map<std::string, std::string>& outAdditionalProperties)
|
|
{
|
|
return GetHierarchicalPool(
|
|
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
|
|
outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
|
|
}
|
|
|
|
bool OctreeLoader::GetHierarchicalPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
|
|
std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::map<std::string, std::string>& outAdditionalProperties,
|
|
bool verbose)
|
|
{
|
|
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
|
|
if (globalType != HIERARCHICAL && globalType != BITTREES)
|
|
return false;
|
|
|
|
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
|
|
if (usePoolCache)
|
|
{
|
|
// Try and read the pool cache
|
|
// Create a root of the correct type to try and read the pool
|
|
BaseTree* tree = CreateTree(treeType, maxLevel);
|
|
bool readSucces = ReadNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
|
|
if (readSucces) readSucces &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
|
|
if (readSucces) readSucces &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
|
|
if (readSucces && verbose) PrintGPUMemoryRequirements(outPool.size(), outMaterialTexture.size(), 0, 0);
|
|
delete tree;
|
|
if (readSucces)
|
|
return true;
|
|
}
|
|
|
|
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
|
|
BaseTree* tree = ReadCache(treeType, maxLevel, filename, verbose);
|
|
if (tree == NULL)
|
|
return false;
|
|
bool succes = BuildNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
|
|
succes &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
|
|
if (succes) succes &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
|
|
if (verbose) PrintGPUMemoryRequirements(treeType, poolType, maxLevel, tree);
|
|
delete tree;
|
|
return succes;
|
|
}
|
|
|
|
bool OctreeLoader::GetOnlyMaterialPool(
|
|
std::vector<unsigned8>& outGeometryPool, unsigned& outGeometryPoolSize,
|
|
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
|
|
std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::map<std::string, std::string>& outAdditionalProperties)
|
|
{
|
|
return GetOnlyMaterialPool(
|
|
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
|
|
outGeometryPool, outGeometryPoolSize, outMaterialPool, outMaterialPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
|
|
}
|
|
bool OctreeLoader::GetOnlyMaterialPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
|
|
std::vector<unsigned8>& outGeometryPool, unsigned& outGeometryPoolSize,
|
|
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
|
|
std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::map<std::string, std::string>& outAdditionalProperties,
|
|
bool verbose)
|
|
{
|
|
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
|
|
if (globalType != ONLYMATERIAL)
|
|
return false;
|
|
|
|
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
|
|
bool geometryReadSucces = false;
|
|
bool materialReadSucces = false;
|
|
if (usePoolCache)
|
|
{
|
|
// Try and read the pool cache for both the
|
|
// Create a root of the correct type to try and read the pool
|
|
BaseTree* geometryTree = CreateTree("s", maxLevel);
|
|
geometryReadSucces = ReadNodePool(geometryTree, poolType, GetFullFilename("s", maxLevel, filename), outGeometryPool, outGeometryPoolSize);
|
|
delete geometryTree;
|
|
|
|
BaseTree* materialTree = CreateTree(treeType, maxLevel);
|
|
materialReadSucces &= ReadNodePool(materialTree, poolType, poolFilename, outMaterialPool, outMaterialPoolSize, verbose);
|
|
if (materialReadSucces)
|
|
materialReadSucces &= GetMaterialTexture(materialTree, treeType, outMaterialTexture, outMaterialTextureSize);
|
|
|
|
if (materialReadSucces) materialReadSucces &= GetAdditionalProperties(materialTree, treeType, poolType, outAdditionalProperties);
|
|
|
|
delete materialTree;
|
|
if (geometryReadSucces && materialReadSucces)
|
|
return true;
|
|
}
|
|
|
|
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
|
|
if (!geometryReadSucces)
|
|
{
|
|
BaseTree* geometryTree = ReadCache("s", maxLevel, filename, verbose);
|
|
if (geometryTree == NULL)
|
|
return false;
|
|
geometryReadSucces = BuildNodePool(geometryTree, poolType, poolFilename, outGeometryPool, outGeometryPoolSize, verbose);
|
|
delete geometryTree;
|
|
}
|
|
if (!materialReadSucces)
|
|
{
|
|
BaseTree* materialTree = ReadCache(treeType, maxLevel, filename, verbose);
|
|
if (materialTree == NULL)
|
|
return false;
|
|
materialReadSucces = BuildNodePool(materialTree, poolType, poolFilename, outMaterialPool, outMaterialPoolSize, verbose);
|
|
materialReadSucces &= GetMaterialTexture(materialTree, treeType, outMaterialTexture, outMaterialTextureSize);
|
|
if (materialReadSucces) materialReadSucces &= GetAdditionalProperties(materialTree, treeType, poolType, outAdditionalProperties);
|
|
delete materialTree;
|
|
}
|
|
return materialReadSucces && geometryReadSucces;
|
|
}
|
|
|
|
bool OctreeLoader::GetUniqueIndexPool(
|
|
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
|
|
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
|
|
std::map<std::string, std::string>& outAdditionalProperties)
|
|
{
|
|
return GetUniqueIndexPool(
|
|
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
|
|
outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outBlockPointerPool, outBlockPool, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
|
|
}
|
|
bool OctreeLoader::GetUniqueIndexPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
|
|
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
|
|
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
|
|
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
|
|
std::map<std::string, std::string>& outAdditionalProperties,
|
|
bool verbose)
|
|
{
|
|
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
|
|
if (globalType != UNIQUEINDEX)
|
|
return false;
|
|
|
|
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
|
|
if (usePoolCache)
|
|
{
|
|
// Try and read the pool cache
|
|
// Create a root of the correct type to try and read the pool
|
|
BaseTree* tree = CreateTree(treeType, maxLevel);
|
|
bool readSucces = ReadNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
|
|
if (readSucces) readSucces &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
|
|
if (readSucces) readSucces &= GetBlockPointerPool(tree, treeType, outBlockPointerPool);
|
|
if (readSucces) readSucces &= GetBlockPool(tree, treeType, outBlockPool);
|
|
if (readSucces) readSucces &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
|
|
if (readSucces && verbose)
|
|
PrintGPUMemoryRequirements(outPool.size(), outMaterialTexture.size(), outBlockPool.size(), outBlockPointerPool.size());
|
|
delete tree;
|
|
if (readSucces)
|
|
return true;
|
|
}
|
|
|
|
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
|
|
BaseTree* tree = ReadCache(treeType, maxLevel, filename, verbose);
|
|
if (tree == NULL)
|
|
return false;
|
|
bool succes = BuildNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
|
|
if (succes) succes &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
|
|
if (succes) succes &= GetBlockPointerPool(tree, treeType, outBlockPointerPool);
|
|
if (succes) succes &= GetBlockPool(tree, treeType, outBlockPool);
|
|
if (succes) succes &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
|
|
if (verbose) PrintGPUMemoryRequirements(treeType, poolType, maxLevel, tree);
|
|
delete tree;
|
|
return succes;
|
|
}
|
|
|
|
size_t OctreeLoader::GetGPUMemoryRequirements()
|
|
{
|
|
return OctreeLoader::GetGPUMemoryRequirements(SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings());
|
|
}
|
|
|
|
size_t OctreeLoader::GetGPUMemoryRequirements(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename)
|
|
{
|
|
BaseTree* tree = OctreeLoader::ReadCache(treeType, maxLevel, filename);
|
|
return GetGPUMemoryRequirements(treeType, poolType, tree);
|
|
}
|
|
|
|
size_t OctreeLoader::GetGPUMemoryRequirements(std::string treeType, std::string poolType, BaseTree* tree)
|
|
{
|
|
// Every tree has the nodepool.
|
|
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
|
|
size_t treePoolSize = builder->GetPoolSize(tree);
|
|
delete builder;
|
|
size_t res = treePoolSize;
|
|
|
|
if (HasMaterialTexture(tree))
|
|
{
|
|
auto materialTree = dynamic_cast<IMaterialTexture*>(tree);
|
|
size_t materialTextureSize = materialTree->GetMaterialTextureSize();
|
|
res += materialTextureSize * materialTextureSize * materialTree->GetMaterialTextureChannelsPerPixel(); // 2D texture with the given channels per pixel
|
|
}
|
|
if (HasBlockTexture(tree))
|
|
{
|
|
auto blockTextureTree = dynamic_cast<IBlockTexture*>(tree);
|
|
size_t blockPointerPoolMemoryRequirements = blockTextureTree->GetBlockPointerPoolSize();
|
|
size_t blockPoolMemoryRequirements = blockTextureTree->GetBlockPoolSize();
|
|
size_t blockTextureMemoryRequirements = blockPointerPoolMemoryRequirements + blockPoolMemoryRequirements;
|
|
res += blockTextureMemoryRequirements;
|
|
printf("Block texture required %.2f MB. (main: %.2f MB, additional: %.2f MB)\n",
|
|
(double)blockTextureMemoryRequirements / (1024.0 * 1024.0),
|
|
(double)blockPoolMemoryRequirements / (1024.0 * 1024.0),
|
|
(double)blockPointerPoolMemoryRequirements / (1024.0 * 1024.0));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
size_t OctreeLoader::GetMainTreeGPUMemoryRequirements()
|
|
{
|
|
std::string treeType = SettingsParser::GetTreeTypeFromSettings();
|
|
BaseTree* tree = OctreeLoader::ReadCache(treeType, SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings());
|
|
size_t res = GetGPUMemoryRequirements(treeType, SettingsParser::GetPoolTypeFromSettings(), tree);
|
|
return res;
|
|
}
|
|
|
|
size_t OctreeLoader::GetMainTreeGPUMemoryRequirements(std::string treeType, std::string poolType, BaseTree* tree)
|
|
{
|
|
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
|
|
size_t treePoolSize = builder->GetPoolSize(tree);
|
|
delete builder;
|
|
return TEXTURESIZE * TEXTURESIZE * MathHelper::DivideRoundUp(treePoolSize, TEXTURESIZE * TEXTURESIZE);
|
|
}
|
|
|
|
void OctreeLoader::PrintGPUMemoryRequirements(std::string treeType, std::string poolType, unsigned8 maxLevel, BaseTree* tree)
|
|
{
|
|
size_t memoryRequirements = GetGPUMemoryRequirements(treeType, poolType, tree);
|
|
printf("Tree requires %11zu bytes (%8.2f MB).\n", memoryRequirements, (double)memoryRequirements / 1048576.0);
|
|
}
|
|
|
|
void OctreeLoader::PrintGPUMemoryRequirements(size_t poolSize, size_t materialTextureSize, size_t blockPoolSize, size_t blockPointerPoolSize)
|
|
{
|
|
size_t memoryRequirements = poolSize + materialTextureSize + blockPoolSize + blockPointerPoolSize;
|
|
printf("Tree requires %11zu bytes (%8.2f MB).\n", memoryRequirements, (double)memoryRequirements / 1048576.0);
|
|
}
|
|
|
|
std::string OctreeLoader::GetFullFilename()
|
|
{
|
|
PropertyLoader::Create();
|
|
auto propertyLoader = PropertyLoader::Instance();
|
|
|
|
std::string filename = propertyLoader->GetProperty("dag_file");
|
|
unsigned8 maxLevel = (unsigned8)std::stoi(propertyLoader->GetProperty("shader_max_level"));
|
|
std::string treeType = propertyLoader->GetProperty("octree_type");
|
|
|
|
return GetFullFilename(treeType, maxLevel, filename);
|
|
}
|
|
|
|
std::string OctreeLoader::GetFullFilename(std::string treeType, unsigned8 maxLevel, std::string filename)
|
|
{
|
|
// Hack: make sure filenames are consistent for soem special tree types
|
|
if (treeType == "m") treeType = "m8";
|
|
|
|
// Convert compression method to normalized compression method
|
|
TreeTypeDescriptor descr = TreeTypeParser::GetTreeTypeDescriptor(treeType);
|
|
if (descr.quantizer != "")
|
|
{
|
|
StringHelper::Replace(treeType, descr.quantizer, ColorQuantizerFactory::GetNormalizedType(descr.quantizer));
|
|
}
|
|
if (descr.globalType == UNIQUEINDEX && descr.additionalTypeInfo != "")
|
|
{
|
|
unsigned8 lod = TreeTypeParser::GetLevelsWithoutMaterials(descr);
|
|
if (lod != 0)
|
|
StringHelper::Replace(treeType, descr.additionalTypeInfo, std::to_string(lod) + "lod");
|
|
}
|
|
|
|
return filename + "_" + std::to_string(maxLevel) + "_" + treeType;
|
|
}
|
|
|
|
BaseTree* OctreeLoader::CreateTree(std::string type, unsigned8 maxLevel)
|
|
{
|
|
BaseTree* tree = NULL;
|
|
TreeTypeDescriptor descr = TreeTypeParser::GetTreeTypeDescriptor(type);
|
|
|
|
switch (descr.globalType)
|
|
{
|
|
case HIERARCHICAL:
|
|
{
|
|
if (descr.material == "c")
|
|
{
|
|
if (descr.additionalTypeInfo == "s")
|
|
tree = new HierarchicalShiftingColoredTree(maxLevel);
|
|
else
|
|
tree = new MaterialLibraryTree<Color, ColorCompare>(maxLevel);
|
|
}
|
|
else if (descr.material == "n")
|
|
tree = new MaterialLibraryTree<SmallNormal, NormalCompare, SmallNormal::BYTES>(maxLevel);
|
|
else if (descr.material == "cn")
|
|
tree = new MaterialLibraryTree<ColorAndNormal, ColorAndNormalCompare, ColorAndNormal::CHANNELSPERPIXEL>(maxLevel);
|
|
else if (descr.material == "cnr")
|
|
tree = new MaterialLibraryTree<ColorAndNormalAndValue, ColorAndNormalAndValueCompare, ColorAndNormalAndValue::CHANNELSPERPIXEL>(maxLevel);
|
|
else if (descr.material == "co")
|
|
tree = new MaterialLibraryTree<ColorAndOpacity, ColorAndOpacityCompare, ColorAndOpacity::CHANNELSPERPIXEL>(maxLevel);
|
|
break;
|
|
}
|
|
case ONLYMATERIAL:
|
|
{
|
|
tree = new HierarchicalColorsOnlyTree(maxLevel);
|
|
break;
|
|
}
|
|
case UNIQUEINDEX:
|
|
{
|
|
unsigned8 levelsWithoutMaterials = TreeTypeParser::GetLevelsWithoutMaterials(descr);
|
|
if (descr.additionalTypeInfo != "" && descr.additionalTypeInfo[0] == 's')
|
|
{
|
|
assert(descr.material != "n");
|
|
auto texture = CompressedTextureFactory<SignedIntMaterial>::GetCompressedTexture(descr.textureCompressor);
|
|
tree = new UniqueIndexShiftTree<Color, ColorCompare>(maxLevel, texture, levelsWithoutMaterials);
|
|
}
|
|
else
|
|
{
|
|
auto texture = CompressedTextureFactory<MaterialLibraryPointer>::GetCompressedTexture(descr.textureCompressor);
|
|
if (descr.material == "c")
|
|
tree = new MaterialLibraryUniqueIndexTree<Color, ColorCompare>(maxLevel, texture, levelsWithoutMaterials);
|
|
else if (descr.material == "n")
|
|
tree = new MaterialLibraryUniqueIndexTree<SmallNormal, NormalCompare, SmallNormal::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
|
|
else if (descr.material == "cn")
|
|
tree = new MaterialLibraryUniqueIndexTree<ColorAndNormal, ColorAndNormalCompare, ColorAndNormal::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
|
|
else if (descr.material == "cnr")
|
|
tree = new MaterialLibraryUniqueIndexTree<ColorAndNormalAndValue, ColorAndNormalAndValueCompare, ColorAndNormalAndValue::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
|
|
else if (descr.material == "co")
|
|
tree = new MaterialLibraryUniqueIndexTree<ColorAndOpacity, ColorAndOpacityCompare, ColorAndOpacity::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
|
|
else
|
|
delete texture;
|
|
}
|
|
break;
|
|
}
|
|
case MULTIROOT:
|
|
{
|
|
std::vector<std::string> additionalTypes(8);
|
|
additionalTypes[0] = "1";
|
|
additionalTypes[1] = "2";
|
|
additionalTypes[2] = "3";
|
|
additionalTypes[3] = "4";
|
|
additionalTypes[4] = "5";
|
|
additionalTypes[5] = "6";
|
|
additionalTypes[6] = "7";
|
|
additionalTypes[7] = "8";
|
|
if (descr.additionalTypeInfo == "cc")
|
|
{
|
|
tree = new LeafMaterialMultiRootTree<ColorChannel>(maxLevel, 3);
|
|
}
|
|
else if (CollectionHelper::Contains(additionalTypes, descr.additionalTypeInfo))
|
|
{
|
|
unsigned8 bitsPerChannel = TreeTypeParser::GetBitsPerChannel(descr);
|
|
tree = new MultiRootTree<>(maxLevel, 3 * bitsPerChannel);
|
|
}
|
|
else
|
|
{
|
|
unsigned8 bitsPerChannel = TreeTypeParser::GetBitsPerChannel(descr);
|
|
unsigned8 bitsPerTree = TreeTypeParser::GetBitsPerTree(descr);
|
|
unsigned8 treesPerChannel = bitsPerChannel / bitsPerTree + (bitsPerChannel % bitsPerTree == 0 ? 0 : 1);
|
|
switch (bitsPerTree)
|
|
{
|
|
case 1: tree = new LeafMaterialMultiRootTree<BitsMaterial<1>>(maxLevel, 3 * treesPerChannel); break;
|
|
case 2: tree = new LeafMaterialMultiRootTree<BitsMaterial<2>>(maxLevel, 3 * treesPerChannel); break;
|
|
case 3: tree = new LeafMaterialMultiRootTree<BitsMaterial<3>>(maxLevel, 3 * treesPerChannel); break;
|
|
case 4: tree = new LeafMaterialMultiRootTree<BitsMaterial<4>>(maxLevel, 3 * treesPerChannel); break;
|
|
case 5: tree = new LeafMaterialMultiRootTree<BitsMaterial<5>>(maxLevel, 3 * treesPerChannel); break;
|
|
case 6: tree = new LeafMaterialMultiRootTree<BitsMaterial<6>>(maxLevel, 3 * treesPerChannel); break;
|
|
case 7: tree = new LeafMaterialMultiRootTree<BitsMaterial<7>>(maxLevel, 3 * treesPerChannel); break;
|
|
case 8: tree = new LeafMaterialMultiRootTree<BitsMaterial<8>>(maxLevel, 3 * treesPerChannel); break;
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
case RANDOM:
|
|
{
|
|
tree = new MaterialTree<BitsMaterial<1>, HashComparer<BitsMaterial<1>>>(maxLevel); break;
|
|
}
|
|
case BITTREES:
|
|
{
|
|
if (descr.additionalTypeInfo == "l")
|
|
tree = new MaterialLibraryMultiRoot<Color, ColorCompare>(maxLevel);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
tree = new Tree<>(maxLevel);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return tree;
|
|
} |