mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 16:23:39 +02:00
implement support for three children encoding
This commit is contained in:
parent
1e5ce8a7e5
commit
d2bab77c88
6 changed files with 370 additions and 90 deletions
|
@ -48,6 +48,14 @@ bool VoxelPersistThread::process() {
|
|||
unsigned long internalNodeCount = VoxelNode::getInternalNodeCount();
|
||||
unsigned long leafNodeCount = VoxelNode::getLeafNodeCount();
|
||||
qDebug("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount);
|
||||
|
||||
double usecPerGet = (double)VoxelNode::_getChildAtIndexTime / (double)VoxelNode::_getChildAtIndexCalls;
|
||||
double usecPerSet = (double)VoxelNode::_setChildAtIndexTime / (double)VoxelNode::_setChildAtIndexCalls;
|
||||
|
||||
printf("_getChildAtIndexCalls=%llu, _getChildAtIndexTime=%llu, perGet=%lf ... _setChildAtIndexCalls=%llu _setChildAtIndexTime=%llu perSet=%lf\n",
|
||||
VoxelNode::_getChildAtIndexCalls, VoxelNode::_getChildAtIndexTime, usecPerGet,
|
||||
VoxelNode::_setChildAtIndexCalls, VoxelNode::_setChildAtIndexTime, usecPerSet);
|
||||
|
||||
}
|
||||
|
||||
uint64_t MSECS_TO_USECS = 1000;
|
||||
|
|
|
@ -54,17 +54,14 @@ bool VoxelSendThread::process() {
|
|||
}
|
||||
|
||||
// debug some timing...
|
||||
//uint64_t VoxelNode::_getChildAtIndexTime;
|
||||
//uint64_t VoxelNode::_getChildAtIndexCalls;
|
||||
//uint64_t VoxelNode::_setChildAtIndexTime;
|
||||
//uint64_t VoxelNode::_setChildAtIndexCalls;
|
||||
|
||||
/***
|
||||
double usecPerGet = (double)VoxelNode::_getChildAtIndexTime / (double)VoxelNode::_getChildAtIndexCalls;
|
||||
double usecPerSet = (double)VoxelNode::_setChildAtIndexTime / (double)VoxelNode::_setChildAtIndexCalls;
|
||||
|
||||
printf("_getChildAtIndexCalls=%llu, _getChildAtIndexTime=%llu, perGet=%lf ... _setChildAtIndexCalls=%llu _setChildAtIndexTime=%llu perSet=%lf\n",
|
||||
VoxelNode::_getChildAtIndexCalls, VoxelNode::_getChildAtIndexTime, usecPerGet,
|
||||
VoxelNode::_setChildAtIndexCalls, VoxelNode::_setChildAtIndexTime, usecPerSet);
|
||||
***/
|
||||
|
||||
return isStillRunning(); // keep running till they terminate us
|
||||
}
|
||||
|
|
|
@ -148,6 +148,23 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
|
|||
mg_printf(connection, " Internal Nodes: %lu nodes\r\n", internalNodeCount);
|
||||
mg_printf(connection, " Leaf Nodes: %lu leaves\r\n", leafNodeCount);
|
||||
|
||||
mg_printf(connection, "%s", "VoxelNode Children Encoding Statistics...\r\n");
|
||||
mg_printf(connection, " Single or No Children: %10.llu nodes\r\n", VoxelNode::_singleChildrenCount);
|
||||
mg_printf(connection, " Two Children as Offset: %10.llu nodes\r\n", VoxelNode::_twoChildrenOffsetCount);
|
||||
mg_printf(connection, " Two Children as External: %10.llu nodes\r\n", VoxelNode::_twoChildrenExternalCount);
|
||||
mg_printf(connection, " Three Children as Offset: %10.llu nodes\r\n", VoxelNode::_threeChildrenOffsetCount);
|
||||
mg_printf(connection, " Three Children as External: %10.llu nodes\r\n", VoxelNode::_threeChildrenExternalCount);
|
||||
mg_printf(connection, " Children as External Array: %10.llu nodes\r\n", VoxelNode::_externalChildrenCount);
|
||||
|
||||
uint64_t checkSum = VoxelNode::_singleChildrenCount +
|
||||
VoxelNode::_twoChildrenOffsetCount + VoxelNode::_twoChildrenExternalCount +
|
||||
VoxelNode::_threeChildrenOffsetCount + VoxelNode::_threeChildrenExternalCount +
|
||||
VoxelNode::_externalChildrenCount;
|
||||
|
||||
mg_printf(connection, "%s", " ----------------\r\n");
|
||||
mg_printf(connection, " Total: %10.llu nodes\r\n", checkSum);
|
||||
mg_printf(connection, " Expected: %10.lu nodes\r\n", nodeCount);
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
// have mongoose process this request from the document_root
|
||||
|
|
|
@ -65,11 +65,14 @@ void VoxelNode::init(unsigned char * octalCode) {
|
|||
_childBitmask = 0;
|
||||
_childrenExternal = false;
|
||||
_children.external = NULL;
|
||||
_singleChildrenCount++;
|
||||
|
||||
// default pointers to child nodes to NULL
|
||||
/**/
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
_childrenArray[i] = NULL;
|
||||
}
|
||||
/**/
|
||||
|
||||
|
||||
_unknownBufferIndex = true;
|
||||
|
@ -196,7 +199,6 @@ void VoxelNode::deleteChildAtIndex(int childIndex) {
|
|||
_voxelNodeLeafCount++;
|
||||
}
|
||||
}
|
||||
|
||||
auditChildren("deleteChildAtIndex()");
|
||||
}
|
||||
|
||||
|
@ -213,16 +215,16 @@ VoxelNode* VoxelNode::removeChildAtIndex(int childIndex) {
|
|||
_voxelNodeLeafCount++;
|
||||
}
|
||||
}
|
||||
|
||||
auditChildren("removeChildAtIndex()");
|
||||
return returnedChild;
|
||||
}
|
||||
|
||||
void VoxelNode::auditChildren(const char* label) const {
|
||||
return;
|
||||
|
||||
bool auditFailed = false;
|
||||
for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) {
|
||||
VoxelNode* testChildNew = __new__getChildAtIndex(childIndex);
|
||||
VoxelNode* testChildNew = getChildAtIndex(childIndex);
|
||||
VoxelNode* testChildOld = _childrenArray[childIndex];
|
||||
|
||||
if (testChildNew != testChildOld) {
|
||||
|
@ -231,9 +233,15 @@ void VoxelNode::auditChildren(const char* label) const {
|
|||
}
|
||||
|
||||
if (auditFailed) {
|
||||
printf("%s... auditChildren() FAILED <<<< \n", label);
|
||||
printf("%s... auditChildren() %s <<<< \n", label, (auditFailed ? "FAILED" : "PASSED"));
|
||||
printf(" _childrenExternal=%s\n", debug::valueOf(_childrenExternal));
|
||||
printf(" childCount=%d\n", getChildCount());
|
||||
printf(" _childBitmask=");
|
||||
outputBits(_childBitmask);
|
||||
|
||||
|
||||
for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) {
|
||||
VoxelNode* testChildNew = __new__getChildAtIndex(childIndex);
|
||||
VoxelNode* testChildNew = getChildAtIndex(childIndex);
|
||||
VoxelNode* testChildOld = _childrenArray[childIndex];
|
||||
|
||||
printf("child at index %d... testChildOld=%p testChildNew=%p %s \n",
|
||||
|
@ -243,7 +251,6 @@ void VoxelNode::auditChildren(const char* label) const {
|
|||
}
|
||||
printf("%s... auditChildren() <<<< DONE <<<< \n", label);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint64_t VoxelNode::_getChildAtIndexTime = 0;
|
||||
|
@ -251,27 +258,32 @@ uint64_t VoxelNode::_getChildAtIndexCalls = 0;
|
|||
uint64_t VoxelNode::_setChildAtIndexTime = 0;
|
||||
uint64_t VoxelNode::_setChildAtIndexCalls = 0;
|
||||
|
||||
uint64_t VoxelNode::_singleChildrenCount = 0;
|
||||
uint64_t VoxelNode::_twoChildrenOffsetCount = 0;
|
||||
uint64_t VoxelNode::_twoChildrenExternalCount = 0;
|
||||
uint64_t VoxelNode::_threeChildrenOffsetCount = 0;
|
||||
uint64_t VoxelNode::_threeChildrenExternalCount = 0;
|
||||
uint64_t VoxelNode::_externalChildrenCount = 0;
|
||||
|
||||
VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const {
|
||||
PerformanceWarning warn(false,"getChildAtIndex",false,&_getChildAtIndexTime,&_getChildAtIndexCalls);
|
||||
|
||||
VoxelNode* child = __new__getChildAtIndex(childIndex);
|
||||
//VoxelNode* child = _childrenArray[childIndex]; /// *** OLD WAY ****
|
||||
return child;
|
||||
}
|
||||
|
||||
VoxelNode* VoxelNode::__new__getChildAtIndex(int childIndex) const {
|
||||
VoxelNode* result = NULL;
|
||||
int childCount = getChildCount();
|
||||
|
||||
const char* caseStr = NULL;
|
||||
switch (childCount) {
|
||||
case 0:
|
||||
caseStr = "0 child case";
|
||||
break;
|
||||
case 1: {
|
||||
caseStr = "1 child case";
|
||||
int indexOne = getNthBit(_childBitmask, 1);
|
||||
if (indexOne == childIndex) {
|
||||
result = _children.single;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
caseStr = "2 child case";
|
||||
int indexOne = getNthBit(_childBitmask, 1);
|
||||
int indexTwo = getNthBit(_childBitmask, 2);
|
||||
|
||||
|
@ -291,8 +303,38 @@ VoxelNode* VoxelNode::__new__getChildAtIndex(int childIndex) const {
|
|||
}
|
||||
}
|
||||
} break;
|
||||
case 3: {
|
||||
caseStr = "3 child case";
|
||||
int indexOne = getNthBit(_childBitmask, 1);
|
||||
int indexTwo = getNthBit(_childBitmask, 2);
|
||||
int indexThree = getNthBit(_childBitmask, 3);
|
||||
|
||||
if (_childrenExternal) {
|
||||
if (indexOne == childIndex) {
|
||||
result = _children.external[0];
|
||||
} else if (indexTwo == childIndex) {
|
||||
result = _children.external[1];
|
||||
} else if (indexThree == childIndex) {
|
||||
result = _children.external[2];
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
int64_t offsetOne, offsetTwo, offsetThree;
|
||||
decodeThreeOffsets(offsetOne, offsetTwo, offsetThree);
|
||||
|
||||
if (indexOne == childIndex) {
|
||||
result = (VoxelNode*)((uint8_t*)this + offsetOne);
|
||||
} else if (indexTwo == childIndex) {
|
||||
result = (VoxelNode*)((uint8_t*)this + offsetTwo);
|
||||
} else if (indexThree == childIndex) {
|
||||
result = (VoxelNode*)((uint8_t*)this + offsetThree);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
// if we have 3 or more, we know we're in external mode, so we just need to figure out which
|
||||
caseStr = "default";
|
||||
//printf("default case...\n");
|
||||
// if we have 4 or more, we know we're in external mode, so we just need to figure out which
|
||||
// slot in our external array this child is.
|
||||
if (oneAtBit(_childBitmask, childIndex)) {
|
||||
childCount = getChildCount();
|
||||
|
@ -306,16 +348,21 @@ VoxelNode* VoxelNode::__new__getChildAtIndex(int childIndex) const {
|
|||
}
|
||||
} break;
|
||||
}
|
||||
if (result != _childrenArray[childIndex]) {
|
||||
printf("getChildAtIndex() case:%s result<%p> != _childrenArray[childIndex]<%p> <<<<<<<<<< WARNING!!! \n",
|
||||
caseStr, result,_childrenArray[childIndex]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void VoxelNode::storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo) {
|
||||
int64_t offsetOne = (uint8_t*)childOne - (uint8_t*)this;
|
||||
int64_t offsetTwo = (uint8_t*)childTwo - (uint8_t*)this;
|
||||
|
||||
if (isBetween(offsetOne, std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min()) &&
|
||||
isBetween(offsetTwo, std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min())) {
|
||||
|
||||
const int64_t minOffset = std::numeric_limits<int32_t>::min();
|
||||
const int64_t maxOffset = std::numeric_limits<int32_t>::max();
|
||||
|
||||
if (isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset)) {
|
||||
// if previously external, then clean it up...
|
||||
if (_childrenExternal) {
|
||||
delete[] _children.external;
|
||||
|
@ -326,6 +373,8 @@ void VoxelNode::storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo) {
|
|||
// encode in union
|
||||
_children.offsetsTwoChildren[0] = offsetOne;
|
||||
_children.offsetsTwoChildren[1] = offsetTwo;
|
||||
|
||||
_twoChildrenOffsetCount++;
|
||||
} else {
|
||||
// encode in array
|
||||
|
||||
|
@ -336,6 +385,7 @@ void VoxelNode::storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo) {
|
|||
}
|
||||
_children.external[0] = childOne;
|
||||
_children.external[1] = childTwo;
|
||||
_twoChildrenExternalCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,30 +397,124 @@ void VoxelNode::retrieveTwoChildren(VoxelNode*& childOne, VoxelNode*& childTwo)
|
|||
delete[] _children.external;
|
||||
_children.external = NULL; // probably not needed!
|
||||
_childrenExternal = false;
|
||||
_twoChildrenExternalCount--;
|
||||
} else {
|
||||
int64_t offsetOne = _children.offsetsTwoChildren[0];
|
||||
int64_t offsetTwo = _children.offsetsTwoChildren[1];
|
||||
childOne = (VoxelNode*)((uint8_t*)this + offsetOne);
|
||||
childTwo = (VoxelNode*)((uint8_t*)this + offsetTwo);
|
||||
_twoChildrenOffsetCount--;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelNode::decodeThreeOffsets(int64_t& offsetOne, int64_t& offsetTwo, int64_t& offsetThree) const {
|
||||
const uint64_t ENCODE_BITS = 21;
|
||||
const uint64_t ENCODE_MASK = 0xFFFFF;
|
||||
const uint64_t ENCODE_MASK_SIGN = 0x100000;
|
||||
|
||||
uint64_t offsetEncodedOne = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 2)) & ENCODE_MASK;
|
||||
uint64_t offsetEncodedTwo = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 1)) & ENCODE_MASK;
|
||||
uint64_t offsetEncodedThree = (_children.offsetsThreeChildrenEncoded & ENCODE_MASK);
|
||||
|
||||
uint64_t signEncodedOne = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 2)) & ENCODE_MASK_SIGN;
|
||||
uint64_t signEncodedTwo = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 1)) & ENCODE_MASK_SIGN;
|
||||
uint64_t signEncodedThree = (_children.offsetsThreeChildrenEncoded & ENCODE_MASK_SIGN);
|
||||
|
||||
bool oneNegative = signEncodedOne == ENCODE_MASK_SIGN;
|
||||
bool twoNegative = signEncodedTwo == ENCODE_MASK_SIGN;
|
||||
bool threeNegative = signEncodedThree == ENCODE_MASK_SIGN;
|
||||
|
||||
offsetOne = oneNegative ? -offsetEncodedOne : offsetEncodedOne;
|
||||
offsetTwo = twoNegative ? -offsetEncodedTwo : offsetEncodedTwo;
|
||||
offsetThree = threeNegative ? -offsetEncodedThree : offsetEncodedThree;
|
||||
}
|
||||
|
||||
void VoxelNode::encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree) {
|
||||
const uint64_t ENCODE_BITS = 21;
|
||||
const uint64_t ENCODE_MASK = 0xFFFFF;
|
||||
const uint64_t ENCODE_MASK_SIGN = 0x100000;
|
||||
|
||||
uint64_t offsetEncodedOne, offsetEncodedTwo, offsetEncodedThree;
|
||||
if (offsetOne < 0) {
|
||||
offsetEncodedOne = ((-offsetOne & ENCODE_MASK) | ENCODE_MASK_SIGN);
|
||||
} else {
|
||||
offsetEncodedOne = offsetOne & ENCODE_MASK;
|
||||
}
|
||||
offsetEncodedOne = offsetEncodedOne << (ENCODE_BITS * 2);
|
||||
|
||||
if (offsetTwo < 0) {
|
||||
offsetEncodedTwo = ((-offsetTwo & ENCODE_MASK) | ENCODE_MASK_SIGN);
|
||||
} else {
|
||||
offsetEncodedTwo = offsetTwo & ENCODE_MASK;
|
||||
}
|
||||
offsetEncodedTwo = offsetEncodedTwo << ENCODE_BITS;
|
||||
|
||||
if (offsetThree < 0) {
|
||||
offsetEncodedThree = ((-offsetThree & ENCODE_MASK) | ENCODE_MASK_SIGN);
|
||||
} else {
|
||||
offsetEncodedThree = offsetThree & ENCODE_MASK;
|
||||
}
|
||||
_children.offsetsThreeChildrenEncoded = offsetEncodedOne | offsetEncodedTwo | offsetEncodedThree;
|
||||
}
|
||||
|
||||
void VoxelNode::storeThreeChildren(VoxelNode* childOne, VoxelNode* childTwo, VoxelNode* childThree) {
|
||||
int64_t offsetOne = (uint8_t*)childOne - (uint8_t*)this;
|
||||
int64_t offsetTwo = (uint8_t*)childTwo - (uint8_t*)this;
|
||||
int64_t offsetThree = (uint8_t*)childThree - (uint8_t*)this;
|
||||
|
||||
const int64_t minOffset = std::numeric_limits<int16_t>::min(); // -1000000; // std::numeric_limits<int32_t>::min();
|
||||
const int64_t maxOffset = std::numeric_limits<int16_t>::max(); // 1000000; // std::numeric_limits<int32_t>::max();
|
||||
|
||||
if (isBetween(offsetOne, maxOffset, minOffset) &&
|
||||
isBetween(offsetTwo, maxOffset, minOffset) &&
|
||||
isBetween(offsetThree, maxOffset, minOffset)) {
|
||||
// if previously external, then clean it up...
|
||||
if (_childrenExternal) {
|
||||
delete[] _children.external;
|
||||
_children.external = NULL; // probably not needed!
|
||||
_childrenExternal = false;
|
||||
}
|
||||
// encode in union
|
||||
encodeThreeOffsets(offsetOne, offsetTwo, offsetThree);
|
||||
_threeChildrenOffsetCount++;
|
||||
} else {
|
||||
// encode in array
|
||||
|
||||
// if not previously external, then allocate appropriately
|
||||
if (!_childrenExternal) {
|
||||
_childrenExternal = true;
|
||||
_children.external = new VoxelNode*[3];
|
||||
}
|
||||
_children.external[0] = childOne;
|
||||
_children.external[1] = childTwo;
|
||||
_children.external[2] = childThree;
|
||||
_threeChildrenExternalCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelNode::retrieveThreeChildren(VoxelNode*& childOne, VoxelNode*& childTwo, VoxelNode*& childThree) {
|
||||
// If we previously had an external array, then get the
|
||||
if (_childrenExternal) {
|
||||
childOne = _children.external[0];
|
||||
childTwo = _children.external[1];
|
||||
childThree = _children.external[2];
|
||||
delete[] _children.external;
|
||||
_children.external = NULL; // probably not needed!
|
||||
_childrenExternal = false;
|
||||
_threeChildrenExternalCount--;
|
||||
} else {
|
||||
int64_t offsetOne, offsetTwo, offsetThree;
|
||||
decodeThreeOffsets(offsetOne, offsetTwo, offsetThree);
|
||||
|
||||
childOne = (VoxelNode*)((uint8_t*)this + offsetOne);
|
||||
childTwo = (VoxelNode*)((uint8_t*)this + offsetTwo);
|
||||
childThree = (VoxelNode*)((uint8_t*)this + offsetThree);
|
||||
_threeChildrenOffsetCount--;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
|
||||
PerformanceWarning warn(false,"setChildAtIndex",false,&_setChildAtIndexTime,&_setChildAtIndexCalls);
|
||||
__new__setChildAtIndex(childIndex, child);
|
||||
|
||||
/** OLD WAY ****
|
||||
_childrenArray[childIndex] = child;
|
||||
if (child) {
|
||||
setAtBit(_childBitmask, childIndex);
|
||||
} else {
|
||||
clearAtBit(_childBitmask, childIndex);
|
||||
}
|
||||
**/
|
||||
}
|
||||
|
||||
void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
||||
// Here's how we store things...
|
||||
// If we have 0 or 1 children, then we just store them in the _children.single;
|
||||
// If we have 2 children,
|
||||
|
@ -412,8 +556,8 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
childTwo = _children.single;
|
||||
}
|
||||
|
||||
_singleChildrenCount--;
|
||||
storeTwoChildren(childOne, childTwo);
|
||||
|
||||
} else if (previousChildCount == 2 && newChildCount == 1) {
|
||||
// If we had 2 children, and we're removing one, then we know we can go down to single mode
|
||||
assert(child == NULL); // this is the only logical case
|
||||
|
@ -425,6 +569,8 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
VoxelNode* childTwo;
|
||||
|
||||
retrieveTwoChildren(childOne, childTwo);
|
||||
|
||||
_singleChildrenCount++;
|
||||
|
||||
if (keepChildOne) {
|
||||
_children.single = childOne;
|
||||
|
@ -459,41 +605,9 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
childTwo = child;
|
||||
}
|
||||
|
||||
_twoChildrenOffsetCount--; // will end up one or the other
|
||||
storeTwoChildren(childOne, childTwo);
|
||||
}
|
||||
} else if (previousChildCount == 3 && newChildCount == 2) {
|
||||
// If we had 3 children, and now have 2, then we know we are going from an external case to a potential internal case
|
||||
assert(_childrenExternal);
|
||||
|
||||
// We need to determine which children we had, and which one we got rid of...
|
||||
int indexOne = getNthBit(previousChildMask, 1);
|
||||
int indexTwo = getNthBit(previousChildMask, 2);
|
||||
int indexThree = getNthBit(previousChildMask, 3);
|
||||
|
||||
bool removeChildOne = indexOne == childIndex;
|
||||
bool removeChildTwo = indexTwo == childIndex;
|
||||
bool removeChildThree = indexThree == childIndex;
|
||||
|
||||
VoxelNode* childOne = _children.external[0];
|
||||
VoxelNode* childTwo = _children.external[1];
|
||||
VoxelNode* childThree = _children.external[2];
|
||||
|
||||
if (removeChildOne) {
|
||||
childOne = childTwo;
|
||||
childTwo = childThree;
|
||||
} else if (removeChildTwo) {
|
||||
childTwo = childThree;
|
||||
} else {
|
||||
// removing child three, nothing to do.
|
||||
}
|
||||
|
||||
// clean up the external children...
|
||||
_childrenExternal = false;
|
||||
delete[] _children.external;
|
||||
_children.external = NULL;
|
||||
|
||||
storeTwoChildren(childOne, childTwo);
|
||||
|
||||
} else if (previousChildCount == 2 && newChildCount == 3) {
|
||||
// If we had 2 children, and now have 3, then we know we are going to an external case...
|
||||
|
||||
|
@ -505,10 +619,6 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
// Get the existing two children out of their encoding...
|
||||
retrieveTwoChildren(childOne, childTwo);
|
||||
|
||||
// now, allocate the external...
|
||||
_childrenExternal = true;
|
||||
_children.external = new VoxelNode*[3];
|
||||
|
||||
// determine order of the existing children
|
||||
int indexOne = getNthBit(previousChildMask, 1);
|
||||
int indexTwo = getNthBit(previousChildMask, 2);
|
||||
|
@ -523,13 +633,148 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
} else {
|
||||
childThree = child;
|
||||
}
|
||||
storeThreeChildren(childOne, childTwo, childThree);
|
||||
} else if (previousChildCount == 3 && newChildCount == 2) {
|
||||
// If we had 3 children, and now have 2, then we know we are going from an external case to a potential internal case
|
||||
|
||||
// We need to determine which children we had, and which one we got rid of...
|
||||
int indexOne = getNthBit(previousChildMask, 1);
|
||||
int indexTwo = getNthBit(previousChildMask, 2);
|
||||
int indexThree = getNthBit(previousChildMask, 3);
|
||||
|
||||
bool removeChildOne = indexOne == childIndex;
|
||||
bool removeChildTwo = indexTwo == childIndex;
|
||||
bool removeChildThree = indexThree == childIndex;
|
||||
|
||||
VoxelNode* childOne;
|
||||
VoxelNode* childTwo;
|
||||
VoxelNode* childThree;
|
||||
|
||||
// Get the existing two children out of their encoding...
|
||||
retrieveThreeChildren(childOne, childTwo, childThree);
|
||||
|
||||
if (removeChildOne) {
|
||||
childOne = childTwo;
|
||||
childTwo = childThree;
|
||||
} else if (removeChildTwo) {
|
||||
childTwo = childThree;
|
||||
} else {
|
||||
// removing child three, nothing to do.
|
||||
}
|
||||
|
||||
storeTwoChildren(childOne, childTwo);
|
||||
} else if (previousChildCount == 3 && newChildCount == 3) {
|
||||
// If we had 3 children, and now have 3, then we need to determine which item we're replacing...
|
||||
|
||||
// We need to determine which children we had, and which one we got rid of...
|
||||
int indexOne = getNthBit(previousChildMask, 1);
|
||||
int indexTwo = getNthBit(previousChildMask, 2);
|
||||
int indexThree = getNthBit(previousChildMask, 3);
|
||||
|
||||
bool replaceChildOne = indexOne == childIndex;
|
||||
bool replaceChildTwo = indexTwo == childIndex;
|
||||
bool replaceChildThree = indexThree == childIndex;
|
||||
|
||||
VoxelNode* childOne;
|
||||
VoxelNode* childTwo;
|
||||
VoxelNode* childThree;
|
||||
|
||||
// Get the existing two children out of their encoding...
|
||||
retrieveThreeChildren(childOne, childTwo, childThree);
|
||||
|
||||
if (replaceChildOne) {
|
||||
childOne = child;
|
||||
} else if (replaceChildTwo) {
|
||||
childTwo = child;
|
||||
} else {
|
||||
childThree = child;
|
||||
}
|
||||
|
||||
storeThreeChildren(childOne, childTwo, childThree);
|
||||
} else if (previousChildCount == 3 && newChildCount == 4) {
|
||||
// If we had 3 children, and now have 4, then we know we are going to an external case...
|
||||
|
||||
// First, decode the children...
|
||||
VoxelNode* childOne;
|
||||
VoxelNode* childTwo;
|
||||
VoxelNode* childThree;
|
||||
VoxelNode* childFour;
|
||||
|
||||
// Get the existing two children out of their encoding...
|
||||
retrieveThreeChildren(childOne, childTwo, childThree);
|
||||
|
||||
// determine order of the existing children
|
||||
int indexOne = getNthBit(previousChildMask, 1);
|
||||
int indexTwo = getNthBit(previousChildMask, 2);
|
||||
int indexThree = getNthBit(previousChildMask, 3);
|
||||
|
||||
if (childIndex < indexOne) {
|
||||
childFour = childThree;
|
||||
childThree = childTwo;
|
||||
childTwo = childOne;
|
||||
childOne = child;
|
||||
} else if (childIndex < indexTwo) {
|
||||
childFour = childThree;
|
||||
childThree = childTwo;
|
||||
childTwo = child;
|
||||
} else if (childIndex < indexThree) {
|
||||
childFour = childThree;
|
||||
childThree = child;
|
||||
} else {
|
||||
childFour = child;
|
||||
}
|
||||
|
||||
// now, allocate the external...
|
||||
_childrenExternal = true;
|
||||
_children.external = new VoxelNode*[4];
|
||||
|
||||
_children.external[0] = childOne;
|
||||
_children.external[1] = childTwo;
|
||||
_children.external[2] = childThree;
|
||||
_children.external[3] = childFour;
|
||||
_externalChildrenCount++;
|
||||
} else if (previousChildCount == 4 && newChildCount == 3) {
|
||||
// If we had 4 children, and now have 3, then we know we are going from an external case to a potential internal case
|
||||
assert(_childrenExternal);
|
||||
|
||||
// We need to determine which children we had, and which one we got rid of...
|
||||
int indexOne = getNthBit(previousChildMask, 1);
|
||||
int indexTwo = getNthBit(previousChildMask, 2);
|
||||
int indexThree = getNthBit(previousChildMask, 3);
|
||||
int indexFour = getNthBit(previousChildMask, 4);
|
||||
|
||||
bool removeChildOne = indexOne == childIndex;
|
||||
bool removeChildTwo = indexTwo == childIndex;
|
||||
bool removeChildThree = indexThree == childIndex;
|
||||
bool removeChildFour = indexFour == childIndex;
|
||||
|
||||
VoxelNode* childOne = _children.external[0];
|
||||
VoxelNode* childTwo = _children.external[1];
|
||||
VoxelNode* childThree = _children.external[2];
|
||||
VoxelNode* childFour = _children.external[3];
|
||||
|
||||
if (removeChildOne) {
|
||||
childOne = childTwo;
|
||||
childTwo = childThree;
|
||||
childThree = childFour;
|
||||
} else if (removeChildTwo) {
|
||||
childTwo = childThree;
|
||||
childThree = childFour;
|
||||
} else if (removeChildThree) {
|
||||
childThree = childFour;
|
||||
} else {
|
||||
// removing child four, nothing to do.
|
||||
}
|
||||
|
||||
// clean up the external children...
|
||||
_childrenExternal = false;
|
||||
delete[] _children.external;
|
||||
_children.external = NULL;
|
||||
_externalChildrenCount--;
|
||||
|
||||
storeThreeChildren(childOne, childTwo, childThree);
|
||||
} else if (previousChildCount == newChildCount) {
|
||||
// 3 or more children, one item being replaced, we know we're stored externally, we just need to find the one
|
||||
// 4 or more children, one item being replaced, we know we're stored externally, we just need to find the one
|
||||
// that needs to be replaced and replace it.
|
||||
for (int ordinal = 1; ordinal <= 8; ordinal++) {
|
||||
int index = getNthBit(previousChildMask, ordinal);
|
||||
|
@ -541,7 +786,7 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
}
|
||||
}
|
||||
} else if (previousChildCount < newChildCount) {
|
||||
// 3 or more children, one item being added, we know we're stored externally, we just figure out where to insert
|
||||
// 4 or more children, one item being added, we know we're stored externally, we just figure out where to insert
|
||||
// this child pointer into our external list
|
||||
VoxelNode** newExternalList = new VoxelNode*[newChildCount];
|
||||
|
||||
|
@ -569,7 +814,7 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
delete[] _children.external;
|
||||
_children.external = newExternalList;
|
||||
} else if (previousChildCount > newChildCount) {
|
||||
// 3 or more children, one item being removed, we know we're stored externally, we just figure out which
|
||||
// 4 or more children, one item being removed, we know we're stored externally, we just figure out which
|
||||
// item to remove from our external list
|
||||
VoxelNode** newExternalList = new VoxelNode*[newChildCount];
|
||||
|
||||
|
@ -588,9 +833,10 @@ void VoxelNode::__new__setChildAtIndex(int childIndex, VoxelNode* child) {
|
|||
}
|
||||
delete[] _children.external;
|
||||
_children.external = newExternalList;
|
||||
} else {
|
||||
assert(false);
|
||||
printf("THIS SHOULD NOT HAPPEN previousChildCount == %d && newChildCount == %d\n",previousChildCount, newChildCount);
|
||||
}
|
||||
|
||||
// to be deleted...
|
||||
_childrenArray[childIndex] = child;
|
||||
auditChildren("setChildAtIndex()");
|
||||
}
|
||||
|
@ -612,9 +858,6 @@ VoxelNode* VoxelNode::addChildAtIndex(int childIndex) {
|
|||
_isDirty = true;
|
||||
markWithChangedTime();
|
||||
}
|
||||
|
||||
auditChildren("addChildAtIndex()");
|
||||
|
||||
return childAt;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,13 +122,28 @@ public:
|
|||
static uint64_t _setChildAtIndexTime;
|
||||
static uint64_t _setChildAtIndexCalls;
|
||||
|
||||
static uint64_t _singleChildrenCount;
|
||||
static uint64_t _twoChildrenOffsetCount;
|
||||
static uint64_t _twoChildrenExternalCount;
|
||||
static uint64_t _threeChildrenOffsetCount;
|
||||
static uint64_t _threeChildrenExternalCount;
|
||||
static uint64_t _externalChildrenCount;
|
||||
|
||||
void auditChildren(const char* label) const;
|
||||
|
||||
private:
|
||||
void setChildAtIndex(int childIndex, VoxelNode* child);
|
||||
void storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo);
|
||||
void retrieveTwoChildren(VoxelNode*& childOne, VoxelNode*& childTwo);
|
||||
void storeThreeChildren(VoxelNode* childOne, VoxelNode* childTwo, VoxelNode* childThree);
|
||||
void retrieveThreeChildren(VoxelNode*& childOne, VoxelNode*& childTwo, VoxelNode*& childThree);
|
||||
void decodeThreeOffsets(int64_t& offsetOne, int64_t& offsetTwo, int64_t& offsetThree) const;
|
||||
void encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree);
|
||||
|
||||
/**
|
||||
VoxelNode* __new__getChildAtIndex(int childIndex) const;
|
||||
void __new__setChildAtIndex(int childIndex, VoxelNode* child);
|
||||
void auditChildren(const char* label) const;
|
||||
**/
|
||||
|
||||
void calculateAABox();
|
||||
void init(unsigned char * octalCode);
|
||||
|
@ -149,21 +164,18 @@ private:
|
|||
union children_t {
|
||||
VoxelNode* single;
|
||||
int32_t offsetsTwoChildren[2];
|
||||
uint64_t offsetsThreeChildrenA : 21, offsetsThreeChildrenB : 21, offsetsThreeChildrenC : 21 ;
|
||||
uint64_t offsetsThreeChildrenEncoded;
|
||||
VoxelNode** external;
|
||||
} _children;
|
||||
} _children;
|
||||
|
||||
static int64_t _offsetMax;
|
||||
static int64_t _offsetMin;
|
||||
|
||||
//_offsetMax=4,184,812
|
||||
//_offsetMin=-5,828,062
|
||||
|
||||
VoxelNode* _childrenArray[8]; /// Client and server, pointers to child nodes, 64 bytes
|
||||
|
||||
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
|
||||
|
||||
// Support for _voxelSystemIndex, we use these static member variables to track the VoxelSystems that are
|
||||
// in use by various voxel nodes. We map the VoxelSystem pointers into an 1 byte key, this limits us to at
|
||||
// most 255 voxel systems in use at a time within the client. Which is far more than we need.
|
||||
static uint8_t _nextIndex;
|
||||
static std::map<VoxelSystem*, uint8_t> _mapVoxelSystemPointersToIndex;
|
||||
static std::map<uint8_t, VoxelSystem*> _mapIndexToVoxelSystemPointers;
|
||||
|
|
|
@ -710,6 +710,9 @@ VoxelNode* VoxelTree::getVoxelAt(float x, float y, float z, float s) const {
|
|||
node = NULL;
|
||||
}
|
||||
delete[] octalCode; // cleanup memory
|
||||
if (node) {
|
||||
node->auditChildren("VoxelTree::getVoxelAt()");
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue