Files
CDAG/Research/scene/Octree/Node.h

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
};