From 321d1952d652bef13cf77e5238a71572757b1aee Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 20 May 2013 12:56:59 -0700 Subject: [PATCH] first cut at exists bits --- interface/src/Application.cpp | 9 +- interface/src/Application.h | 1 + interface/src/VoxelSystem.cpp | 11 +- interface/src/VoxelSystem.h | 5 + libraries/avatars/src/AvatarData.cpp | 17 +-- libraries/shared/src/SharedUtil.h | 4 + libraries/voxels/src/VoxelNode.cpp | 16 ++- libraries/voxels/src/VoxelTree.cpp | 165 +++++++++++++++++++++------ libraries/voxels/src/VoxelTree.h | 13 ++- tools/sendvoxels.php | 2 +- voxel-server/src/main.cpp | 20 +++- 11 files changed, 208 insertions(+), 55 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7974b2bdf8..0d7b416fe0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1106,6 +1106,10 @@ void Application::setWantsResIn(bool wantsResIn) { _myAvatar.setWantResIn(wantsResIn); } +void Application::setWantsExistsBits(bool wantsExistsBits) { + _myAvatar.setWantExistsBits(wantsExistsBits); + _voxels.setWantExistsBits(wantsExistsBits); +} void Application::setWantsDelta(bool wantsDelta) { _myAvatar.setWantDelta(wantsDelta); @@ -1255,7 +1259,7 @@ void Application::initMenu() { QMenu* debugMenu = menuBar->addMenu("Debug"); debugMenu->addAction("Show Render Pipeline Warnings", this, SLOT(setRenderWarnings(bool)))->setCheckable(true); debugMenu->addAction("Kill Local Voxels", this, SLOT(doKillLocalVoxels())); - debugMenu->addAction("Randomize Voxel TRUE Colors", this, SLOT(doRandomizeVoxelColors())); + debugMenu->addAction("Randomize Voxel TRUE Colors", this, SLOT(doRandomizeVoxelColors()), Qt::CTRL | Qt::Key_R); debugMenu->addAction("FALSE Color Voxels Randomly", this, SLOT(doFalseRandomizeVoxelColors())); debugMenu->addAction("FALSE Color Voxel Every Other Randomly", this, SLOT(doFalseRandomizeEveryOtherVoxelColors())); debugMenu->addAction("FALSE Color Voxels by Distance", this, SLOT(doFalseColorizeByDistance())); @@ -1265,6 +1269,7 @@ void Application::initMenu() { debugMenu->addAction("Wants Res-In", this, SLOT(setWantsResIn(bool)))->setCheckable(true); debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true); debugMenu->addAction("Wants View Delta Sending", this, SLOT(setWantsDelta(bool)))->setCheckable(true); + debugMenu->addAction("Wants Exists Bits", this, SLOT(setWantsExistsBits(bool)), Qt::CTRL | Qt::Key_M)->setCheckable(true); } void Application::updateFrustumRenderModeAction() { @@ -2035,7 +2040,7 @@ void Application::deleteVoxelUnderCursor() { sendVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, _mouseVoxel); // delete the voxel locally so it disappears immediately - _voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + //_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); // remember the position for drag detection _lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); diff --git a/interface/src/Application.h b/interface/src/Application.h index da3898ab9f..d072eefe24 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -90,6 +90,7 @@ private slots: void doTreeStats(); void setWantsMonochrome(bool wantsMonochrome); void setWantsResIn(bool wantsResIn); + void setWantsExistsBits(bool wantsExistsBits); void setWantsDelta(bool wantsDelta); void updateVoxelModeActions(); void addVoxelInFrontOfAvatar(); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index d578bb3504..75d9a15a4d 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -102,21 +102,25 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { switch(command) { case PACKET_HEADER_VOXEL_DATA: { +//printLog("PACKET_HEADER_VOXEL_DATA voxelData="); +//outputBufferBits(sourceBuffer, numBytes); + PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()"); // ask the VoxelTree to read the bitstream into the tree - _tree->readBitstreamToTree(voxelData, numBytes - 1); + _tree->readBitstreamToTree(voxelData, numBytes - 1, true, _wantsExistBits); } break; case PACKET_HEADER_VOXEL_DATA_MONOCHROME: { PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()"); // ask the VoxelTree to read the MONOCHROME bitstream into the tree - _tree->readBitstreamToTree(voxelData, numBytes - 1, false); + _tree->readBitstreamToTree(voxelData, numBytes - 1, false, _wantsExistBits); } break; case PACKET_HEADER_ERASE_VOXEL: // ask the tree to read the "remove" bitstream - _tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); + //_tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); + //printLog("ignoring PACKET_HEADER_ERASE_VOXEL\n"); break; case PACKET_HEADER_Z_COMMAND: @@ -419,6 +423,7 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { void VoxelSystem::init() { + _wantsExistBits = false; _renderWarningsOn = false; _callsToTreesToArrays = 0; _setupNewVoxelsForDrawingLastFinished = 0; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 2d6d9717f6..1f2597763c 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -79,6 +79,9 @@ public: void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive = false); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, creationMode mode, bool destructive = false, bool debug = false); + + void setWantExistsBits(bool on) { _wantsExistBits = on; }; + bool getWantExistsBits() const { return _wantsExistBits; }; private: // disallow copying of VoxelSystem objects @@ -151,6 +154,8 @@ private: void copyWrittenDataToReadArrays(); bool _voxelsDirty; + + bool _wantsExistBits; public: void updateVBOs(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 21e0397619..db5718a516 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -128,9 +128,10 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { // voxel sending features... // voxel sending features... unsigned char wantItems = 0; - if (_wantResIn) { setAtBit(wantItems,WANT_RESIN_AT_BIT); } - if (_wantColor) { setAtBit(wantItems,WANT_COLOR_AT_BIT); } - if (_wantDelta) { setAtBit(wantItems,WANT_DELTA_AT_BIT); } + if (_wantResIn) { setAtBit(wantItems,WANT_RESIN_AT_BIT); } + if (_wantExistsBits) { setAtBit(wantItems,WANT_EXISTS_BITS_BIT); } + if (_wantColor) { setAtBit(wantItems,WANT_COLOR_AT_BIT); } + if (_wantDelta) { setAtBit(wantItems,WANT_DELTA_AT_BIT); } *destinationBuffer++ = wantItems; return destinationBuffer - bufferStart; @@ -210,11 +211,11 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { // voxel sending features... unsigned char wantItems = 0; wantItems = (unsigned char)*sourceBuffer++; + _wantResIn = oneAtBit(wantItems,WANT_RESIN_AT_BIT); + _wantExistsBits = oneAtBit(wantItems,WANT_EXISTS_BITS_BIT); + _wantColor = oneAtBit(wantItems,WANT_COLOR_AT_BIT); + _wantDelta = oneAtBit(wantItems,WANT_DELTA_AT_BIT); - _wantResIn = oneAtBit(wantItems,WANT_RESIN_AT_BIT); - _wantColor = oneAtBit(wantItems,WANT_COLOR_AT_BIT); - _wantDelta = oneAtBit(wantItems,WANT_DELTA_AT_BIT); - return sourceBuffer - startPosition; } @@ -223,4 +224,4 @@ void AvatarData::setHeadPitch(float p) { const float MAX_PITCH = 60; const float MIN_PITCH = -60; _headPitch = glm::clamp(p, MIN_PITCH, MAX_PITCH); -} \ No newline at end of file +} diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index d0e71ec71e..ebaa802890 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -80,4 +80,8 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex, void** valueArray, float* keyArray, int* originalIndexArray, int currentCount, int maxCount); +class debugHelpers { +public: + static const char* booleanValue(bool checkValue) { return checkValue ? "yes" : "no"; }; +}; #endif /* defined(__hifi__SharedUtil__) */ diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 6bab72cf61..37abc3505b 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -242,8 +242,20 @@ void VoxelNode::setRandomColor(int minimumBrightness) { } void VoxelNode::printDebugDetails(const char* label) const { - printLog("%s - Voxel at corner=(%f,%f,%f) size=%f octcode=", label, - _box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getSize().x); + unsigned char childBits = 0; + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + if (_children[i]) { + setAtBit(childBits,i); + } + } + + printLog("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isColored=%s isDirty=%s shouldRender=%s\n children=", label, + _box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getSize().x, + debugHelpers::booleanValue(isLeaf()), debugHelpers::booleanValue(isColored()), debugHelpers::booleanValue(isDirty()), + debugHelpers::booleanValue(getShouldRender()) ); + + outputBits(childBits,false); + printLog("\n octalCode="); printOctalCode(_octalCode); } diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 249a70212e..452ff6fa96 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -103,15 +103,22 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char int indexOfNewChild = branchIndexWithDescendant(lastParentNode->getOctalCode(), codeToReach); // we could be coming down a branch that was already created, so don't stomp on it. + if (!lastParentNode->getChildAtIndex(indexOfNewChild)) { + lastParentNode->addChildAtIndex(indexOfNewChild); + } + +/**** if (lastParentNode->isLeaf() && lastParentNode->isColored()) { // for colored leaves, we must add *all* the children for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { +printLog(">>>>>>>> createMissingNode() add *all* the children - calling addChildAtIndex() at %d <<<<<<<\n",i); lastParentNode->addChildAtIndex(i); lastParentNode->getChildAtIndex(i)->setColor(lastParentNode->getColor()); } } else if (!lastParentNode->getChildAtIndex(indexOfNewChild)) { lastParentNode->addChildAtIndex(indexOfNewChild); } +***/ // This works because we know we traversed down the same tree so if the length is the same, then the whole code is the same if (*lastParentNode->getChildAtIndex(indexOfNewChild)->getOctalCode() == *codeToReach) { @@ -121,14 +128,28 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char } } -int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead, bool includeColor) { +int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead, + bool includeColor, bool includeExistsBits) { + + +if (includeExistsBits) { + //printLog("readNodeData() expecting includeExistsBits\n"); +} + // give this destination node the child mask from the packet + const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF; + unsigned char colorInPacketMask = *nodeData; + unsigned char colorInTreeMask = includeExistsBits ? *(nodeData+1) : ALL_CHILDREN_ASSUMED_TO_EXIST; + // instantiate variable for bytes already read - int bytesRead = 1; + int bytesRead = includeExistsBits ? 2 : 1; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { // check the colors mask to see if we have a child to color in - if (oneAtBit(*nodeData, i)) { + if (oneAtBit(colorInPacketMask, i)) { // create the child if it doesn't exist if (!destinationNode->getChildAtIndex(i)) { +//printLog(">>>>>>>> readNodeData() colorInPacketMask area -- calling addChildAtIndex() at %d colorInTreeBitSet=%s<<<<<<<\n",i, +// debugHelpers::booleanValue(oneAtBit(colorInTreeMask, i))); + destinationNode->addChildAtIndex(i); if (destinationNode->isDirty()) { _isDirty = true; @@ -156,13 +177,27 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, this->voxelsColored++; this->voxelsColoredStats.updateAverage(1); } + + // now also check the colorInTreeMask, if the mask is missing the bit, then it means we need to delete this child + // node, because it shouldn't actually exist in the tree. + /** + if (!oneAtBit(colorInTreeMask, i) && destinationNode->getChildAtIndex(i) && + destinationNode->getChildAtIndex(i)->isColored()) { + + destinationNode->printDebugDetails("colorInTreeMask mismatch "); + // we should delete this node!!! + printLog("colorInTreeMask for child %d missing, should delete this node? colorInTreeMask=",i); + outputBits(colorInTreeMask, true); + } + **/ } // give this destination node the child mask from the packet - unsigned char childMask = *(nodeData + bytesRead); - + unsigned char childrenInTreeMask = includeExistsBits ? *(nodeData + bytesRead) : ALL_CHILDREN_ASSUMED_TO_EXIST; + unsigned char childMask = *(nodeData + bytesRead + (includeExistsBits ? 1 : 0) ); + int childIndex = 0; - bytesRead++; + bytesRead += includeExistsBits ? 2 : 1; while (bytesLeftToRead - bytesRead > 0 && childIndex < NUMBER_OF_CHILDREN) { // check the exists mask to see if we have a child to traverse into @@ -171,6 +206,10 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, if (!destinationNode->getChildAtIndex(childIndex)) { // add a child at that index, if it doesn't exist bool nodeWasDirty = destinationNode->isDirty(); +//printLog(">>>>>>>> readNodeData() childMask area -- calling addChildAtIndex() at %d colorInTreeBitSet=%s<<<<<<<\n",childIndex, +// debugHelpers::booleanValue(oneAtBit(childrenInTreeMask, childIndex))); + + destinationNode->addChildAtIndex(childIndex); bool nodeIsDirty = destinationNode->isDirty(); if (nodeIsDirty) { @@ -185,17 +224,38 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, // tell the child to read the subsequent data bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex), - nodeData + bytesRead, - bytesLeftToRead - bytesRead, includeColor); + nodeData + bytesRead, bytesLeftToRead - bytesRead, includeColor, includeExistsBits); } - childIndex++; } + + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child + // subtree/node, because it shouldn't actually exist in the tree. + if (!oneAtBit(childrenInTreeMask, i) && destinationNode->getChildAtIndex(i)) { + // we should delete this node!!! + //destinationNode->printDebugDetails("childrenInTreeMask mismatch "); + //printLog("childrenInTreeMask for child %d missing, should delete this node? childrenInTreeMask=",i); + //outputBits(childrenInTreeMask, true); + + // If this node has a VBO index, then we can only stage it for deletion, otherwise delete away! + if (destinationNode->getChildAtIndex(i)->isKnownBufferIndex()) { + printLog("childrenInTreeMask for child %d missing, staging for deletion\n",i); + destinationNode->getChildAtIndex(i)->stageForDeletion(); + _isDirty = true; + } else { + printLog("childrenInTreeMask for child %d missing, deleting now\n",i); + destinationNode->deleteChildAtIndex(i); + _isDirty = true; + } + } + } return bytesRead; } -void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor) { +void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, + bool includeColor, bool includeExistsBits) { int bytesRead = 0; unsigned char* bitstreamAt = bitstream; @@ -224,7 +284,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int int theseBytesRead = 0; theseBytesRead += octalCodeBytes; theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes, - bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor); + bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor, includeExistsBits); // skip bitstream to new startPoint bitstreamAt += theseBytesRead; @@ -245,6 +305,7 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s, bool stage) { // Note: uses the codeColorBuffer format, but the color's are ignored, because // this only finds and deletes the node from the tree. void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage) { +//printLog(">>>>>>>> deleteVoxelCodeFromTree() <<<<<<<\n"); VoxelNode* parentNode = NULL; VoxelNode* nodeToDelete = nodeForOctalCode(rootNode, codeBuffer, &parentNode); @@ -271,6 +332,7 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage) { int index = branchIndexWithDescendant(ancestorNode->getOctalCode(), codeBuffer); for (int i = 0; i < 8; i++) { if (i != index) { +//printLog(">>>>>>>> deleteVoxelCodeFromTree() calling addChildAtIndex() at %d <<<<<<<\n",i); ancestorNode->addChildAtIndex(i); ancestorNode->getChildAtIndex(i)->setColor(nodeToDelete->getColor()); } @@ -278,6 +340,7 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage) { if (*ancestorNode->getOctalCode() == *codeBuffer - 1) { break; } +//printLog(">>>>>>>> deleteVoxelCodeFromTree() calling addChildAtIndex() at %d <<<<<<<\n",index); ancestorNode->addChildAtIndex(index); ancestorNode = ancestorNode->getChildAtIndex(index); ancestorNode->setColor(nodeToDelete->getColor()); @@ -764,7 +827,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe } int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor, + VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const { // How many bytes have we written so far at this level; @@ -784,8 +847,8 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned availableBytes -= codeLength; // keep track or remaining space int currentEncodeLevel = 0; - int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel, - node, outputBuffer, availableBytes, bag, viewFrustum, includeColor, + int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel, node, outputBuffer, availableBytes, + bag, viewFrustum, includeColor, includeExistsBits, deltaViewFrustum, lastViewFrustum); // if childBytesWritten == 1 then something went wrong... that's not possible @@ -807,9 +870,9 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned return bytesWritten; } -int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, - VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor, +int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, VoxelNode* node, + unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag, + const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const { // How many bytes have we written so far at this level; int bytesAtThisLevel = 0; @@ -855,7 +918,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco unsigned char thisLevelBuffer[MAX_LEVEL_BYTES]; unsigned char* writeToThisLevelBuffer = &thisLevelBuffer[0]; - unsigned char childrenExistBits = 0; + unsigned char childrenExistInTreeBits = 0; + unsigned char colorsExistInTreeBits = 0; + unsigned char childrenExistInPacketBits = 0; unsigned char childrenColoredBits = 0; int inViewCount = 0; int inViewNotLeafCount = 0; @@ -865,6 +930,16 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // add them to our distance ordered array of children for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { VoxelNode* childNode = node->getChildAtIndex(i); + + // if the caller wants to include childExistsBits, then include them even if not in view + if (includeExistsBits && childNode) { +//printLog("includeExistsBits, calculating exists bits\n"); + childrenExistInTreeBits += (1 << (7 - i)); + if (childNode->isColored()) { + colorsExistInTreeBits += (1 << (7 - i)); + } + } + bool childIsInView = (childNode && (!viewFrustum || childNode->isInView(*viewFrustum))); if (childIsInView) { @@ -879,7 +954,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // we don't care about recursing deeper on them, and we don't consider their // subtree to exist if (!(childNode && childNode->isLeaf())) { - childrenExistBits += (1 << (7 - i)); + childrenExistInPacketBits += (1 << (7 - i)); inViewNotLeafCount++; } @@ -897,6 +972,20 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco *writeToThisLevelBuffer = childrenColoredBits; writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count + // if the caller wants to include childExistsBits, then include them even if not in view + if (includeExistsBits) { +printLog("includeExistsBits, writing color exists bits...\n"); +printLog("childrenColoredBits="); +outputBits(childrenColoredBits); +printLog(" colorsExistInTreeBits="); +outputBits(colorsExistInTreeBits); +printLog(" childrenExistInTreeBits="); +outputBits(childrenExistInTreeBits); + + *writeToThisLevelBuffer = colorsExistInTreeBits; + writeToThisLevelBuffer += sizeof(colorsExistInTreeBits); // move the pointer + bytesAtThisLevel += sizeof(colorsExistInTreeBits); // keep track of byte count + } // write the color data... if (includeColor) { @@ -908,12 +997,21 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco } } } - // write the child exist bits - *writeToThisLevelBuffer = childrenExistBits; - writeToThisLevelBuffer += sizeof(childrenExistBits); // move the pointer - bytesAtThisLevel += sizeof(childrenExistBits); // keep track of byte count - + // if the caller wants to include childExistsBits, then include them even if not in view, put them before the + // childrenExistInPacketBits, so that the lower code can properly repair the packet exists bits + if (includeExistsBits) { +printLog("includeExistsBits, writing subtree exists bits\n"); + *writeToThisLevelBuffer = childrenExistInTreeBits; + writeToThisLevelBuffer += sizeof(childrenExistInTreeBits); // move the pointer + bytesAtThisLevel += sizeof(childrenExistInTreeBits); // keep track of byte count + } + + // write the child exist bits + *writeToThisLevelBuffer = childrenExistInPacketBits; + writeToThisLevelBuffer += sizeof(childrenExistInPacketBits); // move the pointer + bytesAtThisLevel += sizeof(childrenExistInPacketBits); // keep track of byte count + // We only need to keep digging, if there is at least one child that is inView, and not a leaf. keepDiggingDeeper = (inViewNotLeafCount > 0); @@ -933,23 +1031,23 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // and we need to determine if there's a deeper tree below them that we care about. // // Since this recursive function assumes we're already writing, we know we've already written our - // childrenExistBits. But... we don't really know how big the child tree will be. And we don't know if + // childrenExistInPacketBits. But... we don't really know how big the child tree will be. And we don't know if // we'll have room in our buffer to actually write all these child trees. What we kinda would like to do is // write our childExistsBits as a place holder. Then let each potential tree have a go at it. If they // write something, we keep them in the bits, if they don't, we take them out. // - // we know the last thing we wrote to the outputBuffer was our childrenExistBits. Let's remember where that was! - unsigned char* childExistsPlaceHolder = outputBuffer-sizeof(childrenExistBits); + // we know the last thing we wrote to the outputBuffer was our childrenExistInPacketBits. Let's remember where that was! + unsigned char* childExistsPlaceHolder = outputBuffer-sizeof(childrenExistInPacketBits); for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - if (oneAtBit(childrenExistBits, i)) { + if (oneAtBit(childrenExistInPacketBits, i)) { VoxelNode* childNode = node->getChildAtIndex(i); int thisLevel = currentEncodeLevel; int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode, outputBuffer, availableBytes, bag, - viewFrustum, includeColor, + viewFrustum, includeColor, includeExistsBits, deltaViewFrustum, lastViewFrustum); // if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space, @@ -970,6 +1068,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // we can make this act like no bytes out, by just resetting the bytes out in this case if (includeColor && childTreeBytesOut == 2) { childTreeBytesOut = 0; // this is the degenerate case of a tree with no colors and no child trees +printLog("childTreeBytesOut==2.... lopping empty lower tree\n"); } bytesAtThisLevel += childTreeBytesOut; @@ -979,15 +1078,17 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // If we had previously started writing, and if the child DIDN'T write any bytes, // then we want to remove their bit from the childExistsPlaceHolder bitmask if (childTreeBytesOut == 0) { +printLog("childTreeBytesOut == 0... actually lopping empty lower tree\n"); // remove this child's bit... - childrenExistBits -= (1 << (7 - i)); + childrenExistInPacketBits -= (1 << (7 - i)); // repair the child exists mask - *childExistsPlaceHolder = childrenExistBits; + *childExistsPlaceHolder = childrenExistInPacketBits; // Note: no need to move the pointer, cause we already stored this } // end if (childTreeBytesOut == 0) - } // end if (oneAtBit(childrenExistBits, i)) + } // end if (oneAtBit(childrenExistInPacketBits, i)) } // end for } // end keepDiggingDeeper + return bytesAtThisLevel; } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 6d384f0244..c4a5631abf 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -40,7 +40,8 @@ public: void eraseAllVoxels(); void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes); - void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor = true); + void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, + bool includeColor = true, bool includeExistsBits = false); void readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool destructive = false); void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = false); void printTreeForDebugging(VoxelNode *startNode); @@ -57,7 +58,8 @@ public: void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL); int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor = true, + VoxelNodeBag& bag, const ViewFrustum* viewFrustum, + bool includeColor = true, bool includeExistsBits = false, bool deltaViewFrustum = false, const ViewFrustum* lastViewFrustum = NULL) const; int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag, @@ -82,8 +84,8 @@ public: private: int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, - VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor, + VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag, + const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const; int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel, @@ -95,7 +97,8 @@ private: void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData); VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const; VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate); - int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, bool includeColor = true); + int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, + bool includeColor = true, bool includeExistsBits = false); bool _isDirty; unsigned long int _nodesChangedFromBitstream; diff --git a/tools/sendvoxels.php b/tools/sendvoxels.php index 438c9a1b8a..ed3b7b6095 100644 --- a/tools/sendvoxels.php +++ b/tools/sendvoxels.php @@ -30,8 +30,8 @@ function send_voxels($inputFileName,$server,$port,$command) { echo "sending adding octets=$octets size=$size to packet packetSize=$packetSize\n"; } - echo "sending packet server=$serverIP port=$serverSendPort $voxNum size=$packetSize result=$result\n"; $result = socket_sendto($socketHandle, $netData, $packetSize, 0, $serverIP, $serverSendPort); + echo "sent packet server=$serverIP port=$serverSendPort $voxNum size=$packetSize result=$result\n"; usleep(20000); // 1,000,000 per second $voxNum++; } diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index c268031e74..3561559e89 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -168,13 +168,15 @@ void resInVoxelDistributor(AgentList* agentList, bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, agentData->nodeBag, &viewFrustum, - agentData->getWantColor()); + agentData->getWantColor(),agentData->getWantExistsBits()); if (agentData->getAvailable() >= bytesWritten) { agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten); } else { agentList->getAgentSocket()->send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + printf("sending packet..."); + outputBufferBits((unsigned char*)agentData->getPacket(), agentData->getPacketLength()); trueBytesSent += agentData->getPacketLength(); truePacketsSent++; packetsSentThisInterval++; @@ -185,6 +187,8 @@ void resInVoxelDistributor(AgentList* agentList, if (agentData->isPacketWaiting()) { agentList->getAgentSocket()->send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + printf("sending packet..."); + outputBufferBits((unsigned char*)agentData->getPacket(), agentData->getPacketLength()); trueBytesSent += agentData->getPacketLength(); truePacketsSent++; agentData->resetVoxelPacket(); @@ -254,6 +258,10 @@ void deepestLevelVoxelDistributor(AgentList* agentList, maxLevelReached = randomTree.searchForColoredNodes(INT_MAX, randomTree.rootNode, agentData->getCurrentViewFrustum(), agentData->nodeBag, wantDelta, lastViewFrustum); + // if nothing was found in view, send the root node. + if (agentData->nodeBag.isEmpty()){ + agentData->nodeBag.insert(randomTree.rootNode); + } agentData->setViewSent(false); } @@ -288,13 +296,17 @@ void deepestLevelVoxelDistributor(AgentList* agentList, bytesWritten = randomTree.encodeTreeBitstream(INT_MAX, subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, agentData->nodeBag, &agentData->getCurrentViewFrustum(), - agentData->getWantColor(), wantDelta, lastViewFrustum); + agentData->getWantColor(), agentData->getWantExistsBits(), + wantDelta, lastViewFrustum); if (agentData->getAvailable() >= bytesWritten) { agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten); } else { agentList->getAgentSocket()->send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + + printf("sending packet..."); + outputBufferBits((unsigned char*)agentData->getPacket(), agentData->getPacketLength()); trueBytesSent += agentData->getPacketLength(); truePacketsSent++; packetsSentThisInterval++; @@ -305,6 +317,8 @@ void deepestLevelVoxelDistributor(AgentList* agentList, if (agentData->isPacketWaiting()) { agentList->getAgentSocket()->send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + printf("sending packet..."); + outputBufferBits((unsigned char*)agentData->getPacket(), agentData->getPacketLength()); trueBytesSent += agentData->getPacketLength(); truePacketsSent++; agentData->resetVoxelPacket(); @@ -532,6 +546,8 @@ int main(int argc, const char * argv[]) persistVoxelsWhenDirty(); if (agentList->getAgentSocket()->receive(&agentPublicAddress, packetData, &receivedBytes)) { + + //printf("got a packet with message %d %c\n",(int)packetData[0],packetData[0]); // XXXBHG: Hacked in support for 'S' SET command if (packetData[0] == PACKET_HEADER_SET_VOXEL || packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) { bool destructive = (packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE);