112 lines
5.7 KiB
C++
112 lines
5.7 KiB
C++
#pragma once
|
|
#include <vector>
|
|
#include "BasePoolBuilder.h"
|
|
#include "../Octree/BaseTree.h"
|
|
|
|
// Pool builder class that can be used to build a pool for a specific kind of tree. Constructor should indicate the tree type.
|
|
class BaseTreePoolBuilder : public BasePoolBuilder<BaseTree>
|
|
{
|
|
public:
|
|
BaseTreePoolBuilder() { mIsBuilding = false; }
|
|
virtual ~BaseTreePoolBuilder() override {}
|
|
|
|
size_t GetPoolSize(const BaseTree* tree) override;
|
|
bool BuildPool(const BaseTree* tree, std::vector<unsigned8>& pool) override;
|
|
bool VerifyPool(std::vector<unsigned8>& pool, const unsigned8& depth) const override;
|
|
|
|
size_t GetMinimumNodePoolTexelCount(const BaseTree* tree);
|
|
unsigned32 GetTreeInfoBytesSize(const BaseTree* tree) const;
|
|
|
|
static const size_t WORD_SIZE = 4;
|
|
protected:
|
|
inline static void RoundToWords(size_t& value) { value += (WORD_SIZE - (value % WORD_SIZE)) % WORD_SIZE; }
|
|
|
|
// Returns the size of a node without the pointers (but with the additional pointer, node and nodepool information if needed)
|
|
inline size_t GetBaseNodeSize(const BaseTree* tree, const unsigned32& nodeId) const
|
|
{
|
|
auto node = tree->GetNode(nodeId);
|
|
unsigned8 level = node->GetLevel();
|
|
size_t additionalPointerBytes = 0;
|
|
if (node->GetChildCount() > 0)
|
|
{
|
|
size_t additionalBytesPerPointer = tree->GetAdditionalBytesPerPointer(level);
|
|
// Word-align additional bytes per pointer
|
|
if (WordAligned()) RoundToWords(additionalBytesPerPointer);
|
|
additionalPointerBytes = (node->GetChildCount() - (LastChildHasAdditionalBytesPerPointer(tree) ? 0 : 1)) * additionalBytesPerPointer;
|
|
}
|
|
size_t basicNodeSize = 1 + tree->GetAdditionalBytesPerNode(level) + GetAdditionalPoolInfoForNodeSize(tree, nodeId);
|
|
if (WordAligned()) RoundToWords(basicNodeSize);
|
|
return additionalPointerBytes + basicNodeSize;
|
|
}
|
|
|
|
inline size_t GetNodeSize(const BaseTree* tree, const unsigned32& nodeId) const
|
|
{
|
|
const Node* node = tree->GetNode(nodeId);
|
|
size_t nodeSize = GetBaseNodeSize(tree, nodeId);
|
|
unsigned32* children = node->GetChildren();
|
|
for (ChildIndex c = 0; c < node->GetChildCount(); c++)
|
|
{
|
|
size_t pointerSize = GetBytesPerPointer(tree, children[c]);
|
|
if (WordAligned()) RoundToWords(pointerSize);
|
|
nodeSize += pointerSize;
|
|
}
|
|
return nodeSize;
|
|
}
|
|
|
|
inline bool HasAdditionalBytesPerNode(const BaseTree* tree) const
|
|
{
|
|
std::vector<unsigned8> additionalBytesPerNode = tree->GetAdditionalBytesPerNode();
|
|
bool hasAdditionalBytesPerNode = false; for (auto abpn : additionalBytesPerNode) if (abpn != 0) hasAdditionalBytesPerNode = true;
|
|
return hasAdditionalBytesPerNode;
|
|
}
|
|
|
|
inline bool HasAdditionalBytesPerPointer(const BaseTree* tree) const
|
|
{
|
|
std::vector<unsigned8> additionalBytesPerPointer = tree->GetAdditionalBytesPerPointer();
|
|
bool hasAdditionalBytesPerPointer = false; for (auto abpp : additionalBytesPerPointer) if (abpp != 0) hasAdditionalBytesPerPointer = true;
|
|
return hasAdditionalBytesPerPointer;
|
|
}
|
|
|
|
inline bool LastChildHasAdditionalBytesPerPointer(const BaseTree* tree) const
|
|
{
|
|
return tree->LastChildHasAdditionalBytes();
|
|
}
|
|
|
|
// Use this method to pre-calculate information needed to build the tree
|
|
virtual void InitBuild(const BaseTree* tree) = 0;
|
|
// Use this method to finalize the build process and clear resources
|
|
virtual void FinishBuild(const BaseTree* tree) = 0;
|
|
|
|
// Subtrees can use this to ask for the pool to be word aligned. If a subclass returns true, additional pointer and pool sizes will be rounded to word sizes (i.e. 4 bytes)
|
|
virtual bool WordAligned() const = 0;
|
|
|
|
// Should return the number of bytes required for a pointer to the the node with nodeIndex.
|
|
virtual unsigned8 GetBytesPerPointer(const BaseTree* tree, const unsigned32& nodeIndex) const = 0;
|
|
|
|
// Should return the bytes containing a pointer to the node with the given index.
|
|
virtual std::vector<unsigned8> WrapPointer(const BaseTree* root, const unsigned32& nodeIndex, const unsigned32& indexInPool, const unsigned32& pointer) const = 0;
|
|
|
|
// Pool info required for the tree. The size of this should be determined only by the depth of the tree.
|
|
virtual size_t GetPoolInfoSize(const BaseTree* tree) const = 0;
|
|
// Pool info required for the tree (e.g. level offsets in memory, pointer sizes per level).
|
|
virtual std::vector<unsigned8> GetPoolInfo(const BaseTree* tree, const std::vector<size_t>& nodePointers, const std::vector<unsigned32>& nodeOrder) = 0;
|
|
|
|
// Additional pool info of variable size, such as lookup tables.
|
|
virtual size_t GetAdditionalPoolInfoSize(const BaseTree* tree) const { return 0; }
|
|
// Additional pool info of variable size, such as lookup tables.
|
|
virtual std::vector<unsigned8> GetAdditionalPoolInfo(const BaseTree* tree, const std::vector<size_t>& nodePointers, const std::vector<unsigned32>& nodeOrder) { return std::vector<unsigned8>(); }
|
|
|
|
virtual unsigned8 GetAdditionalPoolInfoForNodeSize(const BaseTree* tree, const unsigned32& nodeIndex) const { return 0; }
|
|
virtual std::vector<unsigned8> GetAdditionalPoolInfoForNode(const BaseTree* tree, const unsigned32& nodeIndex, const unsigned32& indexInPool) const { return std::vector<unsigned8>(); }
|
|
|
|
// Can be used to change the order of the nodes in memory.
|
|
virtual void OrderNodes(const BaseTree* tree, std::vector<unsigned32>& nodeOrder) const;
|
|
|
|
std::vector<unsigned8> GetBytesForNode(const BaseTree* tree,const unsigned32& nodeId, const std::vector<size_t>& nodePointers, const std::vector<unsigned32>& reverseNodeMap,
|
|
const std::vector<unsigned8>& additionalBytesPerNode, const std::vector<unsigned8>& additionalBytesPerPointer) const;
|
|
|
|
size_t GetAdditionalTreeInfoStart(const BaseTree* tree) const;
|
|
size_t GetAdditionalPoolInfoStart(const BaseTree* tree) const;
|
|
|
|
bool mIsBuilding;
|
|
}; |