From d1d2e75143b110bbedd0e843fa0d898b716e4b69 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 28 May 2013 19:00:02 -0700 Subject: [PATCH 01/19] first cut at export and import of voxels --- interface/src/Application.cpp | 40 +++++++++++++++++++++++++++++- interface/src/Application.h | 5 +++- interface/src/VoxelSystem.cpp | 12 +++++++++ interface/src/VoxelSystem.h | 2 ++ libraries/voxels/src/VoxelTree.cpp | 11 +++++--- libraries/voxels/src/VoxelTree.h | 4 +-- voxel-server/src/main.cpp | 2 +- 7 files changed, 68 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a0979eb4b9..b18a0095e7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -853,7 +854,10 @@ void Application::idle() { // red indicates deletion _mouseVoxel.red = 255; _mouseVoxel.green = _mouseVoxel.blue = 0; - + } else if (_selectVoxelMode->isChecked()) { + // yellow indicates deletion + _mouseVoxel.red = _mouseVoxel.green = 255; + _mouseVoxel.blue = 0; } else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked() QColor paintColor = _voxelPaintColor->data().value(); _mouseVoxel.red = paintColor.red(); @@ -1136,6 +1140,35 @@ void Application::chooseVoxelPaintColor() { // restore the main window's active state _window->activateWindow(); } + +void Application::exportVoxels() { + QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.hio2", + tr("High Fidelity Voxel Files (*.hio2)")); + QByteArray fileNameAscii = fileNameString.toAscii(); + const char* fileName = fileNameAscii.data(); + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + printf("exportVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName, + _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (selectedNode) { + selectedNode->printDebugDetails("selected voxel"); + } + _voxels.writeToFileV2(fileName,selectedNode); +} + +void Application::importVoxels() { + QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), "~", tr("High Fidelity Voxel Files (*.hio2)")); + QByteArray fileNameAscii = fileNameString.toAscii(); + const char* fileName = fileNameAscii.data(); + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + printf("importVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName, + _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (selectedNode) { + selectedNode->printDebugDetails("selected voxel"); + } + + // not yet supported!!! + _voxels.readFromFileV2(fileName,selectedNode); +} void Application::initMenu() { QMenuBar* menuBar = new QMenuBar(); @@ -1202,6 +1235,9 @@ void Application::initMenu() { (_colorVoxelMode = voxelMenu->addAction( "Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_3))->setCheckable(true); _voxelModeActions->addAction(_colorVoxelMode); + (_selectVoxelMode = voxelMenu->addAction( + "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_8))->setCheckable(true); + _voxelModeActions->addAction(_selectVoxelMode); voxelMenu->addAction("Place Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::Key_4); voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), Qt::Key_5); @@ -1212,6 +1248,8 @@ void Application::initMenu() { _voxelPaintColor->setData(paintColor); _voxelPaintColor->setIcon(createSwatchIcon(paintColor)); (_destructiveAddVoxel = voxelMenu->addAction("Create Voxel is Destructive"))->setCheckable(true); + voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E); + voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I); QMenu* frustumMenu = menuBar->addMenu("Frustum"); (_frustumOn = frustumMenu->addAction("Display Frustum"))->setCheckable(true); diff --git a/interface/src/Application.h b/interface/src/Application.h index 35d49d275a..ed03708bd9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -99,7 +99,9 @@ private slots: void decreaseVoxelSize(); void increaseVoxelSize(); void chooseVoxelPaintColor(); - + void exportVoxels(); + void importVoxels(); + private: void initMenu(); @@ -155,6 +157,7 @@ private: QAction* _addVoxelMode; // Whether add voxel mode is enabled QAction* _deleteVoxelMode; // Whether delete voxel mode is enabled QAction* _colorVoxelMode; // Whether color voxel mode is enabled + QAction* _selectVoxelMode; // Whether select voxel mode is enabled QAction* _voxelPaintColor; // The color with which to paint voxels QAction* _destructiveAddVoxel; // when doing voxel editing do we want them to be destructive QAction* _frustumOn; // Whether or not to display the debug view frustum diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ea8787a902..2a0a7e7a7a 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -70,6 +70,18 @@ void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) setupNewVoxelsForDrawing(); } +void VoxelSystem::writeToFileV2(const char* filename, VoxelNode* node) const { + _tree->writeToFileV2(filename, node); +} + +bool VoxelSystem::readFromFileV2(const char* filename, VoxelNode* node) { + bool result = _tree->readFromFileV2(filename, node); + if (result) { + setupNewVoxelsForDrawing(); + } + return result; +} + long int VoxelSystem::getVoxelsCreated() { return _tree->voxelsCreated; } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 7bffb1d33c..1aeb66a7c6 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -44,6 +44,8 @@ public: void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; }; void setCamera(Camera* newCamera) { _camera = newCamera; }; void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); + void writeToFileV2(const char* filename, VoxelNode* node) const; + bool readFromFileV2(const char* filename, VoxelNode* node); long int getVoxelsCreated(); long int getVoxelsColored(); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 798b447d6c..89b584a541 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1105,7 +1105,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco return bytesAtThisLevel; } -bool VoxelTree::readFromFileV2(const char* fileName) { +bool VoxelTree::readFromFileV2(const char* fileName, VoxelNode* node) { std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate); if(file.is_open()) { printLog("loading file %s...\n", fileName); @@ -1126,7 +1126,7 @@ bool VoxelTree::readFromFileV2(const char* fileName) { return false; } -void VoxelTree::writeToFileV2(const char* fileName) const { +void VoxelTree::writeToFileV2(const char* fileName, VoxelNode* node) const { std::ofstream file(fileName, std::ios::out|std::ios::binary); @@ -1134,7 +1134,12 @@ void VoxelTree::writeToFileV2(const char* fileName) const { printLog("saving to file %s...\n", fileName); VoxelNodeBag nodeBag; - nodeBag.insert(rootNode); + // If we were given a specific node, start from there, otherwise start from root + if (node) { + nodeBag.insert(node); + } else { + nodeBag.insert(rootNode); + } static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static int bytesWritten = 0; diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 0643b1038e..5e56be5062 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -91,8 +91,8 @@ public: void loadVoxelsFile(const char* fileName, bool wantColorRandomizer); // these will read/write files that match the wireformat, excluding the 'V' leading - void writeToFileV2(const char* filename) const; - bool readFromFileV2(const char* filename); + void writeToFileV2(const char* filename, VoxelNode* node = NULL) const; + bool readFromFileV2(const char* filename, VoxelNode* node = NULL); unsigned long getVoxelCount(); diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 1a93021f09..70f7ab8752 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -517,7 +517,7 @@ int main(int argc, const char * argv[]) { const char* INPUT_FILE = "-i"; const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); if (voxelsFilename) { - randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer); + randomTree.readFromFileV2(voxelsFilename); } // Check to see if the user passed in a command line option for setting packet send rate From eb675c8dd79d16ca17d2e6de7da0b129247fe82e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 May 2013 08:25:30 -0700 Subject: [PATCH 02/19] fix crash when no audio mixer available --- libraries/audio/src/AudioInjectionManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjectionManager.cpp b/libraries/audio/src/AudioInjectionManager.cpp index 275161730e..b49151616d 100644 --- a/libraries/audio/src/AudioInjectionManager.cpp +++ b/libraries/audio/src/AudioInjectionManager.cpp @@ -58,7 +58,10 @@ void* AudioInjectionManager::injectAudioViaThread(void* args) { // if we don't have an explicit destination socket then pull active socket for current audio mixer from agent list if (!_isDestinationSocketExplicit) { - _destinationSocket = *AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER)->getActiveSocket(); + Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER); + if (audioMixer) { + _destinationSocket = *audioMixer->getActiveSocket(); + } } injector->injectAudio(_injectorSocket, &_destinationSocket); From 377fb1e936ef64670145d947b771bba1d0e1ad18 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 May 2013 12:06:58 -0700 Subject: [PATCH 03/19] latest copy and paste --- interface/src/Application.cpp | 35 +++++++++++++++----- interface/src/Application.h | 2 ++ interface/src/main.cpp | 14 ++++++++ libraries/shared/src/OctalCode.cpp | 51 ++++++++++++++++++++++++++++++ libraries/shared/src/OctalCode.h | 3 ++ libraries/voxels/src/VoxelTree.cpp | 27 +++++++++++++++- libraries/voxels/src/VoxelTree.h | 4 +++ 7 files changed, 127 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3908164890..95e3e5f1c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1153,6 +1153,22 @@ void Application::importVoxels() { // not yet supported!!! _voxels.readFromFileV2(fileName,selectedNode); } + +void Application::copyVoxels() { + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + printf("copyVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (selectedNode) { + selectedNode->printDebugDetails("selected voxel"); + } +} + +void Application::pasteVoxels() { + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + printf("pasteVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (selectedNode) { + selectedNode->printDebugDetails("selected voxel"); + } +} void Application::initMenu() { QMenuBar* menuBar = new QMenuBar(); @@ -1211,29 +1227,32 @@ void Application::initMenu() { _voxelModeActions = new QActionGroup(this); _voxelModeActions->setExclusive(false); // exclusivity implies one is always checked (_addVoxelMode = voxelMenu->addAction( - "Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_1))->setCheckable(true); + "Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_A))->setCheckable(true); _voxelModeActions->addAction(_addVoxelMode); (_deleteVoxelMode = voxelMenu->addAction( - "Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_2))->setCheckable(true); + "Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_D))->setCheckable(true); _voxelModeActions->addAction(_deleteVoxelMode); (_colorVoxelMode = voxelMenu->addAction( - "Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_3))->setCheckable(true); + "Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_C))->setCheckable(true); _voxelModeActions->addAction(_colorVoxelMode); (_selectVoxelMode = voxelMenu->addAction( - "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_8))->setCheckable(true); + "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_S))->setCheckable(true); _voxelModeActions->addAction(_selectVoxelMode); - voxelMenu->addAction("Place Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::Key_4); - voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), Qt::Key_5); - voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), Qt::Key_6); + voxelMenu->addAction("Place Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::SHIFT | Qt::Key_P); + voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), Qt::CTRL | Qt::SHIFT | Qt::Key_Minus); + voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), Qt::CTRL | Qt::SHIFT | Qt::Key_Plus); - _voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, SLOT(chooseVoxelPaintColor()), Qt::Key_7); + _voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, SLOT(chooseVoxelPaintColor()), + Qt::CTRL | Qt::SHIFT | Qt::Key_C); QColor paintColor(128, 128, 128); _voxelPaintColor->setData(paintColor); _voxelPaintColor->setIcon(createSwatchIcon(paintColor)); (_destructiveAddVoxel = voxelMenu->addAction("Create Voxel is Destructive"))->setCheckable(true); 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("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C); + voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V); QMenu* frustumMenu = menuBar->addMenu("Frustum"); (_frustumOn = frustumMenu->addAction("Display Frustum"))->setCheckable(true); diff --git a/interface/src/Application.h b/interface/src/Application.h index ed03708bd9..57605f8cc5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -101,6 +101,8 @@ private slots: void chooseVoxelPaintColor(); void exportVoxels(); void importVoxels(); + void copyVoxels(); + void pasteVoxels(); private: diff --git a/interface/src/main.cpp b/interface/src/main.cpp index ea915658af..5091eb9f4f 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -18,7 +18,21 @@ #include "Application.h" #include "Log.h" +#include + int main(int argc, const char * argv[]) { + + unsigned char test1[2] = {2, 0xE0 }; + unsigned char test2[2] = {2, 0xFC }; + + unsigned char* result1 = chopOctalCode((unsigned char*)&test1, 1); + + printOctalCode((unsigned char*)&test1); + printOctalCode(result1); + + unsigned char* result2 = chopOctalCode((unsigned char*)&test2, 1); + printOctalCode((unsigned char*)&test2); + printOctalCode(result2); timeval startup_time; gettimeofday(&startup_time, NULL); diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index d218639882..b69136ddb6 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -168,3 +168,54 @@ OctalCodeComparison compareOctalCodes(unsigned char* codeA, unsigned char* codeB return result; } + +char getOctalCodeSectionValue(unsigned char* octalCode, int section) { + return sectionValue(octalCode + 1 + (3 * section / 8), (3 * section) % 8); +} + +void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectionValue) { + unsigned char* byteAt = octalCode + 1 + (3 * section / 8); + char bitInByte = (3 * section) % 8; + char shiftBy = 8 - bitInByte - 3; + const unsigned char UNSHIFTED_MASK = 0x03; + unsigned char shiftedMask; + unsigned char shiftedValue; + + + if (shiftBy >=0) { + shiftedMask = UNSHIFTED_MASK << shiftBy; + shiftedValue = sectionValue << shiftBy; + } else { + shiftedMask = UNSHIFTED_MASK >> -shiftBy; + shiftedValue = sectionValue >> -shiftBy; + } + + byteAt[0] = byteAt[0] & (shiftedMask | shiftedValue); + if (bitInByte >= 6) { + shiftBy = bitInByte + 1; + shiftedMask = UNSHIFTED_MASK << shiftBy; + shiftedValue = sectionValue << shiftBy; + + byteAt[1] = byteAt[1] & (shiftedMask | shiftedValue); + } +} + +unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels) { + int codeLength = numberOfThreeBitSectionsInCode(originalOctalCode); + unsigned char* newCode = NULL; + if (codeLength > chopLevels) { + int newLength = codeLength - chopLevels; + newCode = new unsigned char[newLength+1]; + *newCode = newLength; // set the length byte + + for (int section = chopLevels; section < codeLength; section++) { + char sectionValue = getOctalCodeSectionValue(originalOctalCode, section); + setOctalCodeSectionValue(newCode, section - chopLevels, sectionValue); + } + } + return newCode; +} + +unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode) { +} + diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index bf4a6ef699..bce7a066b9 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -17,6 +17,9 @@ bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * child int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode); unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber); +unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels); +unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode); + // Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return // but other than that these do the same thing. diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 01a9ace8b6..a0864964a2 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -53,7 +53,7 @@ VoxelTree::~VoxelTree() { // Recurses voxel tree calling the RecurseVoxelTreeOperation function for each node. // stops recursion if operation function returns false. void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData) { - recurseNodeWithOperation(rootNode, operation,extraData); + recurseNodeWithOperation(rootNode, operation, extraData); } // Recurses voxel node with an operation function @@ -1165,3 +1165,28 @@ bool VoxelTree::countVoxelsOperation(VoxelNode* node, void* extraData) { (*(unsigned long*)extraData)++; return true; // keep going } + +void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) { + + printLog("copySubTreeIntoNewTree()...\n"); + + VoxelNodeBag nodeBag; + // If we were given a specific node, start from there, otherwise start from root + nodeBag.insert(startNode); + + static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static + int bytesWritten = 0; + + while (!nodeBag.isEmpty()) { + VoxelNode* subTree = nodeBag.extract(); + + // ask our tree to write a bitsteam + bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], + MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); + + // ask destination tree to read the bitstream + destinationTree->readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS); + } + + +} diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 5e56be5062..eccc4e0434 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -95,6 +95,9 @@ public: bool readFromFileV2(const char* filename, VoxelNode* node = NULL); unsigned long getVoxelCount(); + + void copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot); + void copyNodeIntoTree(VoxelNode* node); private: int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, @@ -107,6 +110,7 @@ private: bool deltaViewFrustum, const ViewFrustum* lastViewFrustum); static bool countVoxelsOperation(VoxelNode* node, void* extraData); + static bool copySubTreeIntoNewTreeOperation(VoxelNode* node, void* extraData); void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData); VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const; From 46c6f2f9b5f3add89a29fb695a53401a68c5057f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 May 2013 15:02:28 -0700 Subject: [PATCH 04/19] latest copy paste --- interface/src/Application.cpp | 13 +++++++- interface/src/Application.h | 2 ++ interface/src/VoxelSystem.cpp | 9 ++++++ interface/src/VoxelSystem.h | 4 +++ interface/src/main.cpp | 13 -------- libraries/shared/src/OctalCode.cpp | 16 ++++++--- libraries/shared/src/OctalCode.h | 1 + libraries/voxels/src/VoxelTree.cpp | 52 ++++++++++++++++++++++++------ libraries/voxels/src/VoxelTree.h | 26 +++++++-------- 9 files changed, 95 insertions(+), 41 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 95e3e5f1c1..7f5eeccd76 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1159,6 +1159,7 @@ void Application::copyVoxels() { printf("copyVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode) { selectedNode->printDebugDetails("selected voxel"); + _voxels.copySubTreeIntoNewTree(selectedNode, &_clipboardTree, true); } } @@ -1166,7 +1167,17 @@ void Application::pasteVoxels() { VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); printf("pasteVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode) { - selectedNode->printDebugDetails("selected voxel"); + //selectedNode->printDebugDetails("selected voxel"); + + // First, create a temporary Paste Tree + VoxelTree _temporaryPasteTree; + + // Create a destination node to paste into + _temporaryPasteTree.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s, 0, 0, 0); + + // Paste into the temporary tree + destinationNode = _temporaryPasteTree.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + _temporaryPasteTree.copyFromTreeIntoSubTree(&_clipboardTree, destinationNode); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 57605f8cc5..85d5d7ef43 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -184,6 +184,8 @@ private: Stars _stars; VoxelSystem _voxels; + VoxelTree _clipboardTree; // if I copy/paste + QByteArray _voxelsFilename; bool _wantToKillLocalVoxels; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 2a0a7e7a7a..359e5b77af 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1156,3 +1156,12 @@ void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bo _tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug); setupNewVoxelsForDrawing(); }; + +void VoxelSystem::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) { + _tree->copySubTreeIntoNewTree(startNode, destinationTree, rebaseToRoot); +} + +void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) { + _tree->copyFromTreeIntoSubTree(sourceTree, destinationNode); +} + diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 1aeb66a7c6..c15ba53ba0 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -85,6 +85,10 @@ 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 copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot); + void copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode); + private: // disallow copying of VoxelSystem objects VoxelSystem(const VoxelSystem&); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 5091eb9f4f..8894e5bd7c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -21,19 +21,6 @@ #include int main(int argc, const char * argv[]) { - - unsigned char test1[2] = {2, 0xE0 }; - unsigned char test2[2] = {2, 0xFC }; - - unsigned char* result1 = chopOctalCode((unsigned char*)&test1, 1); - - printOctalCode((unsigned char*)&test1); - printOctalCode(result1); - - unsigned char* result2 = chopOctalCode((unsigned char*)&test2, 1); - printOctalCode((unsigned char*)&test2); - printOctalCode(result2); - timeval startup_time; gettimeofday(&startup_time, NULL); diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index b69136ddb6..f331545b33 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -170,14 +170,18 @@ OctalCodeComparison compareOctalCodes(unsigned char* codeA, unsigned char* codeB char getOctalCodeSectionValue(unsigned char* octalCode, int section) { - return sectionValue(octalCode + 1 + (3 * section / 8), (3 * section) % 8); + int startAtByte = 1 + (3 * section / 8); + char startIndexInByte = (3 * section) % 8; + unsigned char* startByte = octalCode + startAtByte; + + return sectionValue(startByte, startIndexInByte); } void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectionValue) { unsigned char* byteAt = octalCode + 1 + (3 * section / 8); char bitInByte = (3 * section) % 8; char shiftBy = 8 - bitInByte - 3; - const unsigned char UNSHIFTED_MASK = 0x03; + const unsigned char UNSHIFTED_MASK = 0x07; unsigned char shiftedMask; unsigned char shiftedValue; @@ -190,13 +194,17 @@ void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectio shiftedValue = sectionValue >> -shiftBy; } - byteAt[0] = byteAt[0] & (shiftedMask | shiftedValue); + unsigned char oldValue = *byteAt & ~shiftedMask; + unsigned char newValue = oldValue | shiftedValue; + *byteAt = newValue; if (bitInByte >= 6) { shiftBy = bitInByte + 1; shiftedMask = UNSHIFTED_MASK << shiftBy; shiftedValue = sectionValue << shiftBy; - byteAt[1] = byteAt[1] & (shiftedMask | shiftedValue); + oldValue = byteAt[1] & ~shiftedMask; + newValue = oldValue | shiftedValue; + byteAt[1] = newValue; } } diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index bce7a066b9..1849989cc3 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -19,6 +19,7 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels); unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode); +int numberOfThreeBitSectionsInCode(unsigned char * octalCode); // Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index a0864964a2..562cfcc88c 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -212,10 +212,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, } void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, - bool includeColor, bool includeExistsBits) { + bool includeColor, bool includeExistsBits, VoxelNode* destinationNode) { int bytesRead = 0; unsigned char* bitstreamAt = bitstream; + // If destination node is not included, set it to root + if (!destinationNode) { + destinationNode = rootNode; + } + _nodesChangedFromBitstream = 0; // Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes @@ -223,14 +228,14 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int // if there are more bytes after that, it's assumed to be another root relative tree while (bitstreamAt < bitstream + bufferSizeBytes) { - VoxelNode* bitstreamRootNode = nodeForOctalCode(rootNode, (unsigned char *)bitstreamAt, NULL); + VoxelNode* bitstreamRootNode = nodeForOctalCode(destinationNode, (unsigned char *)bitstreamAt, NULL); if (*bitstreamAt != *bitstreamRootNode->getOctalCode()) { // if the octal code returned is not on the same level as // the code being searched for, we have VoxelNodes to create // 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); + bitstreamRootNode = createMissingNode(destinationNode, (unsigned char*) bitstreamAt); if (bitstreamRootNode->isDirty()) { _isDirty = true; _nodesChangedFromBitstream++; @@ -862,7 +867,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, bool includeExistsBits, - bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const { + int chopLevels, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const { // How many bytes have we written so far at this level; int bytesWritten = 0; @@ -882,7 +887,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned int currentEncodeLevel = 0; int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel, node, outputBuffer, availableBytes, - bag, viewFrustum, includeColor, includeExistsBits, + bag, viewFrustum, includeColor, includeExistsBits, chopLevels, deltaViewFrustum, lastViewFrustum); // if childBytesWritten == 1 then something went wrong... that's not possible @@ -907,7 +912,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned 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 { + int chopLevels, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const { // How many bytes have we written so far at this level; int bytesAtThisLevel = 0; @@ -1062,7 +1067,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco int thisLevel = currentEncodeLevel; int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode, outputBuffer, availableBytes, bag, - viewFrustum, includeColor, includeExistsBits, + viewFrustum, includeColor, includeExistsBits, chopLevels, deltaViewFrustum, lastViewFrustum); // if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space, @@ -1173,6 +1178,12 @@ void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinat VoxelNodeBag nodeBag; // If we were given a specific node, start from there, otherwise start from root nodeBag.insert(startNode); + + int chopLevels = 0; + + if (rebaseToRoot) { + chopLevels = numberOfThreeBitSectionsInCode(startNode->getOctalCode()); + } static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static int bytesWritten = 0; @@ -1182,11 +1193,32 @@ void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinat // ask our tree to write a bitsteam bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], - MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); + MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS, chopLevels); // ask destination tree to read the bitstream destinationTree->readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS); } - - } + +void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) { + printLog("copyFromTreeIntoSubTree()...\n"); + + VoxelNodeBag nodeBag; + // If we were given a specific node, start from there, otherwise start from root + nodeBag.insert(sourceTree->rootNode); + + static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static + int bytesWritten = 0; + + while (!nodeBag.isEmpty()) { + VoxelNode* subTree = nodeBag.extract(); + + // ask our tree to write a bitsteam + bytesWritten = sourceTree->encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], + MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); + + // ask destination tree to read the bitstream + readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS); + } +} + diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index eccc4e0434..a2302f6cc7 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -44,19 +44,20 @@ public: VoxelTree(bool shouldReaverage = false); ~VoxelTree(); - VoxelNode *rootNode; + VoxelNode* rootNode; int leavesWrittenToBitstream; void eraseAllVoxels(); - void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes); - void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, - bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS); - void readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool destructive = false); - void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = ACTUALLY_DELETE, + void processRemoveVoxelBitstream(unsigned char* bitstream, int bufferSizeBytes); + void readBitstreamToTree(unsigned char* bitstream, unsigned long int bufferSizeBytes, + bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS, + VoxelNode* destinationNode = NULL); + void readCodeColorBufferToTree(unsigned char* codeColorBuffer, bool destructive = false); + void deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage = ACTUALLY_DELETE, bool collapseEmptyTrees = DONT_COLLAPSE); - void printTreeForDebugging(VoxelNode *startNode); - void reaverageVoxelColors(VoxelNode *startNode); + void printTreeForDebugging(VoxelNode* startNode); + void reaverageVoxelColors(VoxelNode* startNode); void deleteVoxelAt(float x, float y, float z, float s, bool stage = false); VoxelNode* getVoxelAt(float x, float y, float z, float s) const; @@ -70,7 +71,7 @@ public: int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag, const ViewFrustum* viewFrustum, - bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS, + bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS, int chopLevels = 0, bool deltaViewFrustum = false, const ViewFrustum* lastViewFrustum = NULL) const; int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag, @@ -97,20 +98,19 @@ public: unsigned long getVoxelCount(); void copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot); - void copyNodeIntoTree(VoxelNode* node); + void copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode); private: int 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; + const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits, + int chopLevels, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const; int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum); static bool countVoxelsOperation(VoxelNode* node, void* extraData); - static bool copySubTreeIntoNewTreeOperation(VoxelNode* node, void* extraData); void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData); VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const; From e5e200345b93bcd42af1eb2102e7857e0f383470 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 31 May 2013 11:52:18 -0700 Subject: [PATCH 05/19] more work on copy and paste --- interface/src/Application.cpp | 67 ++++++++++++++++++++++++++---- interface/src/Application.h | 2 + libraries/shared/src/OctalCode.cpp | 21 +++++++++- libraries/shared/src/OctalCode.h | 7 ++-- libraries/voxels/src/VoxelTree.cpp | 22 ++++++++-- 5 files changed, 102 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b6aba80c06..5395bfa54f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "Application.h" #include "InterfaceConfig.h" @@ -1319,26 +1320,76 @@ void Application::copyVoxels() { if (selectedNode) { selectedNode->printDebugDetails("selected voxel"); _voxels.copySubTreeIntoNewTree(selectedNode, &_clipboardTree, true); + + // debug tree + _clipboardTree.printTreeForDebugging(_clipboardTree.rootNode); } } +const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500; +struct SendVoxelsOperataionArgs { + unsigned char* newBaseOctCode; + unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE]; + int bufferInUse; + +}; + void Application::pasteVoxels() { VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); printf("pasteVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode) { //selectedNode->printDebugDetails("selected voxel"); - // First, create a temporary Paste Tree - VoxelTree _temporaryPasteTree; + // 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 + SendVoxelsOperataionArgs args; + args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; + unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)]; + *sequenceAt = 0; + args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence + args.newBaseOctCode = selectedNode->getOctalCode(); + _clipboardTree.recurseTreeWithOperation(sendVoxelsOperataion, &args); - // Create a destination node to paste into - _temporaryPasteTree.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s, 0, 0, 0); - - // Paste into the temporary tree - destinationNode = _temporaryPasteTree.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - _temporaryPasteTree.copyFromTreeIntoSubTree(&_clipboardTree, destinationNode); + // If we have voxels left in the packet, then send the packet + if (args.bufferInUse > 1) { + AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1); + } } } + +bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { + SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData; + if (node->isColored()) { + const int SIZE_OF_COLOR_DATA = 3; + const int RED_INDEX = 0; + const int GREEN_INDEX = 1; + const int BLUE_INDEX = 2; + unsigned char* nodeOctalCode = node->getOctalCode(); + printOctalCode(nodeOctalCode); + unsigned char* rebasedCodeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); + printOctalCode(rebasedCodeColorBuffer); + int rebasedCodeLength = numberOfThreeBitSectionsInCode(rebasedCodeColorBuffer); + int bytesInRebasedCode = bytesRequiredForCodeLength(rebasedCodeLength); + int codeAndColorLength = bytesInRebasedCode + SIZE_OF_COLOR_DATA; + + // copy the colors over + rebasedCodeColorBuffer[bytesInRebasedCode + RED_INDEX ] = node->getColor()[RED_INDEX ]; + rebasedCodeColorBuffer[bytesInRebasedCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX]; + rebasedCodeColorBuffer[bytesInRebasedCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ]; + + // 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) { + AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1); + args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(int); // reset to command + sequence + } + + // copy this node's code color details into our buffer. + memcpy(&args->messageBuffer[args->bufferInUse], rebasedCodeColorBuffer, codeAndColorLength); + args->bufferInUse += codeAndColorLength; + } + return true; // keep going +} + void Application::initMenu() { QMenuBar* menuBar = new QMenuBar(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9a6d02ecc0..7761d9a84b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -160,6 +160,8 @@ private slots: void pasteVoxels(); private: + + static bool sendVoxelsOperataion(VoxelNode* node, void* extraData); void initMenu(); void updateFrustumRenderModeAction(); diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index f331545b33..150789bec8 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -224,6 +224,25 @@ unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels) { return newCode; } -unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode) { +unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode, bool includeColorSpace) { + int oldCodeLength = numberOfThreeBitSectionsInCode(originalOctalCode); + int newParentCodeLength = numberOfThreeBitSectionsInCode(newParentOctalCode); + int newCodeLength = newParentCodeLength + oldCodeLength; + const int COLOR_SPACE = 3; + int bufferLength = newCodeLength + (includeColorSpace ? COLOR_SPACE : 0); + unsigned char* newCode = new unsigned char[bufferLength]; + *newCode = newCodeLength; // set the length byte + + // copy parent code section first + for (int sectionFromParent = 0; sectionFromParent < newParentCodeLength; sectionFromParent++) { + char sectionValue = getOctalCodeSectionValue(newParentOctalCode, sectionFromParent); + setOctalCodeSectionValue(newCode, sectionFromParent, sectionValue); + } + // copy original code section next + for (int sectionFromOriginal = 0; sectionFromOriginal < oldCodeLength; sectionFromOriginal++) { + char sectionValue = getOctalCodeSectionValue(originalOctalCode, sectionFromOriginal); + setOctalCodeSectionValue(newCode, sectionFromOriginal + newParentCodeLength, sectionValue); + } + return newCode; } diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index 1849989cc3..bfed24a87c 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -16,11 +16,10 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes); bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode); int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode); unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber); - -unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels); -unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode); int numberOfThreeBitSectionsInCode(unsigned char * octalCode); - +unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels); +unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode, + bool includeColorSpace = false); // Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return // but other than that these do the same thing. diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 562cfcc88c..704c15e4db 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -878,9 +878,22 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned } // write the octal code - int codeLength = bytesRequiredForCodeLength(*node->getOctalCode()); - memcpy(outputBuffer,node->getOctalCode(),codeLength); - + int codeLength; + if (chopLevels) { + unsigned char* newCode = chopOctalCode(node->getOctalCode(), chopLevels); + if (newCode) { + codeLength = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(newCode)); + memcpy(outputBuffer, newCode, codeLength); + delete newCode; + } else { + codeLength = 1; // chopped to root! + *outputBuffer = 0; // root + } + } else { + codeLength = bytesRequiredForCodeLength(*node->getOctalCode()); + memcpy(outputBuffer, node->getOctalCode(), codeLength); + } + outputBuffer += codeLength; // move the pointer bytesWritten += codeLength; // keep track of byte count availableBytes -= codeLength; // keep track or remaining space @@ -1183,6 +1196,7 @@ void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinat if (rebaseToRoot) { chopLevels = numberOfThreeBitSectionsInCode(startNode->getOctalCode()); + printLog("copySubTreeIntoNewTree()...rebaseToRoot=true, chopLevels=%d\n", chopLevels); } static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static @@ -1218,7 +1232,7 @@ void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destin MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); // ask destination tree to read the bitstream - readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS); + readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS,destinationNode); } } From 7dd217b3182eb6df44439d53c60a0accbd25c821 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 3 Jun 2013 10:57:18 -0700 Subject: [PATCH 06/19] more work on copy and paste --- interface/src/Application.cpp | 79 +++++++++++++++++++------------ libraries/shared/src/SharedUtil.h | 2 +- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5395bfa54f..30f4d958a2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1002,7 +1002,7 @@ void Application::idle() { _mouseVoxel.z += faceVector.z * _mouseVoxel.s; } } - } else if (_addVoxelMode->isChecked()) { + } else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) { // place the voxel a fixed distance away float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE; glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f); @@ -1318,11 +1318,16 @@ void Application::copyVoxels() { VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); printf("copyVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode) { - selectedNode->printDebugDetails("selected voxel"); + //selectedNode->printDebugDetails("selected voxel"); + + // clear the clipboard first... + _clipboardTree.eraseAllVoxels(); + + // then copy onto it _voxels.copySubTreeIntoNewTree(selectedNode, &_clipboardTree, true); // debug tree - _clipboardTree.printTreeForDebugging(_clipboardTree.rootNode); + //_clipboardTree.printTreeForDebugging(_clipboardTree.rootNode); } } @@ -1335,25 +1340,37 @@ struct SendVoxelsOperataionArgs { }; void Application::pasteVoxels() { + unsigned char* calculatedOctCode = NULL; VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); printf("pasteVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + + // 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 + SendVoxelsOperataionArgs args; + args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; + unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)]; + *sequenceAt = 0; + args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence + + // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the + // voxel size/position details. if (selectedNode) { //selectedNode->printDebugDetails("selected voxel"); - - // 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 - SendVoxelsOperataionArgs args; - args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; - unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)]; - *sequenceAt = 0; - args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence args.newBaseOctCode = selectedNode->getOctalCode(); - _clipboardTree.recurseTreeWithOperation(sendVoxelsOperataion, &args); - - // If we have voxels left in the packet, then send the packet - if (args.bufferInUse > 1) { - AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1); - } + } else { + printf("pasteVoxels() no voxel at current location, calculate octCode... \n"); + args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + } + + _clipboardTree.recurseTreeWithOperation(sendVoxelsOperataion, &args); + + // If we have voxels left in the packet, then send the packet + if (args.bufferInUse > 1) { + AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1); + } + + if (calculatedOctCode) { + delete calculatedOctCode; } } @@ -1449,33 +1466,35 @@ void Application::initMenu() { QMenu* voxelMenu = menuBar->addMenu("Voxels"); _voxelModeActions = new QActionGroup(this); _voxelModeActions->setExclusive(false); // exclusivity implies one is always checked + (_addVoxelMode = voxelMenu->addAction( - "Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_A))->setCheckable(true); + "Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_A))->setCheckable(true); _voxelModeActions->addAction(_addVoxelMode); (_deleteVoxelMode = voxelMenu->addAction( - "Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_D))->setCheckable(true); + "Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_D))->setCheckable(true); _voxelModeActions->addAction(_deleteVoxelMode); (_colorVoxelMode = voxelMenu->addAction( - "Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_C))->setCheckable(true); + "Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_B))->setCheckable(true); _voxelModeActions->addAction(_colorVoxelMode); (_selectVoxelMode = voxelMenu->addAction( - "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::SHIFT | Qt::Key_S))->setCheckable(true); + "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true); _voxelModeActions->addAction(_selectVoxelMode); - voxelMenu->addAction("Place Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::SHIFT | Qt::Key_P); - voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), Qt::CTRL | Qt::SHIFT | Qt::Key_Minus); - voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), Qt::CTRL | Qt::SHIFT | Qt::Key_Plus); + voxelMenu->addAction("Place New Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::Key_N); + voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut); + voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), QKeySequence::ZoomIn); - _voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, SLOT(chooseVoxelPaintColor()), - Qt::CTRL | Qt::SHIFT | Qt::Key_C); + _voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, + SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C); QColor paintColor(128, 128, 128); _voxelPaintColor->setData(paintColor); _voxelPaintColor->setIcon(createSwatchIcon(paintColor)); (_destructiveAddVoxel = voxelMenu->addAction("Create Voxel is Destructive"))->setCheckable(true); - 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("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C); - voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V); + + 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("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C); + voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V); QMenu* frustumMenu = menuBar->addMenu("Frustum"); (_frustumOn = frustumMenu->addAction("Display Frustum"))->setCheckable(true); diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 8da9d7beca..6c48c9e42e 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -70,7 +70,7 @@ struct VoxelDetail { unsigned char blue; }; -unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, unsigned char g, unsigned char b ); +unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r = 0, unsigned char g = 0, unsigned char b = 0); bool createVoxelEditMessage(unsigned char command, short int sequence, int voxelCount, VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut); From 78fe89172ac221ad59e8bfab4c478234c5a62c0e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 3 Jun 2013 12:23:16 -0700 Subject: [PATCH 07/19] eyedropper mode, and import work --- interface/src/Application.cpp | 150 ++++++++++++++++++-------- interface/src/Application.h | 3 +- libraries/voxels/src/VoxelConstants.h | 9 +- 3 files changed, 115 insertions(+), 47 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 30f4d958a2..ab335dce97 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1285,6 +1285,58 @@ void Application::chooseVoxelPaintColor() { _window->activateWindow(); } +const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500; +struct SendVoxelsOperataionArgs { + unsigned char* newBaseOctCode; + unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE]; + int bufferInUse; + +}; + +bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { + SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData; + if (node->isColored()) { + unsigned char* nodeOctalCode = node->getOctalCode(); + printOctalCode(nodeOctalCode); + + unsigned char* codeColorBuffer = NULL; + int codeLength = 0; + int bytesInCode = 0; + int codeAndColorLength; + + // If the newBase is NULL, then don't rebase + if (args->newBaseOctCode) { + codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); + printOctalCode(codeColorBuffer); + codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer); + bytesInCode = bytesRequiredForCodeLength(codeLength); + codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; + } else { + codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode); + bytesInCode = bytesRequiredForCodeLength(codeLength); + codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; + codeColorBuffer = new unsigned char[codeAndColorLength]; + memcpy(codeColorBuffer, nodeOctalCode, bytesInCode); + } + + // copy the colors over + codeColorBuffer[bytesInCode + RED_INDEX ] = node->getColor()[RED_INDEX ]; + codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX]; + codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ]; + + // 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) { + AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1); + args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(int); // reset to command + sequence + } + + // copy this node's code color details into our buffer. + memcpy(&args->messageBuffer[args->bufferInUse], codeColorBuffer, codeAndColorLength); + args->bufferInUse += codeAndColorLength; + } + return true; // keep going +} + void Application::exportVoxels() { QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.hio2", tr("High Fidelity Voxel Files (*.hio2)")); @@ -1303,15 +1355,45 @@ void Application::importVoxels() { QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), "~", tr("High Fidelity Voxel Files (*.hio2)")); QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); + + // Read the file into a tree + VoxelTree importVoxels; + importVoxels.readFromFileV2(fileName); + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); printf("importVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName, _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + + // Recurse the Import Voxels 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 + unsigned char* calculatedOctCode = NULL; + SendVoxelsOperataionArgs args; + args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; + unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)]; + *sequenceAt = 0; + args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence + + // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the + // voxel size/position details. if (selectedNode) { - selectedNode->printDebugDetails("selected voxel"); + //selectedNode->printDebugDetails("selected voxel"); + args.newBaseOctCode = NULL; // selectedNode->getOctalCode(); + } else { + printf("importVoxels() no voxel at current location, calculate octCode... \n"); + args.newBaseOctCode = NULL; // = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + } + + importVoxels.recurseTreeWithOperation(sendVoxelsOperataion, &args); + + // If we have voxels left in the packet, then send the packet + if (args.bufferInUse > 1) { + AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1); } - // not yet supported!!! - _voxels.readFromFileV2(fileName,selectedNode); + if (calculatedOctCode) { + delete calculatedOctCode; + } + } void Application::copyVoxels() { @@ -1331,14 +1413,6 @@ void Application::copyVoxels() { } } -const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500; -struct SendVoxelsOperataionArgs { - unsigned char* newBaseOctCode; - unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE]; - int bufferInUse; - -}; - void Application::pasteVoxels() { unsigned char* calculatedOctCode = NULL; VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); @@ -1374,40 +1448,6 @@ void Application::pasteVoxels() { } } -bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { - SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData; - if (node->isColored()) { - const int SIZE_OF_COLOR_DATA = 3; - const int RED_INDEX = 0; - const int GREEN_INDEX = 1; - const int BLUE_INDEX = 2; - unsigned char* nodeOctalCode = node->getOctalCode(); - printOctalCode(nodeOctalCode); - unsigned char* rebasedCodeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); - printOctalCode(rebasedCodeColorBuffer); - int rebasedCodeLength = numberOfThreeBitSectionsInCode(rebasedCodeColorBuffer); - int bytesInRebasedCode = bytesRequiredForCodeLength(rebasedCodeLength); - int codeAndColorLength = bytesInRebasedCode + SIZE_OF_COLOR_DATA; - - // copy the colors over - rebasedCodeColorBuffer[bytesInRebasedCode + RED_INDEX ] = node->getColor()[RED_INDEX ]; - rebasedCodeColorBuffer[bytesInRebasedCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX]; - rebasedCodeColorBuffer[bytesInRebasedCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ]; - - // 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) { - AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1); - args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(int); // reset to command + sequence - } - - // copy this node's code color details into our buffer. - memcpy(&args->messageBuffer[args->bufferInUse], rebasedCodeColorBuffer, codeAndColorLength); - args->bufferInUse += codeAndColorLength; - } - return true; // keep going -} - - void Application::initMenu() { QMenuBar* menuBar = new QMenuBar(); _window->setMenuBar(menuBar); @@ -1479,6 +1519,9 @@ void Application::initMenu() { (_selectVoxelMode = voxelMenu->addAction( "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true); _voxelModeActions->addAction(_selectVoxelMode); + (_eyedropperMode = voxelMenu->addAction( + "Eyedropper Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_E))->setCheckable(true); + _voxelModeActions->addAction(_eyedropperMode); voxelMenu->addAction("Place New Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::Key_N); voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut); @@ -1486,6 +1529,7 @@ void Application::initMenu() { _voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C); + voxelMenu->addAction("Use Voxel Color", this, SLOT(useVoxelPaintColor()), Qt::CTRL | Qt::Key_U); QColor paintColor(128, 128, 128); _voxelPaintColor->setData(paintColor); _voxelPaintColor->setIcon(createSwatchIcon(paintColor)); @@ -2359,6 +2403,8 @@ void Application::maybeEditVoxelUnderCursor() { } } else if (_deleteVoxelMode->isChecked()) { deleteVoxelUnderCursor(); + } else if (_eyedropperMode->isChecked()) { + eyedropperVoxelUnderCursor(); } } @@ -2383,6 +2429,20 @@ void Application::deleteVoxelUnderCursor() { _justEditedVoxel = true; } +void Application::eyedropperVoxelUnderCursor() { + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (selectedNode && selectedNode->isColored()) { + QColor selectedColor(selectedNode->getColor()[RED_INDEX], + selectedNode->getColor()[GREEN_INDEX], + selectedNode->getColor()[BLUE_INDEX]); + + if (selectedColor.isValid()) { + _voxelPaintColor->setData(selectedColor); + _voxelPaintColor->setIcon(createSwatchIcon(selectedColor)); + } + } +} + void Application::goHome() { _myAvatar.setPosition(START_LOCATION); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 7761d9a84b..ee48307910 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -182,7 +182,7 @@ private: void shiftPaintingColor(); void maybeEditVoxelUnderCursor(); void deleteVoxelUnderCursor(); - + void eyedropperVoxelUnderCursor(); void goHome(); void resetSensors(); @@ -225,6 +225,7 @@ private: QAction* _deleteVoxelMode; // Whether delete voxel mode is enabled QAction* _colorVoxelMode; // Whether color voxel mode is enabled QAction* _selectVoxelMode; // Whether select voxel mode is enabled + QAction* _eyedropperMode; // Whether voxel color eyedropper mode is enabled QAction* _voxelPaintColor; // The color with which to paint voxels QAction* _destructiveAddVoxel; // when doing voxel editing do we want them to be destructive QAction* _frustumOn; // Whether or not to display the debug view frustum diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 156a310476..b18315402a 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -23,11 +23,18 @@ const int MAX_VOXELS_PER_SYSTEM = 200000; const int VERTICES_PER_VOXEL = 24; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; -const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; + +const int NUMBER_OF_COLORS = 3; // RGB! +const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes +const int RED_INDEX = 0; +const int GREEN_INDEX = 1; +const int BLUE_INDEX = 2; +const int COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * VERTICES_PER_VOXEL; typedef unsigned long int glBufferIndex; const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60; const double VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0; // once a second is fine + #endif From c4b3b568e7e551f5716642b29f7aaefa21f9b253 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 3 Jun 2013 13:13:52 -0700 Subject: [PATCH 08/19] make import and export properly rebase --- interface/src/Application.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ab335dce97..73a0190267 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1343,12 +1343,22 @@ void Application::exportVoxels() { QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + printf("exportVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName, _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + + if (selectedNode) { - selectedNode->printDebugDetails("selected voxel"); + //selectedNode->printDebugDetails("selected voxel"); + + VoxelTree exportTree; + + // then copy onto it + _voxels.copySubTreeIntoNewTree(selectedNode, &exportTree, true); + + exportTree.writeToFileV2(fileName); } - _voxels.writeToFileV2(fileName,selectedNode); + } void Application::importVoxels() { @@ -1377,10 +1387,10 @@ void Application::importVoxels() { // voxel size/position details. if (selectedNode) { //selectedNode->printDebugDetails("selected voxel"); - args.newBaseOctCode = NULL; // selectedNode->getOctalCode(); + args.newBaseOctCode = selectedNode->getOctalCode(); } else { printf("importVoxels() no voxel at current location, calculate octCode... \n"); - args.newBaseOctCode = NULL; // = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); } importVoxels.recurseTreeWithOperation(sendVoxelsOperataion, &args); @@ -1520,7 +1530,7 @@ void Application::initMenu() { "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true); _voxelModeActions->addAction(_selectVoxelMode); (_eyedropperMode = voxelMenu->addAction( - "Eyedropper Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_E))->setCheckable(true); + "Get Color Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_G))->setCheckable(true); _voxelModeActions->addAction(_eyedropperMode); voxelMenu->addAction("Place New Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::Key_N); @@ -1529,7 +1539,6 @@ void Application::initMenu() { _voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C); - voxelMenu->addAction("Use Voxel Color", this, SLOT(useVoxelPaintColor()), Qt::CTRL | Qt::Key_U); QColor paintColor(128, 128, 128); _voxelPaintColor->setData(paintColor); _voxelPaintColor->setIcon(createSwatchIcon(paintColor)); From ea965f22902c4e81105bf2f4a9b33de7f0c2103d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 3 Jun 2013 13:46:21 -0700 Subject: [PATCH 09/19] fixed issue with sendVoxelsOperataion, some other cleanup --- interface/src/Application.cpp | 26 ++++++++++---------------- libraries/voxels/src/VoxelTree.cpp | 9 --------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 73a0190267..ec51855c49 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1297,7 +1297,6 @@ bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData; if (node->isColored()) { unsigned char* nodeOctalCode = node->getOctalCode(); - printOctalCode(nodeOctalCode); unsigned char* codeColorBuffer = NULL; int codeLength = 0; @@ -1307,7 +1306,6 @@ bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { // If the newBase is NULL, then don't rebase if (args->newBaseOctCode) { codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); - printOctalCode(codeColorBuffer); codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer); bytesInCode = bytesRequiredForCodeLength(codeLength); codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; @@ -1327,7 +1325,7 @@ bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { // 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) { AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1); - args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(int); // reset to command + sequence + args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // reset } // copy this node's code color details into our buffer. @@ -1359,6 +1357,8 @@ void Application::exportVoxels() { exportTree.writeToFileV2(fileName); } + // restore the main window's active state + _window->activateWindow(); } void Application::importVoxels() { @@ -1394,9 +1394,9 @@ void Application::importVoxels() { } importVoxels.recurseTreeWithOperation(sendVoxelsOperataion, &args); - + // If we have voxels left in the packet, then send the packet - if (args.bufferInUse > 1) { + if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) { AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1); } @@ -1404,29 +1404,24 @@ void Application::importVoxels() { delete calculatedOctCode; } + // restore the main window's active state + _window->activateWindow(); } void Application::copyVoxels() { VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - printf("copyVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode) { - //selectedNode->printDebugDetails("selected voxel"); - // clear the clipboard first... _clipboardTree.eraseAllVoxels(); // then copy onto it _voxels.copySubTreeIntoNewTree(selectedNode, &_clipboardTree, true); - - // debug tree - //_clipboardTree.printTreeForDebugging(_clipboardTree.rootNode); } } void Application::pasteVoxels() { unsigned char* calculatedOctCode = NULL; VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - printf("pasteVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); // 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 @@ -1437,19 +1432,18 @@ void Application::pasteVoxels() { args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the - // voxel size/position details. + // voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a + // target octalCode for where the user is pointing. if (selectedNode) { - //selectedNode->printDebugDetails("selected voxel"); args.newBaseOctCode = selectedNode->getOctalCode(); } else { - printf("pasteVoxels() no voxel at current location, calculate octCode... \n"); args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); } _clipboardTree.recurseTreeWithOperation(sendVoxelsOperataion, &args); // If we have voxels left in the packet, then send the packet - if (args.bufferInUse > 1) { + if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) { AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1); } diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 704c15e4db..af6b435512 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1185,18 +1185,11 @@ bool VoxelTree::countVoxelsOperation(VoxelNode* node, void* extraData) { } void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) { - - printLog("copySubTreeIntoNewTree()...\n"); - VoxelNodeBag nodeBag; - // If we were given a specific node, start from there, otherwise start from root nodeBag.insert(startNode); - int chopLevels = 0; - if (rebaseToRoot) { chopLevels = numberOfThreeBitSectionsInCode(startNode->getOctalCode()); - printLog("copySubTreeIntoNewTree()...rebaseToRoot=true, chopLevels=%d\n", chopLevels); } static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static @@ -1215,8 +1208,6 @@ void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinat } void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) { - printLog("copyFromTreeIntoSubTree()...\n"); - VoxelNodeBag nodeBag; // If we were given a specific node, start from there, otherwise start from root nodeBag.insert(sourceTree->rootNode); From 0f2b73613091eb8f6b40684a8250d000d2812205 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 3 Jun 2013 13:50:42 -0700 Subject: [PATCH 10/19] cleanup --- interface/src/Application.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ec51855c49..9b1b97be19 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1341,19 +1341,9 @@ void Application::exportVoxels() { QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - - printf("exportVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName, - _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - - if (selectedNode) { - //selectedNode->printDebugDetails("selected voxel"); - VoxelTree exportTree; - - // then copy onto it _voxels.copySubTreeIntoNewTree(selectedNode, &exportTree, true); - exportTree.writeToFileV2(fileName); } @@ -1371,8 +1361,6 @@ void Application::importVoxels() { importVoxels.readFromFileV2(fileName); VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - printf("importVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName, - _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); // Recurse the Import Voxels 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 @@ -1386,10 +1374,8 @@ void Application::importVoxels() { // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the // voxel size/position details. if (selectedNode) { - //selectedNode->printDebugDetails("selected voxel"); args.newBaseOctCode = selectedNode->getOctalCode(); } else { - printf("importVoxels() no voxel at current location, calculate octCode... \n"); args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); } @@ -1744,17 +1730,6 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { glm::vec3 up = rotation * AVATAR_UP; glm::vec3 right = rotation * AVATAR_RIGHT; - /* - printf("position.x=%f, position.y=%f, position.z=%f\n", position.x, position.y, position.z); - printf("yaw=%f, pitch=%f, roll=%f\n", yaw,pitch,roll); - printf("direction.x=%f, direction.y=%f, direction.z=%f\n", direction.x, direction.y, direction.z); - printf("up.x=%f, up.y=%f, up.z=%f\n", up.x, up.y, up.z); - printf("right.x=%f, right.y=%f, right.z=%f\n", right.x, right.y, right.z); - printf("fov=%f\n", fov); - printf("nearClip=%f\n", nearClip); - printf("farClip=%f\n", farClip); - */ - // Set the viewFrustum up with the correct position and orientation of the camera viewFrustum.setPosition(position); viewFrustum.setOrientation(direction,up,right); @@ -2355,7 +2330,6 @@ void Application::maybeEditVoxelUnderCursor() { //_myAvatar.getPosition() voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw()); voxelInjector->setVolume (16 * pow (_mouseVoxel.s, 2) / .0000001); //255 is max, and also default value - // printf("mousevoxelscale is %f\n", _mouseVoxel.s); /* for (int i = 0; i < 22050; i++) { From cf3ff53e2c777de6e8821d4b5e8811005a3b1cef Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 3 Jun 2013 18:08:11 -0700 Subject: [PATCH 11/19] copy and paste working --- interface/src/Application.cpp | 2 +- libraries/shared/src/OctalCode.cpp | 33 ++++++++++++++++----------- libraries/shared/src/OctalCode.h | 8 +++++++ libraries/voxels/src/VoxelConstants.h | 7 +----- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b2bd7b22e6..8cc313b4bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2397,7 +2397,7 @@ void Application::deleteVoxelUnderCursor() { for (int i = 0; i < 5000; i++) { voxelInjector->addSample(10000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 500.0)))); //FM 3 resonant pulse - // voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter + //voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter } AudioInjectionManager::threadInjector(voxelInjector); diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index 150789bec8..d51f058459 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -170,22 +170,21 @@ OctalCodeComparison compareOctalCodes(unsigned char* codeA, unsigned char* codeB char getOctalCodeSectionValue(unsigned char* octalCode, int section) { - int startAtByte = 1 + (3 * section / 8); - char startIndexInByte = (3 * section) % 8; + int startAtByte = 1 + (BITS_IN_OCTAL * section / BITS_IN_BYTE); + char startIndexInByte = (BITS_IN_OCTAL * section) % BITS_IN_BYTE; unsigned char* startByte = octalCode + startAtByte; return sectionValue(startByte, startIndexInByte); } void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectionValue) { - unsigned char* byteAt = octalCode + 1 + (3 * section / 8); - char bitInByte = (3 * section) % 8; - char shiftBy = 8 - bitInByte - 3; + int byteForSection = (BITS_IN_OCTAL * section / BITS_IN_BYTE); + unsigned char* byteAt = octalCode + 1 + byteForSection; + char bitInByte = (BITS_IN_OCTAL * section) % BITS_IN_BYTE; + char shiftBy = BITS_IN_BYTE - bitInByte - BITS_IN_OCTAL; const unsigned char UNSHIFTED_MASK = 0x07; unsigned char shiftedMask; unsigned char shiftedValue; - - if (shiftBy >=0) { shiftedMask = UNSHIFTED_MASK << shiftBy; shiftedValue = sectionValue << shiftBy; @@ -193,15 +192,24 @@ void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectio shiftedMask = UNSHIFTED_MASK >> -shiftBy; shiftedValue = sectionValue >> -shiftBy; } - unsigned char oldValue = *byteAt & ~shiftedMask; unsigned char newValue = oldValue | shiftedValue; *byteAt = newValue; - if (bitInByte >= 6) { - shiftBy = bitInByte + 1; + + // If the requested section is partially in the byte, then we + // need to also set the portion of the section value in the next byte + // there's only two cases where this happens, if the bit in byte is + // 6, then it means that 1 extra bit lives in the next byte. If the + // bit in this byte is 7 then 2 extra bits live in the next byte. + const int FIRST_PARTIAL_BIT = 6; + if (bitInByte >= FIRST_PARTIAL_BIT) { + int bitsInFirstByte = BITS_IN_BYTE - bitInByte; + int bitsInSecondByte = BITS_IN_OCTAL - bitsInFirstByte; + shiftBy = BITS_IN_BYTE - bitsInSecondByte; + shiftedMask = UNSHIFTED_MASK << shiftBy; shiftedValue = sectionValue << shiftBy; - + oldValue = byteAt[1] & ~shiftedMask; newValue = oldValue | shiftedValue; byteAt[1] = newValue; @@ -228,8 +236,7 @@ unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* int oldCodeLength = numberOfThreeBitSectionsInCode(originalOctalCode); int newParentCodeLength = numberOfThreeBitSectionsInCode(newParentOctalCode); int newCodeLength = newParentCodeLength + oldCodeLength; - const int COLOR_SPACE = 3; - int bufferLength = newCodeLength + (includeColorSpace ? COLOR_SPACE : 0); + int bufferLength = newCodeLength + (includeColorSpace ? SIZE_OF_COLOR_DATA : 0); unsigned char* newCode = new unsigned char[bufferLength]; *newCode = newCodeLength; // set the length byte diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index bfed24a87c..761eac1953 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -11,6 +11,14 @@ #include +const int BITS_IN_BYTE = 8; +const int BITS_IN_OCTAL = 3; +const int NUMBER_OF_COLORS = 3; // RGB! +const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes +const int RED_INDEX = 0; +const int GREEN_INDEX = 1; +const int BLUE_INDEX = 2; + void printOctalCode(unsigned char * octalCode); int bytesRequiredForCodeLength(unsigned char threeBitCodes); bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode); diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index b18315402a..5bf1345d73 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -13,6 +13,7 @@ #define __hifi_VoxelConstants_h__ #include +#include const int TREE_SCALE = 128; @@ -23,12 +24,6 @@ const int MAX_VOXELS_PER_SYSTEM = 200000; const int VERTICES_PER_VOXEL = 24; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; - -const int NUMBER_OF_COLORS = 3; // RGB! -const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes -const int RED_INDEX = 0; -const int GREEN_INDEX = 1; -const int BLUE_INDEX = 2; const int COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * VERTICES_PER_VOXEL; typedef unsigned long int glBufferIndex; From 03f79f5cab8d566373e7be82d4b762e6f5fbb4d0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 3 Jun 2013 21:04:42 -0700 Subject: [PATCH 12/19] fixed delete voxel --- libraries/voxels/src/VoxelTree.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index af6b435512..5bf9844fc1 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -286,9 +286,9 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage, b } } - // If we're not a colored leaf, and we have no children, then delete ourselves - // This will collapse the empty tree above us. - if (collapseEmptyTrees && parentNode->getChildCount() == 0 && !parentNode->isColored()) { + // If we're in collpaseEmptryTrees mode, and we're the last child of this parent, then delete the parent. + // This will collapse the empty tree above us. + if (collapseEmptyTrees && parentNode->getChildCount() == 0) { // Can't delete the root this way. if (parentNode != rootNode) { deleteVoxelCodeFromTree(parentNode->getOctalCode(), stage, collapseEmptyTrees); From 435791f28c0d08fa144881f773e7a46a303fc9b3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Jun 2013 01:02:10 -0700 Subject: [PATCH 13/19] CR feedback --- interface/src/Application.cpp | 14 +++++++------- interface/src/Application.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 05bd0f3d5a..d8eed95ea7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1293,15 +1293,15 @@ void Application::chooseVoxelPaintColor() { } const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500; -struct SendVoxelsOperataionArgs { +struct SendVoxelsOperationArgs { unsigned char* newBaseOctCode; unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE]; int bufferInUse; }; -bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { - SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData; +bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) { + SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; if (node->isColored()) { unsigned char* nodeOctalCode = node->getOctalCode(); @@ -1372,7 +1372,7 @@ void Application::importVoxels() { // Recurse the Import Voxels 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 unsigned char* calculatedOctCode = NULL; - SendVoxelsOperataionArgs args; + SendVoxelsOperationArgs args; args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)]; *sequenceAt = 0; @@ -1386,7 +1386,7 @@ void Application::importVoxels() { args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); } - importVoxels.recurseTreeWithOperation(sendVoxelsOperataion, &args); + importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args); // If we have voxels left in the packet, then send the packet if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) { @@ -1418,7 +1418,7 @@ 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 - SendVoxelsOperataionArgs args; + SendVoxelsOperationArgs args; args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)]; *sequenceAt = 0; @@ -1433,7 +1433,7 @@ void Application::pasteVoxels() { args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); } - _clipboardTree.recurseTreeWithOperation(sendVoxelsOperataion, &args); + _clipboardTree.recurseTreeWithOperation(sendVoxelsOperation, &args); // If we have voxels left in the packet, then send the packet if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) { diff --git a/interface/src/Application.h b/interface/src/Application.h index ee48307910..edcc1d6b82 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -161,7 +161,7 @@ private slots: private: - static bool sendVoxelsOperataion(VoxelNode* node, void* extraData); + static bool sendVoxelsOperation(VoxelNode* node, void* extraData); void initMenu(); void updateFrustumRenderModeAction(); From 1f3de3e12b64621a4d125942a6b7b93d46ffc18f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Jun 2013 01:03:26 -0700 Subject: [PATCH 14/19] CR feedback --- libraries/voxels/src/VoxelTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 5bf9844fc1..de6bafef3d 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -286,7 +286,7 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage, b } } - // If we're in collpaseEmptryTrees mode, and we're the last child of this parent, then delete the parent. + // If we're in collapseEmptyTrees mode, and we're the last child of this parent, then delete the parent. // This will collapse the empty tree above us. if (collapseEmptyTrees && parentNode->getChildCount() == 0) { // Can't delete the root this way. From 0a9b3bf5ce87e1045d4aaf21f323330db6d44159 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Jun 2013 01:07:18 -0700 Subject: [PATCH 15/19] changed file name and exention to Sparse Voxel Octree and svo --- interface/src/Application.cpp | 7 ++++--- voxel-edit/src/main.cpp | 2 +- voxel-server/src/main.cpp | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d8eed95ea7..00772e7fec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1343,8 +1343,8 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) { } void Application::exportVoxels() { - QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.hio2", - tr("High Fidelity Voxel Files (*.hio2)")); + QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.svo", + tr("Sparse Voxel Octree Files (*.svo)")); QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); @@ -1359,7 +1359,8 @@ void Application::exportVoxels() { } void Application::importVoxels() { - QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), "~", tr("High Fidelity Voxel Files (*.hio2)")); + QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), "~", + tr("Sparse Voxel Octree Files (*.svo)")); QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); diff --git a/voxel-edit/src/main.cpp b/voxel-edit/src/main.cpp index 222bf3f15b..d2c88812ca 100644 --- a/voxel-edit/src/main.cpp +++ b/voxel-edit/src/main.cpp @@ -92,7 +92,7 @@ int main(int argc, const char * argv[]) unsigned long nodeCount = myTree.getVoxelCount(); printf("Nodes after adding scenes: %ld nodes\n", nodeCount); - myTree.writeToFileV2("voxels.hio2"); + myTree.writeToFileV2("voxels.svo"); } return 0; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 70f7ab8752..4d06f60f0c 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -30,8 +30,8 @@ #include #endif -const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.hio2"; -const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.hio2"; +const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; +const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; const double VOXEL_PERSIST_INTERVAL = 1000.0 * 30; // every 30 seconds const int VOXEL_LISTEN_PORT = 40106; From 37cc436b2b9c4a082f6e252f38a4d91f70e41a11 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Jun 2013 01:08:18 -0700 Subject: [PATCH 16/19] CR feedback --- libraries/voxels/src/VoxelTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index de6bafef3d..96c9320edd 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1223,7 +1223,7 @@ void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destin MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); // ask destination tree to read the bitstream - readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS,destinationNode); + readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS, destinationNode); } } From 4f3872c18fb696863cfbe20c71a4f84e2c0a49ad Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Jun 2013 01:13:58 -0700 Subject: [PATCH 17/19] CR feedback --- interface/src/Application.cpp | 4 ++-- interface/src/VoxelSystem.cpp | 8 ++++---- interface/src/VoxelSystem.h | 4 ++-- libraries/voxels/src/VoxelTree.cpp | 4 ++-- libraries/voxels/src/VoxelTree.h | 4 ++-- voxel-edit/src/main.cpp | 2 +- voxel-server/src/main.cpp | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 00772e7fec..4610d889ed 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1351,7 +1351,7 @@ void Application::exportVoxels() { if (selectedNode) { VoxelTree exportTree; _voxels.copySubTreeIntoNewTree(selectedNode, &exportTree, true); - exportTree.writeToFileV2(fileName); + exportTree.writeToSVOFile(fileName); } // restore the main window's active state @@ -1366,7 +1366,7 @@ void Application::importVoxels() { // Read the file into a tree VoxelTree importVoxels; - importVoxels.readFromFileV2(fileName); + importVoxels.readFromSVOFile(fileName); VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index b99519e845..11c274119b 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -70,12 +70,12 @@ void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) setupNewVoxelsForDrawing(); } -void VoxelSystem::writeToFileV2(const char* filename, VoxelNode* node) const { - _tree->writeToFileV2(filename, node); +void VoxelSystem::writeToSVOFile(const char* filename, VoxelNode* node) const { + _tree->writeToSVOFile(filename, node); } -bool VoxelSystem::readFromFileV2(const char* filename, VoxelNode* node) { - bool result = _tree->readFromFileV2(filename, node); +bool VoxelSystem::readFromSVOFile(const char* filename) { + bool result = _tree->readFromSVOFile(filename); if (result) { setupNewVoxelsForDrawing(); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index c15ba53ba0..ee63801f92 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -44,8 +44,8 @@ public: void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; }; void setCamera(Camera* newCamera) { _camera = newCamera; }; void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); - void writeToFileV2(const char* filename, VoxelNode* node) const; - bool readFromFileV2(const char* filename, VoxelNode* node); + void writeToSVOFile(const char* filename, VoxelNode* node) const; + bool readFromSVOFile(const char* filename); long int getVoxelsCreated(); long int getVoxelsColored(); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 96c9320edd..49d79141de 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1123,7 +1123,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco return bytesAtThisLevel; } -bool VoxelTree::readFromFileV2(const char* fileName, VoxelNode* node) { +bool VoxelTree::readFromSVOFile(const char* fileName) { std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate); if(file.is_open()) { printLog("loading file %s...\n", fileName); @@ -1144,7 +1144,7 @@ bool VoxelTree::readFromFileV2(const char* fileName, VoxelNode* node) { return false; } -void VoxelTree::writeToFileV2(const char* fileName, VoxelNode* node) const { +void VoxelTree::writeToSVOFile(const char* fileName, VoxelNode* node) const { std::ofstream file(fileName, std::ios::out|std::ios::binary); diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index a2302f6cc7..b63e6eb738 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -92,8 +92,8 @@ public: void loadVoxelsFile(const char* fileName, bool wantColorRandomizer); // these will read/write files that match the wireformat, excluding the 'V' leading - void writeToFileV2(const char* filename, VoxelNode* node = NULL) const; - bool readFromFileV2(const char* filename, VoxelNode* node = NULL); + void writeToSVOFile(const char* filename, VoxelNode* node = NULL) const; + bool readFromSVOFile(const char* filename); unsigned long getVoxelCount(); diff --git a/voxel-edit/src/main.cpp b/voxel-edit/src/main.cpp index d2c88812ca..9571e4adf5 100644 --- a/voxel-edit/src/main.cpp +++ b/voxel-edit/src/main.cpp @@ -92,7 +92,7 @@ int main(int argc, const char * argv[]) unsigned long nodeCount = myTree.getVoxelCount(); printf("Nodes after adding scenes: %ld nodes\n", nodeCount); - myTree.writeToFileV2("voxels.svo"); + myTree.writeToSVOFile("voxels.svo"); } return 0; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 4d06f60f0c..9bf4a1dcc4 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -399,10 +399,10 @@ void persistVoxelsWhenDirty() { { PerformanceWarning warn(::shouldShowAnimationDebug, - "persistVoxelsWhenDirty() - writeToFileV2()", ::shouldShowAnimationDebug); + "persistVoxelsWhenDirty() - writeToSVOFile()", ::shouldShowAnimationDebug); printf("saving voxels to file...\n"); - randomTree.writeToFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + randomTree.writeToSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); randomTree.clearDirtyBit(); // tree is clean after saving printf("DONE saving voxels to file...\n"); } @@ -505,7 +505,7 @@ int main(int argc, const char * argv[]) { bool persistantFileRead = false; if (::wantVoxelPersist) { printf("loading voxels from file...\n"); - persistantFileRead = ::randomTree.readFromFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + persistantFileRead = ::randomTree.readFromSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); ::randomTree.clearDirtyBit(); // the tree is clean since we just loaded it printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); unsigned long nodeCount = ::randomTree.getVoxelCount(); @@ -517,7 +517,7 @@ int main(int argc, const char * argv[]) { const char* INPUT_FILE = "-i"; const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); if (voxelsFilename) { - randomTree.readFromFileV2(voxelsFilename); + randomTree.readFromSVOFile(voxelsFilename); } // Check to see if the user passed in a command line option for setting packet send rate From 743e1a433c00e80c388f3d61d34967d53e6ce5d4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Jun 2013 01:24:35 -0700 Subject: [PATCH 18/19] make import/export default to desktop --- interface/src/Application.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4610d889ed..56f1604e97 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1343,8 +1344,11 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) { } void Application::exportVoxels() { - QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.svo", - tr("Sparse Voxel Octree Files (*.svo)")); + QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); + QString suggestedName = desktopLocation.append("/voxels.svo"); + + QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), suggestedName, + tr("Sparse Voxel Octree Files (*.svo)")); QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); @@ -1359,7 +1363,8 @@ void Application::exportVoxels() { } void Application::importVoxels() { - QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), "~", + QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); + QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation, tr("Sparse Voxel Octree Files (*.svo)")); QByteArray fileNameAscii = fileNameString.toAscii(); const char* fileName = fileNameAscii.data(); From 626874f9ecbf210722b8211c971fc41497e27f24 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Jun 2013 08:47:57 -0700 Subject: [PATCH 19/19] add delete key support while in select mode --- interface/src/Application.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 56f1604e97..26d7f92533 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -617,6 +617,12 @@ void Application::keyPressEvent(QKeyEvent* event) { } resizeGL(_glWidget->width(), _glWidget->height()); break; + case Qt::Key_Backspace: + case Qt::Key_Delete: + if (_selectVoxelMode->isChecked()) { + deleteVoxelUnderCursor(); + } + break; default: event->ignore();