// // VoxelNodeBag.cpp // hifi // // Created by Brad Hefta-Gaub on 4/25/2013 // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // // This class is used by the VoxelTree:encodeTreeBitstream() functions to store extra nodes that need to be sent // it's a generic bag style storage mechanism. But It has the property that you can't put the same node into the bag // more than once (in other words, it de-dupes automatically), also, it supports collapsing it's several peer nodes // into a parent node in cases where you add enough peers that it makes more sense to just add the parent. // #include "VoxelNodeBag.h" #include VoxelNodeBag::~VoxelNodeBag() { if (_bagElements) { delete[] _bagElements; } } const int GROW_BAG_BY = 500; // put a node into the bag void VoxelNodeBag::insert(VoxelNode* node) { // Search for where we should live in the bag (sorted) // Note: change this to binary search... instead of linear! int insertAt = _elementsInUse; for (int i = 0; i < _elementsInUse; i++) { // compare the newNode to the elements already in the bag OctalTreeDepth comparison = compareOctalCodes(_bagElements[i]->octalCode,node->octalCode); // If we found a code in the bag that matches, then just return, since the element is already in the bag. if (comparison == EXACT_MATCH) { return; // exit early!! } // if we found a node "greater than" the inserted node, then // we want to insert our node here. if (comparison == GREATER_THAN) { insertAt = i; break; } } // at this point, inserAt will be the location we want to insert at. // If we don't have room in our bag, then grow the bag if (_sizeOfElementsArray < _elementsInUse+1) { VoxelNode** oldBag = _bagElements; _bagElements = new VoxelNode*[_sizeOfElementsArray + GROW_BAG_BY]; _sizeOfElementsArray += GROW_BAG_BY; // If we had an old bag... if (oldBag) { // copy old elements into the new bag, but leave a space where we need to // insert the new node memcpy(_bagElements, oldBag, insertAt*sizeof(VoxelNode*)); memcpy(&_bagElements[insertAt+1], &oldBag[insertAt], (_elementsInUse-insertAt)*sizeof(VoxelNode*)); } } else { // move existing elements further back in the bag array, leave a space where we need to // insert the new node memmove(&_bagElements[insertAt+1], &_bagElements[insertAt], (_elementsInUse-insertAt)*sizeof(VoxelNode*)); } _bagElements[insertAt] = node; _elementsInUse++; } // pull a node out of the bag (could come in any order) VoxelNode* VoxelNodeBag::extract() { // pull the last node out, and shrink our list... if (_elementsInUse) { // get the last element VoxelNode* node = _bagElements[_elementsInUse-1]; // reduce the count _elementsInUse--; // debug!! printf("VoxelNodeBag::extract() node="); node->printDebugDetails(""); return node; } return NULL; }