From 6a7ebb3a556b5536c6a4462a0c3975e7a45957bf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 22:57:19 -0700 Subject: [PATCH 01/15] fixed LOD issue in client --- interface/src/VoxelSystem.cpp | 2 +- libraries/voxels/src/VoxelNode.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 76fda4f942..9dd948e881 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -164,7 +164,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { float childBoundary = boundaryDistanceForRenderLevel(*node->octalCode + 2); bool inBoundary = (distanceToNode <= boundary); bool inChildBoundary = (distanceToNode <= childBoundary); - bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary)); + bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary)); node->setShouldRender(shouldRender); // let children figure out their renderness diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 6f8f1d71f8..776aec7a9a 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -234,6 +234,7 @@ bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const { float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const { AABox box; getAABox(box); + box.scale(TREE_SCALE); float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - (box.getCorner().x + box.getSize().x), 2) + powf(viewFrustum.getPosition().y - (box.getCorner().y + box.getSize().y), 2) + powf(viewFrustum.getPosition().z - (box.getCorner().z + box.getSize().z), 2)); From a6d2bb73ada91462e7ba3dfbcedb176c7d85271c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 23:24:46 -0700 Subject: [PATCH 02/15] added warnings if bitstream processing takes too long --- interface/src/VoxelSystem.cpp | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 9dd948e881..a1f4404e20 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -97,8 +97,21 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { switch(command) { case PACKET_HEADER_VOXEL_DATA: + { + double start = usecTimestampNow(); // ask the VoxelTree to read the bitstream into the tree _tree->readBitstreamToTree(voxelData, numBytes - 1); + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! readBitstreamToTree() took %lf milliseconds\n",elapsedmsec); + } + } + } break; case PACKET_HEADER_ERASE_VOXEL: // ask the tree to read the "remove" bitstream @@ -135,16 +148,28 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { } void VoxelSystem::setupNewVoxelsForDrawing() { + double start = usecTimestampNow(); _voxelsUpdated = newTreeToArrays(_tree->rootNode); if (_voxelsUpdated) { _voxelsDirty=true; } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! newTreeToArrays() took %lf milliseconds\n",elapsedmsec); + } + } // copy the newly written data to the arrays designated for reading copyWrittenDataToReadArrays(); } void VoxelSystem::copyWrittenDataToReadArrays() { + double start = usecTimestampNow(); if (_voxelsDirty) { // lock on the buffer write lock so we can't modify the data when the GPU is reading it pthread_mutex_lock(&_bufferWriteLock); @@ -154,6 +179,16 @@ void VoxelSystem::copyWrittenDataToReadArrays() { memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); pthread_mutex_unlock(&_bufferWriteLock); } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds\n",elapsedmsec); + } + } } int VoxelSystem::newTreeToArrays(VoxelNode* node) { @@ -296,6 +331,7 @@ void VoxelSystem::init() { } void VoxelSystem::updateVBOs() { + double start = usecTimestampNow(); if (_voxelsDirty) { glBufferIndex segmentStart = 0; glBufferIndex segmentEnd = 0; @@ -327,9 +363,20 @@ void VoxelSystem::updateVBOs() { } _voxelsDirty = false; } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! updateVBOs() took %lf milliseconds\n",elapsedmsec); + } + } } void VoxelSystem::render() { + double start = usecTimestampNow(); glPushMatrix(); updateVBOs(); // tell OpenGL where to find vertex and color information @@ -362,6 +409,16 @@ void VoxelSystem::render() { // scale back down to 1 so heads aren't massive glPopMatrix(); + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! render() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! render() took %lf milliseconds\n",elapsedmsec); + } + } } int VoxelSystem::_nodeCount = 0; From 174c3ee65b5ca6798745aed92ca1ad383f270842 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 11:31:20 -0700 Subject: [PATCH 03/15] search into level appropriately --- libraries/voxels/src/VoxelTree.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 3ff14b5afd..ba13ee1c28 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -498,10 +498,10 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe // Keep track of how deep we've searched. currentSearchLevel++; - // If we've reached our max Search Level, then stop searching. - if (currentSearchLevel >= maxSearchLevel) { - return currentSearchLevel; - } + // If we've passed our max Search Level, then stop searching. return last level searched + if (currentSearchLevel > maxSearchLevel) { + return currentSearchLevel-1; + } // If we're at a node that is out of view, then we can return, because no nodes below us will be in view! if (!node->isInView(viewFrustum)) { From 275772bb3d3cd800d615e78397fc0b6cd70eb084 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:26:51 -0700 Subject: [PATCH 04/15] debugging voxel sending behavior --- interface/src/VoxelSystem.cpp | 11 +++++++++-- interface/src/VoxelSystem.h | 2 ++ interface/src/main.cpp | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a1f4404e20..72a153ded2 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -423,10 +423,17 @@ void VoxelSystem::render() { int VoxelSystem::_nodeCount = 0; +void VoxelSystem::killLocalVoxels() { + _tree->eraseAllVoxels(); + _voxelsInArrays = 0; // better way to do this?? + //setupNewVoxelsForDrawing(); +} + + bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { _nodeCount++; if (node->isColored()) { - nodeColor newColor = { randomColorValue(150), randomColorValue(150), randomColorValue(150), 1 }; + nodeColor newColor = { 255, randomColorValue(150), randomColorValue(150), 1 }; node->setColor(newColor); } return true; @@ -442,7 +449,7 @@ void VoxelSystem::randomizeVoxelColors() { bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { _nodeCount++; // always false colorize - node->setFalseColor(randomColorValue(150), randomColorValue(150), randomColorValue(150)); + node->setFalseColor(255, randomColorValue(150), randomColorValue(150)); return true; // keep going! } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index e6798f9fd1..63f3b8622e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -58,6 +58,8 @@ public: void falseColorizeInView(ViewFrustum* viewFrustum); void falseColorizeDistanceFromView(ViewFrustum* viewFrustum); + void killLocalVoxels(); + private: // Operation functions for tree recursion methods static int _nodeCount; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 08b1666d05..d5c28770be 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -130,6 +130,9 @@ glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE); VoxelSystem voxels; +bool wantToKillLocalVoxels = false; + + #ifndef _WIN32 Audio audio(&audioScope, &myAvatar); #endif @@ -1071,6 +1074,13 @@ int setFrustumRenderMode(int state) { return ::frustumDrawingMode; } +int doKillLocalVoxels(int state) { + if (state == MENU_ROW_PICKED) { + ::wantToKillLocalVoxels = true; + } + return state; +} + int doRandomizeVoxelColors(int state) { if (state == MENU_ROW_PICKED) { ::voxels.randomizeVoxelColors(); @@ -1168,6 +1178,7 @@ void initMenu() { // Debug menuColumnDebug = menu.addColumn("Debug"); + menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels); menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors); menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors); menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance); @@ -1412,6 +1423,12 @@ void* networkReceive(void* args) ssize_t bytesReceived; while (!stopNetworkReceiveThread) { + // check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that + if (::wantToKillLocalVoxels) { + ::voxels.killLocalVoxels(); + ::wantToKillLocalVoxels = false; + } + if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { packetCount++; bytesCount += bytesReceived; From 0f48ac67b8b3d2cd594d46b5ae095cef02438fe2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:27:16 -0700 Subject: [PATCH 05/15] added timing details to voxel sending behavior --- voxel-server/src/main.cpp | 51 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 9ab5675d7e..2c215b03e4 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -167,8 +167,14 @@ void eraseVoxelTreeAndCleanupAgentVisitData() { void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) { - // If the bag is empty, fill it... - if (agentData->nodeBag.isEmpty()) { + bool searchReset = false; + int searchLoops = 0; + int searchLevelWas = agentData->getMaxSearchLevel(); + double start = usecTimestampNow(); + while (!searchReset && agentData->nodeBag.isEmpty()) { + searchLoops++; + + searchLevelWas = agentData->getMaxSearchLevel(); int maxLevelReached = randomTree.searchForColoredNodes(agentData->getMaxSearchLevel(), randomTree.rootNode, viewFrustum, agentData->nodeBag); agentData->setMaxLevelReached(maxLevelReached); @@ -177,17 +183,38 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge if (agentData->nodeBag.isEmpty()) { if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) { agentData->resetMaxSearchLevel(); + searchReset = true; } else { agentData->incrementMaxSearchLevel(); } } } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printf("WARNING! searchForColoredNodes() took %lf seconds to identify %d nodes at level %d in %d loops\n", + elapsedsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); + } else { + printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", + elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); + } + } else { + printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", + elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); + } + // If we have something in our nodeBag, then turn them into packets and send them out... if (!agentData->nodeBag.isEmpty()) { static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static int bytesWritten = 0; int packetsSentThisInterval = 0; + int truePacketsSent = 0; + int trueBytesSent = 0; + double start = usecTimestampNow(); + while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) { if (!agentData->nodeBag.isEmpty()) { VoxelNode* subTree = agentData->nodeBag.extract(); @@ -200,6 +227,8 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge } else { agentList->getAgentSocket().send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + trueBytesSent += agentData->getPacketLength(); + truePacketsSent++; packetsSentThisInterval++; agentData->resetVoxelPacket(); agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten); @@ -208,12 +237,30 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge if (agentData->isPacketWaiting()) { agentList->getAgentSocket().send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + trueBytesSent += agentData->getPacketLength(); + truePacketsSent++; agentData->resetVoxelPacket(); } packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left } } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printf("WARNING! packetLoop() took %lf seconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + elapsedsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); + } else { + printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); + } + } else { + printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); + } + // if during this last pass, we emptied our bag, then we want to move to the next level. if (agentData->nodeBag.isEmpty()) { if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) { From e2481f514c75a6ecd13c9561bffeef59df48f799 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:53:56 -0700 Subject: [PATCH 06/15] lower warning threshold to 1 millisecond for voxel render pipeline steps --- interface/src/VoxelSystem.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 72a153ded2..ba76202822 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -103,7 +103,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { _tree->readBitstreamToTree(voxelData, numBytes - 1); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec); @@ -155,7 +155,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); @@ -181,7 +181,7 @@ void VoxelSystem::copyWrittenDataToReadArrays() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); @@ -365,7 +365,7 @@ void VoxelSystem::updateVBOs() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); @@ -411,7 +411,7 @@ void VoxelSystem::render() { glPopMatrix(); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! render() took %lf seconds\n",elapsedsec); From 7625c9a62122dff2cb2be08ff3fa0cbfe7d2b28a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:54:26 -0700 Subject: [PATCH 07/15] add command line option to debug voxel sending time --- voxel-server/src/main.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 2c215b03e4..4a64da8a0f 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -45,8 +45,7 @@ const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; VoxelTree randomTree; bool wantColorRandomizer = false; -bool debugViewFrustum = false; -bool viewFrustumCulling = true; // for now +bool debugVoxelSending = false; void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) { float r = random ? randFloatInRange(0.05,0.1) : 0.25; @@ -200,7 +199,7 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); } - } else { + } else if (::debugVoxelSending) { printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); } @@ -256,7 +255,7 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); } - } else { + } else if (::debugVoxelSending) { printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); } @@ -343,13 +342,9 @@ int main(int argc, const char * argv[]) srand((unsigned)time(0)); - const char* DEBUG_VIEW_FRUSTUM = "--DebugViewFrustum"; - ::debugViewFrustum = cmdOptionExists(argc, argv, DEBUG_VIEW_FRUSTUM); - printf("debugViewFrustum=%s\n", (::debugViewFrustum ? "yes" : "no")); - - const char* NO_VIEW_FRUSTUM_CULLING = "--NoViewFrustumCulling"; - ::viewFrustumCulling = !cmdOptionExists(argc, argv, NO_VIEW_FRUSTUM_CULLING); - printf("viewFrustumCulling=%s\n", (::viewFrustumCulling ? "yes" : "no")); + const char* DEBUG_VOXEL_SENDING = "--DebugVoxelSending"; + ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); + printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no")); const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer"; ::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER); @@ -427,8 +422,6 @@ int main(int argc, const char * argv[]) delete []vertices; randomTree.readCodeColorBufferToTree(pVoxelData); - //printf("readCodeColorBufferToTree() of size=%d atByte=%d receivedBytes=%ld\n", - // voxelDataSize,atByte,receivedBytes); // skip to next pVoxelData+=voxelDataSize; atByte+=voxelDataSize; From 8f0dd1ffa16752bf19eab7c199e0615d9c84fbf1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 13:17:06 -0700 Subject: [PATCH 08/15] added render pipeline warnings menu item --- interface/src/VoxelSystem.cpp | 12 +++++++----- interface/src/VoxelSystem.h | 3 +++ interface/src/main.cpp | 11 +++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ba76202822..1005da8850 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -103,7 +103,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { _tree->readBitstreamToTree(voxelData, numBytes - 1); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec); @@ -155,7 +155,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); @@ -181,7 +181,7 @@ void VoxelSystem::copyWrittenDataToReadArrays() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); @@ -260,6 +260,8 @@ VoxelSystem* VoxelSystem::clone() const { void VoxelSystem::init() { + _renderWarningsOn = false; + // When we change voxels representations in the arrays, we'll update this _voxelsDirty = false; _voxelsInArrays = 0; @@ -365,7 +367,7 @@ void VoxelSystem::updateVBOs() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); @@ -411,7 +413,7 @@ void VoxelSystem::render() { glPopMatrix(); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! render() took %lf seconds\n",elapsedsec); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 63f3b8622e..d2c3fed499 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -59,8 +59,11 @@ public: void falseColorizeDistanceFromView(ViewFrustum* viewFrustum); void killLocalVoxels(); + void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; }; + bool getRenderPipelineWarnings() const { return _renderWarningsOn; }; private: + bool _renderWarningsOn; // Operation functions for tree recursion methods static int _nodeCount; static bool randomColorOperation(VoxelNode* node, void* extraData); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index d5c28770be..2b8760abdf 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -143,6 +143,8 @@ Audio audio(&audioScope, &myAvatar); // Where one's own agent begins in the world (needs to become a dynamic thing passed to the program) glm::vec3 start_location(6.1f, 0, 1.4f); +bool renderWarningsOn = false; // Whether to show render pipeline warnings + bool statsOn = false; // Whether to show onscreen text overlay with stats bool starsOn = false; // Whether to display the stars bool paintOn = false; // Whether to paint voxels as you fly around @@ -1041,6 +1043,14 @@ int setMenu(int state) { return setValue(state, &::menuOn); } +int setRenderWarnings(int state) { + int value = setValue(state, &::renderWarningsOn); + if (state == MENU_ROW_PICKED) { + ::voxels.setRenderPipelineWarnings(::renderWarningsOn); + } + return value; +} + int setDisplayFrustum(int state) { return setValue(state, &::frustumOn); } @@ -1178,6 +1188,7 @@ void initMenu() { // Debug menuColumnDebug = menu.addColumn("Debug"); + menuColumnDebug->addRow("Show Render Pipeline Warnings", setRenderWarnings); menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels); menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors); menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors); From c353c1d2bf3517e5803a87e0d490caa5f66de8e7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 13:18:12 -0700 Subject: [PATCH 09/15] added command line options for packets per second and debug packet sending --- voxel-server/src/main.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 4a64da8a0f..ecccbf0291 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05f; const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000; -const int PACKETS_PER_CLIENT_PER_INTERVAL = 20; +int PACKETS_PER_CLIENT_PER_INTERVAL = 20; const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; @@ -342,7 +342,7 @@ int main(int argc, const char * argv[]) srand((unsigned)time(0)); - const char* DEBUG_VOXEL_SENDING = "--DebugVoxelSending"; + const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no")); @@ -357,6 +357,17 @@ int main(int argc, const char * argv[]) if (voxelsFilename) { randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer); } + + // Check to see if the user passed in a command line option for setting packet send rate + const char* PACKETS_PER_SECOND = "--packetsPerSecond"; + const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); + if (packetsPerSecond) { + PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10; + if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { + PACKETS_PER_CLIENT_PER_INTERVAL = 1; + } + printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); + } const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels"; if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) { From 5a14c71225c8a506773ced4073f1d9e4101a4c34 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 15:57:31 -0700 Subject: [PATCH 10/15] added dirty bit support to VoxelTree, use it to determine when to call treeToArrays --- interface/src/VoxelSystem.cpp | 9 +++++++-- libraries/voxels/src/VoxelNode.cpp | 2 ++ libraries/voxels/src/VoxelTree.cpp | 26 +++++++++++++++++++++----- libraries/voxels/src/VoxelTree.h | 5 +++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 1005da8850..5ee098a775 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -149,7 +149,12 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { void VoxelSystem::setupNewVoxelsForDrawing() { double start = usecTimestampNow(); - _voxelsUpdated = newTreeToArrays(_tree->rootNode); + if (_tree->isDirty()) { + _voxelsUpdated = newTreeToArrays(_tree->rootNode); + _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean + } else { + _voxelsUpdated = 0; + } if (_voxelsUpdated) { _voxelsDirty=true; } @@ -248,8 +253,8 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { _voxelsInArrays++; // our know vertices in the arrays } voxelsUpdated++; - node->clearDirtyBit(); } + node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered return voxelsUpdated; } diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 776aec7a9a..80da795fe1 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -143,6 +143,8 @@ void VoxelNode::setFalseColored(bool isFalseColored) { void VoxelNode::setColor(const nodeColor& color) { if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) { + //printLog("VoxelNode::setColor() was: (%d,%d,%d) is: (%d,%d,%d)\n", + // _trueColor[0],_trueColor[1],_trueColor[2],color[0],color[1],color[2]); memcpy(&_trueColor,&color,sizeof(nodeColor)); if (!_falseColored) { memcpy(&_currentColor,&color,sizeof(nodeColor)); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index ba13ee1c28..f781c16b0d 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -35,7 +35,8 @@ VoxelTree::VoxelTree() : voxelsBytesRead(0), voxelsCreatedStats(100), voxelsColoredStats(100), - voxelsBytesReadStats(100) { + voxelsBytesReadStats(100), + _isDirty(true) { rootNode = new VoxelNode(); rootNode->octalCode = new unsigned char[1]; @@ -127,10 +128,13 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, // check the colors mask to see if we have a child to color in if (oneAtBit(*nodeData, i)) { // create the child if it doesn't exist - if (destinationNode->children[i] == NULL) { + if (!destinationNode->children[i]) { destinationNode->addChildAtIndex(i); - this->voxelsCreated++; - this->voxelsCreatedStats.updateAverage(1); + if (destinationNode->isDirty()) { + _isDirty = true; + } + voxelsCreated++; + voxelsCreatedStats.updateAverage(1); } // pull the color for this child @@ -138,6 +142,9 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, memcpy(newColor, nodeData + bytesRead, 3); newColor[3] = 1; destinationNode->children[i]->setColor(newColor); + if (destinationNode->children[i]->isDirty()) { + _isDirty = true; + } this->voxelsColored++; this->voxelsColoredStats.updateAverage(1); @@ -146,6 +153,9 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, } // average node's color based on color of children destinationNode->setColorFromAverageOfChildren(); + if (destinationNode->isDirty()) { + _isDirty = true; + } // give this destination node the child mask from the packet unsigned char childMask = *(nodeData + bytesRead); @@ -157,9 +167,12 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, // check the exists mask to see if we have a child to traverse into if (oneAtBit(childMask, childIndex)) { - if (destinationNode->children[childIndex] == NULL) { + if (!destinationNode->children[childIndex]) { // add a child at that index, if it doesn't exist destinationNode->addChildAtIndex(childIndex); + if (destinationNode->isDirty()) { + _isDirty = true; + } this->voxelsCreated++; this->voxelsCreatedStats.updateAverage(this->voxelsCreated); } @@ -193,6 +206,9 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt // Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial // octal code is always relative to root! bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt); + if (bitstreamRootNode->isDirty()) { + _isDirty = true; + } } int octalCodeBytes = bytesRequiredForCodeLength(*bitstreamAt); diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 7f5a6b866b..1209868c62 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -54,6 +54,9 @@ public: VoxelNodeBag& bag); int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag); + + bool isDirty() const { return _isDirty; }; + void clearDirtyBit() { _isDirty = false; }; private: int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, @@ -68,6 +71,8 @@ private: VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode); VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate); int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes); + + bool _isDirty; }; int boundaryDistanceForRenderLevel(unsigned int renderLevel); From fcce4753c9f85d2a7e82a868d52bd7b16c704a6f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 16:37:31 -0700 Subject: [PATCH 11/15] more optimizations on render pipeline --- interface/src/VoxelSystem.cpp | 33 +++++++++++++++++++++--------- interface/src/VoxelSystem.h | 2 ++ libraries/voxels/src/VoxelNode.cpp | 12 ++++++++--- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 5ee098a775..2195c7fe1a 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -150,6 +150,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { void VoxelSystem::setupNewVoxelsForDrawing() { double start = usecTimestampNow(); if (_tree->isDirty()) { + _callsToTreesToArrays++; _voxelsUpdated = newTreeToArrays(_tree->rootNode); _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean } else { @@ -163,14 +164,16 @@ void VoxelSystem::setupNewVoxelsForDrawing() { if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; - printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); + printLog("WARNING! newTreeToArrays() took %lf seconds %ld voxels updated\n", elapsedsec, _voxelsUpdated); } else { - printLog("WARNING! newTreeToArrays() took %lf milliseconds\n",elapsedmsec); + printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated); } } - // copy the newly written data to the arrays designated for reading - copyWrittenDataToReadArrays(); + if (_voxelsDirty) { + // copy the newly written data to the arrays designated for reading + copyWrittenDataToReadArrays(); + } } void VoxelSystem::copyWrittenDataToReadArrays() { @@ -189,9 +192,11 @@ void VoxelSystem::copyWrittenDataToReadArrays() { if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; - printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); + printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds for %ld voxels %ld updated\n", + elapsedsec, _voxelsInArrays, _voxelsUpdated); } else { - printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds\n",elapsedmsec); + printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds for %ld voxels %ld updated\n", + elapsedmsec, _voxelsInArrays, _voxelsUpdated); } } } @@ -266,6 +271,7 @@ VoxelSystem* VoxelSystem::clone() const { void VoxelSystem::init() { _renderWarningsOn = false; + _callsToTreesToArrays = 0; // When we change voxels representations in the arrays, we'll update this _voxelsDirty = false; @@ -373,13 +379,20 @@ void VoxelSystem::updateVBOs() { double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; if (_renderWarningsOn && elapsedmsec > 1) { - if (elapsedmsec > 1000) { - double elapsedsec = (end - start)/1000000.0; - printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); + if (elapsedmsec > 1) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! updateVBOs() took %lf seconds after %d calls to newTreeToArrays()\n", + elapsedsec, _callsToTreesToArrays); + } else { + printLog("WARNING! updateVBOs() took %lf milliseconds after %d calls to newTreeToArrays()\n", + elapsedmsec, _callsToTreesToArrays); + } } else { - printLog("WARNING! updateVBOs() took %lf milliseconds\n",elapsedmsec); + printLog("WARNING! updateVBOs() called after %d calls to newTreeToArrays()\n",_callsToTreesToArrays); } } + _callsToTreesToArrays = 0; // clear it } void VoxelSystem::render() { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index d2c3fed499..949417cf3b 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -63,6 +63,8 @@ public: bool getRenderPipelineWarnings() const { return _renderWarningsOn; }; private: + int _callsToTreesToArrays; + bool _renderWarningsOn; // Operation functions for tree recursion methods static int _nodeCount; diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 80da795fe1..7e411d9c4b 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -125,7 +125,9 @@ void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { _currentColor[1] = green; _currentColor[2] = blue; _currentColor[3] = 1; // XXXBHG - False colors are always considered set - _isDirty = true; + if (_shouldRender) { + _isDirty = true; + } } } @@ -136,7 +138,9 @@ void VoxelNode::setFalseColored(bool isFalseColored) { memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); } _falseColored = isFalseColored; - _isDirty = true; + if (_shouldRender) { + _isDirty = true; + } } }; @@ -149,7 +153,9 @@ void VoxelNode::setColor(const nodeColor& color) { if (!_falseColored) { memcpy(&_currentColor,&color,sizeof(nodeColor)); } - _isDirty = true; + if (_shouldRender) { + _isDirty = true; + } } } #endif From 771c6041212110d833214bcb8d01c12d3088a840 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 18:12:55 -0700 Subject: [PATCH 12/15] more render pipeline optimizations --- interface/src/VoxelSystem.cpp | 7 ++++++- libraries/voxels/src/VoxelNode.cpp | 12 ++++++------ libraries/voxels/src/VoxelTree.cpp | 25 ++++++++++++++++++++++--- libraries/voxels/src/VoxelTree.h | 2 ++ 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 2195c7fe1a..ebcc12a707 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -101,6 +101,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { double start = usecTimestampNow(); // ask the VoxelTree to read the bitstream into the tree _tree->readBitstreamToTree(voxelData, numBytes - 1); + if (_renderWarningsOn && _tree->getNodesChangedFromBitstream()) { + printLog("readBitstreamToTree()... getNodesChangedFromBitstream=%ld _tree->isDirty()=%s \n", + _tree->getNodesChangedFromBitstream(), (_tree->isDirty() ? "yes" : "no") ); + } + double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; if (_renderWarningsOn && elapsedmsec > 1) { @@ -178,7 +183,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { void VoxelSystem::copyWrittenDataToReadArrays() { double start = usecTimestampNow(); - if (_voxelsDirty) { + if (_voxelsDirty && _voxelsUpdated) { // lock on the buffer write lock so we can't modify the data when the GPU is reading it pthread_mutex_lock(&_bufferWriteLock); int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 7e411d9c4b..3d0e400782 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -125,9 +125,9 @@ void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { _currentColor[1] = green; _currentColor[2] = blue; _currentColor[3] = 1; // XXXBHG - False colors are always considered set - if (_shouldRender) { + //if (_shouldRender) { _isDirty = true; - } + //} } } @@ -138,9 +138,9 @@ void VoxelNode::setFalseColored(bool isFalseColored) { memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); } _falseColored = isFalseColored; - if (_shouldRender) { + //if (_shouldRender) { _isDirty = true; - } + //} } }; @@ -153,9 +153,9 @@ void VoxelNode::setColor(const nodeColor& color) { if (!_falseColored) { memcpy(&_currentColor,&color,sizeof(nodeColor)); } - if (_shouldRender) { + //if (_shouldRender) { _isDirty = true; - } + //} } } #endif diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index f781c16b0d..87e87ff1a7 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -132,6 +132,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, destinationNode->addChildAtIndex(i); if (destinationNode->isDirty()) { _isDirty = true; + _nodesChangedFromBitstream++; } voxelsCreated++; voxelsCreatedStats.updateAverage(1); @@ -141,9 +142,14 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, nodeColor newColor; memcpy(newColor, nodeData + bytesRead, 3); newColor[3] = 1; + bool nodeWasDirty = destinationNode->children[i]->isDirty(); destinationNode->children[i]->setColor(newColor); - if (destinationNode->children[i]->isDirty()) { + bool nodeIsDirty = destinationNode->children[i]->isDirty(); + if (nodeIsDirty) { _isDirty = true; + } + if (!nodeWasDirty && nodeIsDirty) { + _nodesChangedFromBitstream++; } this->voxelsColored++; this->voxelsColoredStats.updateAverage(1); @@ -152,10 +158,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, } } // average node's color based on color of children + bool nodeWasDirty = destinationNode->isDirty(); destinationNode->setColorFromAverageOfChildren(); - if (destinationNode->isDirty()) { + bool nodeIsDirty = destinationNode->isDirty(); + if (nodeIsDirty) { _isDirty = true; } + if (!nodeWasDirty && nodeIsDirty) { + _nodesChangedFromBitstream++; + } // give this destination node the child mask from the packet unsigned char childMask = *(nodeData + bytesRead); @@ -169,10 +180,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, if (oneAtBit(childMask, childIndex)) { if (!destinationNode->children[childIndex]) { // add a child at that index, if it doesn't exist + bool nodeWasDirty = destinationNode->isDirty(); destinationNode->addChildAtIndex(childIndex); - if (destinationNode->isDirty()) { + bool nodeIsDirty = destinationNode->isDirty(); + if (nodeIsDirty) { _isDirty = true; } + if (!nodeWasDirty && nodeIsDirty) { + _nodesChangedFromBitstream++; + } this->voxelsCreated++; this->voxelsCreatedStats.updateAverage(this->voxelsCreated); } @@ -192,6 +208,8 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes) { int bytesRead = 0; unsigned char* bitstreamAt = bitstream; + + _nodesChangedFromBitstream = 0; // Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes // into a single network packet. readNodeData() basically goes down a tree from the root, and fills things in from there @@ -208,6 +226,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt); if (bitstreamRootNode->isDirty()) { _isDirty = true; + _nodesChangedFromBitstream++; } } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 1209868c62..e5b18b86c0 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -57,6 +57,7 @@ public: bool isDirty() const { return _isDirty; }; void clearDirtyBit() { _isDirty = false; }; + unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; }; private: int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, @@ -73,6 +74,7 @@ private: int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes); bool _isDirty; + unsigned long int _nodesChangedFromBitstream; }; int boundaryDistanceForRenderLevel(unsigned int renderLevel); From 34a059db9a0bf442e5350e11e98ecfe4bb734f12 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 22:26:56 -0700 Subject: [PATCH 13/15] more optimizations of render pipeline --- interface/src/VoxelSystem.cpp | 23 ++++++++++++++++++----- interface/src/VoxelSystem.h | 4 ++++ libraries/voxels/src/VoxelConstants.h | 1 + libraries/voxels/src/VoxelTree.cpp | 6 ++++++ libraries/voxels/src/VoxelTree.h | 1 + 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ebcc12a707..b8f8485a67 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -154,6 +154,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { void VoxelSystem::setupNewVoxelsForDrawing() { double start = usecTimestampNow(); + + double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished); + + if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) { + return; // bail early, it hasn't been long enough since the last time we ran + } + if (_tree->isDirty()) { _callsToTreesToArrays++; _voxelsUpdated = newTreeToArrays(_tree->rootNode); @@ -164,6 +171,12 @@ void VoxelSystem::setupNewVoxelsForDrawing() { if (_voxelsUpdated) { _voxelsDirty=true; } + + if (_voxelsDirty) { + // copy the newly written data to the arrays designated for reading + copyWrittenDataToReadArrays(); + } + double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; if (_renderWarningsOn && elapsedmsec > 1) { @@ -174,11 +187,9 @@ void VoxelSystem::setupNewVoxelsForDrawing() { printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated); } } - - if (_voxelsDirty) { - // copy the newly written data to the arrays designated for reading - copyWrittenDataToReadArrays(); - } + + _setupNewVoxelsForDrawingLastFinished = end; + _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; } void VoxelSystem::copyWrittenDataToReadArrays() { @@ -277,6 +288,8 @@ void VoxelSystem::init() { _renderWarningsOn = false; _callsToTreesToArrays = 0; + _setupNewVoxelsForDrawingLastFinished = 0; + _setupNewVoxelsForDrawingLastElapsed = 0; // When we change voxels representations in the arrays, we'll update this _voxelsDirty = false; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 949417cf3b..d217e8aa55 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -90,6 +90,10 @@ private: unsigned long _voxelsUpdated; unsigned long _voxelsInArrays; + + double _setupNewVoxelsForDrawingLastElapsed; + double _setupNewVoxelsForDrawingLastFinished; + GLuint _vboVerticesID; GLuint _vboNormalsID; GLuint _vboColorsID; diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 2ba4d05e31..8669ec7130 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -24,4 +24,5 @@ const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; typedef unsigned long int glBufferIndex; const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; +const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60; #endif diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 87e87ff1a7..72327c2346 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -438,6 +438,12 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { } } +void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue) { + unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); + this->readCodeColorBufferToTree(voxelData); + delete voxelData; +} + void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { // About the color of the sphere... we're going to make this sphere be a gradient // between two RGB colors. We will do the gradient along the phi spectrum diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index e5b18b86c0..2ccb704964 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -46,6 +46,7 @@ public: void reaverageVoxelColors(VoxelNode *startNode); void loadVoxelsFile(const char* fileName, bool wantColorRandomizer); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer); + void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue); void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL); From ac879f5809adbf1b287d36b283617310a5207c15 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 22:27:33 -0700 Subject: [PATCH 14/15] added corner voxels to scene --- voxel-server/src/main.cpp | 68 +++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index ecccbf0291..315a2bb09a 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -75,43 +75,57 @@ bool countVoxelsOperation(VoxelNode* node, void* extraData) { } void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { - printf("adding scene of spheres...\n"); - - int sphereBaseSize = 512; - - tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer); - printf("one sphere added...\n"); - tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("adding scene of spheres...\n"); + + int sphereBaseSize = 512; + + tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer); + printf("one sphere added...\n"); + tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true); - printf("two spheres added...\n"); - tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); - printf("three spheres added...\n"); - tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true); - printf("four spheres added...\n"); - tree->createSphere(0.030625, (1.0 - 0.030625), 0.06125, (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); - printf("five spheres added...\n"); - tree->createSphere(0.06125, 0.125, 0.125, (1.0 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("two spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("three spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true); + printf("four spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("five spheres added...\n"); + tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true); float radius = 0.0125f; - printf("6 spheres added...\n"); - tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("7 spheres added...\n"); - tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("8 spheres added...\n"); - tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("9 spheres added...\n"); - tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("10 spheres added...\n"); - tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("11 spheres added...\n"); + printf("6 spheres added...\n"); + tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("7 spheres added...\n"); + tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("8 spheres added...\n"); + tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("9 spheres added...\n"); + tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("10 spheres added...\n"); + tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("11 spheres added...\n"); + + float voxelSize = 1.0f/8; + printf("creating corner points...\n"); + tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255); + tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 ); + tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 ); + tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255); + + + tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255); + tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 ); + printf("DONE creating corner points...\n"); _nodeCount=0; tree->recurseTreeWithOperation(countVoxelsOperation); printf("Nodes after adding scene %d nodes\n", _nodeCount); - printf("DONE adding scene of spheres...\n"); + printf("DONE adding scene of spheres...\n"); } From d7e34d25bfe7ab3077cd7421fb23d3214a9fe1c1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 22:38:58 -0700 Subject: [PATCH 15/15] small tweak to corner boxes --- voxel-server/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 315a2bb09a..9f5fc75ccb 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -106,7 +106,7 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); printf("11 spheres added...\n"); - float voxelSize = 1.0f/8; + float voxelSize = 0.99f/8; printf("creating corner points...\n"); tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255); tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 );