#pragma once // Dynamic arrays are more memory efficient (as they don't require explicitly storing the capacity, size, etc) // But using them is less save. In Windows it seems to work fine, but segmentation errors occur on linux using dynamic arrays. #define USE_DYNAMIC_ARRAY #include #include #include #include "../../inc/glm/glm.hpp" #include "../../core/Defines.h" #include "../../core/Util/SmallDynamicArray.h" #include "ChildMask.h" class BaseTree; class Node { public: Node(const BaseTree* rootIndex, unsigned8 level = 0); //Node(const Node& node); // Copy ctor Node(Node&& node) { mChildren = std::move(node.mChildren); mIndex = std::move(node.mIndex); mChildMask = std::move(node.mChildMask); mLevel = std::move(node.mLevel); mTree = std::move(node.mTree); }// Move ctor //Node(const Node& node) { // mChildren = node.mChildren); //} //Node& operator=(const Node&) = default; ~Node(); //Node& operator=(const Node& other); // Copy assignment Node& operator=(Node&& other) // Move assignment { mChildren = std::move(other.mChildren); mIndex = std::move(other.mIndex); mChildMask = std::move(other.mChildMask); mLevel = std::move(other.mLevel); mTree = std::move(other.mTree); return *this; } void SetChild(const ChildIndex index, Node* child); Node* GetChild(const ChildIndex index) const; inline bool HasChild(const ChildIndex index) const { return mChildMask.Get(index); } inline unsigned GetChildIndex(const ChildIndex index) const { if (!HasChild(index)) return 0; ChildIndex vIndex = mChildMask.GetSetBefore(index); return mChildren[vIndex]; } inline bool HasChildren() const { return mChildMask.mask != 0; } inline unsigned* GetChildren() const { return (unsigned*)&mChildren[0]; } // Replaces the current children of this node by the children in the given array of children. // The given array should have at least as many members as the number of set bits in the new child mask. void SetChildren(ChildMask mask, const unsigned* children); void MoveToTree(BaseTree* tree); // Returns the number of direct children this node has (e.g. the number of "1" in the childmask) inline unsigned8 GetChildCount() const { return mChildMask.GetSet(); } inline unsigned8 GetLevel() const { return mLevel; } inline void SetLevel(unsigned8 level) { mLevel = level; } inline unsigned GetIndex() const { return mIndex; } inline void SetIndex(unsigned32 index) { mIndex = index; } // If the tree type is equal to the current tree type, moved the node to the new tree. inline ChildMask GetChildmask() const { return mChildMask; } // Returns the total number of octree nodes (including the current node) that can be reached from this nodes unsigned64 GetOctreeNodeCount(bool (*f)(const Node*)) const; unsigned64 GetOctreeNodeCount() const { return GetOctreeNodeCount([](const Node* node) { return true; }); } // Returns the number of leaf voxels in this octree (if it wasn't compressed) unsigned64 GetLeafVoxelCount() const; // Returns true if this node is smaller than the other node. Used for sorting bool Compare(const Node& node) const; // Returns true if this node is equal to the other node bool Equals(const Node& node) const; // Adds the the given to the tree at the given coordinate. The node should specify at which level it needs to be added. If a node already exists at the given coordinate, // false is returned Node* AddNode(glm::uvec3 coordinates, const unsigned8 level); bool HasNode(glm::uvec3 coord, const unsigned8 level) const; ChildIndex GetChildIndex(const glm::uvec3 coord, const unsigned8 level) const; void SetChildIndex(const ChildIndex index, const unsigned32 childIndex); void Traverse(const std::function& f) const; void WriteProperties(std::ostream& file); void ReadProperties(std::istream& file); void CopyProperties(Node* source); protected: Node* AddChild(const ChildIndex index); #ifdef USE_DYNAMIC_ARRAY SmallDynamicArray mChildren; // Array (with length of the number of children), containing the indices of child nodes #else std::vector mChildren; #endif unsigned32 mIndex; ChildMask mChildMask; unsigned8 mLevel; // the level of the current node, where the root has level 0 unsigned16 mTree; // the tree to which this node };