#pragma warning(disable:4996) #include "Node.h" #include #include //#include "../PropertyLoader.h" //#include "../Renderer.h" #include "../../core/IntersectTests.h" #include "BaseTree.h" //************************************ // Should only be called on a root node from outside this class //************************************ Node::Node(const BaseTree* tree, unsigned8 level) : mLevel(level), mChildMask(ChildMask(0)), #ifdef USE_DYNAMIC_ARRAY mChildren(SmallDynamicArray()), #else mChildren(std::vector()), #endif mTree(tree != NULL ? tree->GetTreeIndex() : 0) {} //Node::Node(const Node& node) : // mIndex(node.mIndex), // mLevel(node.mLevel), // mTree(node.mTree) //{ // SetChildren(node.mChildMask, node.GetChildren()); //} //Node::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)) //{ //} // //Node& Node::operator=(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); //} //************************************ // Destroys the current node //************************************ Node::~Node() { //printf("Help I'm being killed!\n"); } void Node::Traverse(const std::function& f) const { f.operator()(this); unsigned8 childCount = GetChildCount(); for (unsigned8 i = 0; i < childCount; i++) BaseTree::Get(mTree)->GetNode(mChildren[i])->Traverse(f); } unsigned64 Node::GetOctreeNodeCount(bool (*f)(const Node*)) const { unsigned8 childCount = GetChildCount(); unsigned64 nodeCount = f(this) ? 1 : 0; for (unsigned i = 0; i < childCount; i++) nodeCount += BaseTree::Get(mTree)->GetNode(mChildren[i])->GetOctreeNodeCount(f); return nodeCount; } unsigned64 Node::GetLeafVoxelCount() const { if (mChildMask.mask == 0 || mLevel == BaseTree::Get(mTree)->GetMaxLevel()) // This is e a leaf node! return 1; unsigned long long res = 0; unsigned8 childCount = mChildMask.GetSetBefore(8); for (unsigned i = 0; i < childCount; i++) res += BaseTree::Get(mTree)->GetNode(mChildren[i])->GetLeafVoxelCount(); return res; } Node* Node::AddChild(const ChildIndex index) { Node* curChild = GetChild(index); if (curChild == NULL) { curChild = BaseTree::Get(mTree)->Create(mLevel + 1); SetChild(index, curChild); } return curChild; } Node* Node::GetChild(const ChildIndex index) const { if (!HasChild(index)) return NULL; ChildIndex vIndex = mChildMask.GetSetBefore(index); return BaseTree::Get(mTree)->GetNode(mChildren[vIndex]); } void Node::SetChild(const ChildIndex index, Node* child) { SetChildIndex(index, child->GetIndex()); } void Node::SetChildIndex(const ChildIndex c, const unsigned32 index) { bool isNew = !HasChild(c); unsigned8 oldChildCount = mChildMask.GetSet(); mChildMask.Set(c, true); ChildIndex vIndex = mChildMask.GetSetBefore(c); if (isNew) { #ifdef USE_DYNAMIC_ARRAY mChildren.Insert(vIndex, index, oldChildCount); #else mChildren.insert(mChildren.begin() + vIndex, index); #endif } else mChildren[vIndex] = index; } void Node::SetChildren(ChildMask mask, const unsigned* children) { unsigned8 oldChildCount = mChildMask.GetSet(); unsigned8 newChildCount = mask.GetSet(); mChildMask = mask; #ifdef USE_DYNAMIC_ARRAY if (oldChildCount != newChildCount) mChildren.Resize(oldChildCount, newChildCount); mChildren.SetRange(children, 0, newChildCount); #else mChildren.resize(newChildCount); for (ChildIndex c = 0; c < newChildCount; c++) mChildren[c] = children[c]; #endif } void Node::MoveToTree(BaseTree* tree) { assert(typeid(*(BaseTree::Get(mTree))) == typeid(*tree)); mTree = tree->GetTreeIndex(); } //************************************ // Adds the given node at the given coordinates: recursively adds parents in top-down fashion //************************************ Node* Node::AddNode(glm::uvec3 coordinates, const unsigned8 level) { if (GetLevel() >= level) { if (coordinates.x != 0 || coordinates.y != 0 || coordinates.z != 0) printf("Unexpected root coordinate (%d, %d, %d)\n", coordinates.x, coordinates.y, coordinates.z); return this; } ChildIndex child = GetChildIndex(coordinates, level); unsigned32 mask = BitHelper::GetLSMask(0, level - GetLevel() - 1); coordinates.x &= mask; coordinates.y &= mask; coordinates.z &= mask; return AddChild(child)->AddNode(coordinates, level); } bool Node::HasNode(glm::uvec3 coord, const unsigned8 level) const { // If we reached a node at the wanted level, return true if (mLevel >= level) return true; // Get the wanted child ChildIndex child = GetChildIndex(coord, level); if (HasChild(child)) { unsigned32 mask = BitHelper::GetLSMask(0, level - this->GetLevel() - 1); coord.x &= mask; coord.y &= mask; coord.z &= mask; return GetChild(child)->HasNode(coord, level); } else return false; } ChildIndex Node::GetChildIndex(const glm::uvec3 coord, const unsigned8 level) const { unsigned range = 1 << (level - this->GetLevel() - 1); return (coord.x < range ? 0 : 1) + (coord.y < range ? 0 : 2) + (coord.z < range ? 0 : 4); } void Node::WriteProperties(std::ostream& file) {} void Node::ReadProperties(std::istream& file) {} void Node::CopyProperties(Node* source) {} bool Node::Compare(const Node& node) const { // Then on childmask unsigned8 nodeMask = node.GetChildmask().mask; if (mChildMask.mask != nodeMask) // This is equal to returning false if the highest significant bit in the other childmask is more significant than the highest significant bit in this childmask return mChildMask.mask < nodeMask; // Then on child pointer values unsigned8 childCount = mChildMask.GetSet(); for (unsigned8 i = 0; i < childCount; i++) { // Cast pointer to unsigned number auto aPtr = this->mChildren[i]; auto bPtr = node.mChildren[i]; if (aPtr != bPtr) return aPtr < bPtr; } // Apparently the nodes are equal return false; } bool Node::Equals(const Node& node) const { if (this == &node) // Same address == same node return true; if (this->GetLevel() != node.GetLevel() || this->GetChildmask().mask != node.GetChildmask().mask) return false; unsigned8 childCount = mChildMask.GetSet(); for (unsigned8 i = 0; i < childCount; i++) { if (this->mChildren[i] != node.mChildren[i]) return false; } return true; }