114 lines
4.3 KiB
C++
114 lines
4.3 KiB
C++
#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 <vector>
|
|
#include <functional>
|
|
#include <typeinfo>
|
|
#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<void(const Node*)>& 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<unsigned32> mChildren; // Array (with length of the number of children), containing the indices of child nodes
|
|
#else
|
|
std::vector<unsigned32> 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
|
|
}; |