From 1fb1622beb5d6e2e8ddd6baaadbbb12ac0c5f7ec Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Jul 2013 16:27:23 -0700 Subject: [PATCH 1/5] added sleep to sendVoxelOperation() to keep from overwhelming server --- interface/src/Application.cpp | 41 +++++++++++++++++++++++++----- libraries/voxels/src/VoxelTree.cpp | 2 +- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 75f45e8d91..96e3dbd3d6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1333,7 +1333,9 @@ struct SendVoxelsOperationArgs { unsigned char* newBaseOctCode; unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE]; int bufferInUse; - + uint64_t lastSendTime; + int packetsSent; + uint64_t bytesSent; }; bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) { @@ -1365,17 +1367,30 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) { codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX]; codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ]; - // TODO: sendVoxelsOperation() is sending voxels too fast. - // This printf function accidently slowed down sending - // and hot-fixed the bug when importing - // large PNG models (256x256 px and more) - static unsigned int sendVoxelsOperationCalled = 0; printf("sending voxel #%u\n", ++sendVoxelsOperationCalled); - // if we have room don't have room in the buffer, then send the previously generated message first if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) { + + args->packetsSent++; + args->bytesSent += args->bufferInUse; + controlledBroadcastToNodes(args->messageBuffer, args->bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1); args->bufferInUse = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // reset + + uint64_t now = usecTimestampNow(); + // dynamically sleep until we need to fire off the next set of voxels + const uint64_t CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packet every 10 milliseconds + uint64_t elapsed = now - args->lastSendTime; + int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed; + if (usecToSleep > 0) { + printLog("sendVoxelsOperation: packet: %d bytes:%ld elapsed %ld usecs, sleeping for %d usecs!\n", + args->packetsSent, args->bytesSent, elapsed, usecToSleep); + usleep(usecToSleep); + } else { + printLog("sendVoxelsOperation: packet: %d bytes:%ld elapsed %ld usecs, no need to sleep!\n", + args->packetsSent, args->bytesSent, elapsed); + } + args->lastSendTime = now; } // copy this node's code color details into our buffer. @@ -1442,6 +1457,9 @@ void Application::importVoxels() { // the server as an set voxel message, this will also rebase the voxels to the new location unsigned char* calculatedOctCode = NULL; SendVoxelsOperationArgs args; + args.lastSendTime = usecTimestampNow(); + args.packetsSent = 0; + args.bytesSent = 0; int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE); @@ -1462,6 +1480,9 @@ void Application::importVoxels() { // If we have voxels left in the packet, then send the packet if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) { controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1); + printLog("sending packet: %d\n", ++args.packetsSent); + args.bytesSent += args.bufferInUse; + printLog("total bytes sent: %ld\n", args.bytesSent); } if (calculatedOctCode) { @@ -1495,6 +1516,9 @@ void Application::pasteVoxels() { // Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to // the server as an set voxel message, this will also rebase the voxels to the new location SendVoxelsOperationArgs args; + args.lastSendTime = usecTimestampNow(); + args.packetsSent = 0; + args.bytesSent = 0; int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE); @@ -1516,6 +1540,9 @@ void Application::pasteVoxels() { // If we have voxels left in the packet, then send the packet if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) { controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1); + printLog("sending packet: %d\n", ++args.packetsSent); + args.bytesSent += args.bufferInUse; + printLog("total bytes sent: %ld\n", args.bytesSent); } if (calculatedOctCode) { diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index b84b374309..66fa81c425 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1251,7 +1251,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp } // wants occlusion culling & isLeaf() - bool shouldRender = childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust); + bool shouldRender = !params.viewFrustum ? true : childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust); // track children with actual color, only if the child wasn't previously in view! if (shouldRender && !childIsOccluded) { From 099fa4b4b10446912fe21cfbdf819ce580e35d14 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Jul 2013 16:40:00 -0700 Subject: [PATCH 2/5] fixed server persistance issue --- voxel-server/src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 254b1d2d96..e336234838 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -313,6 +313,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, uint64_t lastPersistVoxels = 0; void persistVoxelsWhenDirty() { uint64_t now = usecTimestampNow(); + if (::lastPersistVoxels == 0) { + ::lastPersistVoxels = now; + } int sinceLastTime = (now - ::lastPersistVoxels) / 1000; // check the dirty bit and persist here... From a3009981d0e04e573b6efd79ccbc7d110551b967 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Jul 2013 17:54:50 -0700 Subject: [PATCH 3/5] added Import Voxels to Clipboard --- interface/src/Application.cpp | 37 +++++++++++++++++++++++++++++++++++ interface/src/Application.h | 1 + 2 files changed, 38 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bcbe92f3bb..77f56fdd6b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1419,6 +1419,42 @@ void Application::exportVoxels() { _window->activateWindow(); } +void Application::importVoxelsToClipboard() { + QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); + QString fileNameString = QFileDialog::getOpenFileName( + _glWidget, tr("Import Voxels to Clipboard"), desktopLocation, + tr("Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)")); + + QByteArray fileNameAscii = fileNameString.toAscii(); + const char* fileName = fileNameAscii.data(); + + _clipboardTree.eraseAllVoxels(); + if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) { + QImage pngImage = QImage(fileName); + if (pngImage.height() != pngImage.width()) { + printLog("ERROR: Bad PNG size: height != width.\n"); + return; + } + + const uint32_t* pixels; + if (pngImage.format() == QImage::Format_ARGB32) { + pixels = reinterpret_cast(pngImage.constBits()); + } else { + QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32); + pixels = reinterpret_cast(tmp.constBits()); + } + + _clipboardTree.readFromSquareARGB32Pixels(pixels, pngImage.height()); + } else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) { + _clipboardTree.readFromSVOFile(fileName); + } else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) { + _clipboardTree.readFromSchematicFile(fileName); + } + + // restore the main window's active state + _window->activateWindow(); +} + void Application::importVoxels() { QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); QString fileNameString = QFileDialog::getOpenFileName( @@ -1658,6 +1694,7 @@ void Application::initMenu() { voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E); voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I); + voxelMenu->addAction("Import Voxels to Clipboard", this, SLOT(importVoxelsToClipboard()), Qt::SHIFT | Qt::CTRL | Qt::Key_I); voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X); voxelMenu->addAction("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C); voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V); diff --git a/interface/src/Application.h b/interface/src/Application.h index cb1335887d..4c1cfa5969 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -153,6 +153,7 @@ private slots: void exportSettings(); void exportVoxels(); void importVoxels(); + void importVoxelsToClipboard(); void cutVoxels(); void copyVoxels(); void pasteVoxels(); From 42e5440b7b8406b0fb158777f314ae13c8509936 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Jul 2013 10:00:55 -0700 Subject: [PATCH 4/5] CR feedback --- interface/src/Application.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fa36847805..772cae733d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1455,11 +1455,11 @@ void Application::exportVoxels() { _window->activateWindow(); } +const char* IMPORT_FILE_TYPES = "Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)"; void Application::importVoxelsToClipboard() { QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); - QString fileNameString = QFileDialog::getOpenFileName( - _glWidget, tr("Import Voxels to Clipboard"), desktopLocation, - tr("Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)")); + QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels to Clipboard"), desktopLocation, + tr(IMPORT_FILE_TYPES)); QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); @@ -1493,9 +1493,8 @@ void Application::importVoxelsToClipboard() { void Application::importVoxels() { QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); - QString fileNameString = QFileDialog::getOpenFileName( - _glWidget, tr("Import Voxels"), desktopLocation, - tr("Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)")); + QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation, + tr(IMPORT_FILE_TYPES)); QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); From 440352c584da853d8469572d3bd72d2b7b33cef9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Jul 2013 10:02:27 -0700 Subject: [PATCH 5/5] white space --- interface/src/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 772cae733d..c28c8a9097 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1479,8 +1479,7 @@ void Application::importVoxelsToClipboard() { QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32); pixels = reinterpret_cast(tmp.constBits()); } - - _clipboardTree.readFromSquareARGB32Pixels(pixels, pngImage.height()); + _clipboardTree.readFromSquareARGB32Pixels(pixels, pngImage.height()); } else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) { _clipboardTree.readFromSVOFile(fileName); } else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) {