#pragma once #include #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 { public: BaseTreePoolBuilder() { mIsBuilding = false; } virtual ~BaseTreePoolBuilder() override {} size_t GetPoolSize(const BaseTree* tree) override; bool BuildPool(const BaseTree* tree, std::vector& pool) override; bool VerifyPool(std::vector& 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 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 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 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 GetPoolInfo(const BaseTree* tree, const std::vector& nodePointers, const std::vector& 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 GetAdditionalPoolInfo(const BaseTree* tree, const std::vector& nodePointers, const std::vector& nodeOrder) { return std::vector(); } virtual unsigned8 GetAdditionalPoolInfoForNodeSize(const BaseTree* tree, const unsigned32& nodeIndex) const { return 0; } virtual std::vector GetAdditionalPoolInfoForNode(const BaseTree* tree, const unsigned32& nodeIndex, const unsigned32& indexInPool) const { return std::vector(); } // Can be used to change the order of the nodes in memory. virtual void OrderNodes(const BaseTree* tree, std::vector& nodeOrder) const; std::vector GetBytesForNode(const BaseTree* tree,const unsigned32& nodeId, const std::vector& nodePointers, const std::vector& reverseNodeMap, const std::vector& additionalBytesPerNode, const std::vector& additionalBytesPerPointer) const; size_t GetAdditionalTreeInfoStart(const BaseTree* tree) const; size_t GetAdditionalPoolInfoStart(const BaseTree* tree) const; bool mIsBuilding; };