From 97070607eaad994267dfad5441447d49d0f77bab Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 28 Oct 2013 14:43:27 -0700 Subject: [PATCH] added SIMPLE_EXTERNAL_CHILDREN mode, which saves on most of our child VoxelNode children storage without being too complicated --- libraries/voxels/src/VoxelNode.cpp | 82 +++++++++++++++++++++++++++++- libraries/voxels/src/VoxelNode.h | 18 +++++-- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index a1f6d9aa7e..4ba90c87c0 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -83,7 +83,11 @@ void VoxelNode::init(unsigned char * octalCode) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { _simpleChildArray[i] = NULL; } -#endif +#endif + +#ifdef SIMPLE_EXTERNAL_CHILDREN + _children.single = NULL; +#endif _unknownBufferIndex = true; setBufferIndex(GLBUFFER_INDEX_UNKNOWN); @@ -335,6 +339,31 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const { return _simpleChildArray[childIndex]; #endif // SIMPLE_CHILD_ARRAY +#ifdef SIMPLE_EXTERNAL_CHILDREN + int childCount = getChildCount(); + + switch (childCount) { + case 0: { + return NULL; + } break; + + case 1: { + // if our single child is the one being requested, return it, otherwise + // return null + int firstIndex = getNthBit(_childBitmask, 1); + if (firstIndex == childIndex) { + return _children.single; + } else { + return NULL; + } + } break; + + default : { + return _children.external[childIndex]; + } break; + } +#endif // def SIMPLE_EXTERNAL_CHILDREN + #ifdef BLENDED_UNION_CHILDREN PerformanceWarning warn(false,"getChildAtIndex",false,&_getChildAtIndexTime,&_getChildAtIndexCalls); VoxelNode* result = NULL; @@ -718,8 +747,57 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { _childrenCount[previousChildCount]--; _childrenCount[newChildCount]++; } - #endif + +#ifdef SIMPLE_EXTERNAL_CHILDREN + + int firstIndex = getNthBit(_childBitmask, 1); + int secondIndex = getNthBit(_childBitmask, 2); + + int previousChildCount = getChildCount(); + if (child) { + setAtBit(_childBitmask, childIndex); + } else { + clearAtBit(_childBitmask, childIndex); + } + int newChildCount = getChildCount(); + + // track our population data + if (previousChildCount != newChildCount) { + _childrenCount[previousChildCount]--; + _childrenCount[newChildCount]++; + } + + if ((previousChildCount == 0 || previousChildCount == 1) && newChildCount == 0) { + _children.single = NULL; + } else if (previousChildCount == 0 && newChildCount == 1) { + _children.single = child; + } else if (previousChildCount == 1 && newChildCount == 2) { + VoxelNode* previousChild = _children.single; + _children.external = new VoxelNode*[NUMBER_OF_CHILDREN]; + memset(_children.external, 0, sizeof(VoxelNode*) * NUMBER_OF_CHILDREN); + _children.external[firstIndex] = previousChild; + _children.external[childIndex] = child; + + _externalChildrenMemoryUsage += NUMBER_OF_CHILDREN * sizeof(VoxelNode*); + + } else if (previousChildCount == 2 && newChildCount == 1) { + assert(child == NULL); // we are removing a child, so this must be true! + VoxelNode* previousFirstChild = _children.external[firstIndex]; + VoxelNode* previousSecondChild = _children.external[secondIndex]; + delete[] _children.external; + _externalChildrenMemoryUsage -= NUMBER_OF_CHILDREN * sizeof(VoxelNode*); + if (childIndex == firstIndex) { + _children.single = previousSecondChild; + } else { + _children.single = previousFirstChild; + } + } else { + _children.external[childIndex] = child; + } + +#endif // def SIMPLE_EXTERNAL_CHILDREN + #ifdef BLENDED_UNION_CHILDREN PerformanceWarning warn(false,"setChildAtIndex",false,&_setChildAtIndexTime,&_setChildAtIndexCalls); diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 07a49e75b9..17760f0514 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -10,7 +10,8 @@ #define __hifi__VoxelNode__ //#define HAS_AUDIT_CHILDREN -#define SIMPLE_CHILD_ARRAY +//#define SIMPLE_CHILD_ARRAY +#define SIMPLE_EXTERNAL_CHILDREN #include #include "AABox.h" @@ -144,9 +145,11 @@ public: static uint64_t getExternalChildrenCount() { return _externalChildrenCount; } static uint64_t getChildrenCount(int childCount) { return _childrenCount[childCount]; } +#ifdef BLENDED_UNION_CHILDREN #ifdef HAS_AUDIT_CHILDREN void auditChildren(const char* label) const; #endif // def HAS_AUDIT_CHILDREN +#endif // def BLENDED_UNION_CHILDREN private: void deleteAllChildren(); @@ -178,7 +181,14 @@ private: /// Client and server, pointers to child nodes, various encodings #ifdef SIMPLE_CHILD_ARRAY - VoxelNode* _simpleChildArray[8]; /// Only used when HAS_AUDIT_CHILDREN is enabled to help debug children encoding + VoxelNode* _simpleChildArray[8]; /// Only used when SIMPLE_CHILD_ARRAY is enabled +#endif + +#ifdef SIMPLE_EXTERNAL_CHILDREN + union children_t { + VoxelNode* single; + VoxelNode** external; + } _children; #endif #ifdef BLENDED_UNION_CHILDREN @@ -188,12 +198,12 @@ private: uint64_t offsetsThreeChildrenEncoded; VoxelNode** external; } _children; -#endif //def BLENDED_UNION_CHILDREN - #ifdef HAS_AUDIT_CHILDREN VoxelNode* _childrenArray[8]; /// Only used when HAS_AUDIT_CHILDREN is enabled to help debug children encoding #endif // def HAS_AUDIT_CHILDREN +#endif //def BLENDED_UNION_CHILDREN + uint32_t _glBufferIndex : 24, /// Client only, vbo index for this voxel if being rendered, 3 bytes _voxelSystemIndex : 8; /// Client only, index to the VoxelSystem rendering this voxel, 1 bytes