From 868ef8bec67922f4488be9f7341e29d762aa5778 Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Thu, 5 Sep 2013 17:42:25 -0700 Subject: [PATCH] Add VoxelNudgeMode and preliminary UI grid for nudging. --- interface/src/Application.cpp | 80 ++++++++++++------------------ interface/src/Application.h | 4 +- interface/src/Menu.cpp | 3 ++ interface/src/Menu.h | 1 + interface/src/Util.cpp | 26 ++++++++++ interface/src/Util.h | 2 + libraries/voxels/src/VoxelTree.cpp | 55 ++++++++++---------- libraries/voxels/src/VoxelTree.h | 2 +- 8 files changed, 92 insertions(+), 81 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2d963f939d..9f8453449c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -130,8 +130,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _bytesPerSecond(0), _bytesCount(0), _swatch(NULL), - _pasteMode(false), - _nudgeCount(0) + _pasteMode(false) { _applicationStartupTime = startup_time; _window->setWindowTitle("Interface"); @@ -689,6 +688,9 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_O: Menu::getInstance()->triggerOption(MenuOption::VoxelSelectMode); break; + case Qt::Key_N: + Menu::getInstance()->triggerOption(MenuOption::VoxelNudgeMode); + break; case Qt::Key_Slash: Menu::getInstance()->triggerOption(MenuOption::Stats); break; @@ -830,6 +832,9 @@ void Application::mousePressEvent(QMouseEvent* event) { } if (MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { + _nudgeVoxel = _hoverVoxel; + } _hoverVoxelOriginalColor[0] = _hoverVoxel.red; _hoverVoxelOriginalColor[1] = _hoverVoxel.green; _hoverVoxelOriginalColor[2] = _hoverVoxel.blue; @@ -1274,48 +1279,22 @@ void Application::pasteVoxels() { } void Application::nudgeVoxels() { - VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - if (selectedNode) { - qDebug("UnNudged xyz: %f, %f, %f\n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); - // // clear the clipboard first... - // _clipboard.killLocalVoxels(); + if (selectedNode) { + // glPushMatrix(); + // glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); + // renderNudgeGrid(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + // glPopMatrix(); + qDebug("UnNudged xyz: %f, %f, %f\n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); - // nudge the node - glm::vec3 nudgeVec(0.5 * _mouseVoxel.s, 0.5 * _mouseVoxel.s, 0.5 * _mouseVoxel.s); - // glm::vec3 nudgeVec(_mouseVoxel.s, _mouseVoxel.s, _mouseVoxel.s); - // _voxelEditSender.sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, _mouseVoxel); - _voxels.getVoxelTree()->nudgeSubTree(selectedNode, nudgeVec, _voxelEditSender); - - // if (!selectedNode) { - // qDebug("new node is null\n"); - // } else { - // // get octal code of this node - // unsigned char* octalCode = selectedNode->getOctalCode(); - - // // get voxel position/size - // VoxelPositionSize nudgedDetails; - // voxelDetailsForCode(octalCode, nudgedDetails); - // qDebug("Nudged xyz: %f, %f, %f\n", nudgedDetails.x, nudgedDetails.y, nudgedDetails.z); - // } - - // // then copy onto it - // _voxels.copySubTreeIntoNewTree(selectedNode, &_clipboard, true); - // // deleteVoxelUnderCursor(); - - // // Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to - // // the server as an set voxel message, this will also rebase the voxels to the new location - // SendVoxelsOperationArgs args; - - // // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the - // // 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. - // args.newBaseOctCode = selectedNode->getOctalCode(); - - // _clipboard.recurseTreeWithOperation(sendVoxelsOperation, &args); - // _voxelEditSender.flushQueue(); - } else { - qDebug("selectedNode is NULL\n"); + // nudge the node + // glm::vec3 nudgeVec(_mouseVoxel.s, _mouseVoxel.s, _mouseVoxel.s); + // glm::vec3 nudgeVec(0.5 * _mouseVoxel.s, 0.5 * _mouseVoxel.s, 0.5 * _mouseVoxel.s); + glm::vec3 nudgeVec(0.25 * _mouseVoxel.s, 0.25 * _mouseVoxel.s, 0.25 * _mouseVoxel.s); + _voxels.getVoxelTree()->nudgeSubTree(selectedNode, nudgeVec, _voxelEditSender); + } } } @@ -1404,6 +1383,7 @@ void Application::init() { _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelColorMode), 0, 2); _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelGetColorMode), 0, 3); _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelSelectMode), 0, 4); + _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelNudgeMode), 0, 5); _pieMenu.init("./resources/images/hifi-interface-tools-v2-pie.svg", _glWidget->width(), @@ -1590,11 +1570,6 @@ void Application::update(float deltaTime) { hoveredNode->setColor(_hoverVoxelOriginalColor); _isHoverVoxelSounding = false; } - // if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode)) { - // nudgeVoxels(); - // _nudgeCount++; - // qDebug("nudgeCount = %d\n", _nudgeCount); - // } } else { // Voxel is not found, clear all _isHoverVoxelSounding = false; @@ -1689,6 +1664,8 @@ void Application::update(float deltaTime) { // yellow indicates selection _mouseVoxel.red = _mouseVoxel.green = 255; _mouseVoxel.blue = 0; + } else if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { + _mouseVoxel.red = _mouseVoxel.green = _mouseVoxel.blue = 255; } else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked() QColor paintColor = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor)->data().value(); _mouseVoxel.red = paintColor.red(); @@ -2221,7 +2198,14 @@ void Application::displaySide(Camera& whichCamera) { glDisable(GL_LIGHTING); glPushMatrix(); glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); - renderMouseVoxelGrid(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { + VoxelNode* selectedNode = _voxels.getVoxelAt(_nudgeVoxel.x, _nudgeVoxel.y, _nudgeVoxel.z, _nudgeVoxel.s); + if (selectedNode) { + renderNudgeGrid(_nudgeVoxel.x, _nudgeVoxel.y, _nudgeVoxel.z, _nudgeVoxel.s); + } + } else { + renderMouseVoxelGrid(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + } if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode)) { // use a contrasting color so that we can see what we're doing glColor3ub(_mouseVoxel.red + 128, _mouseVoxel.green + 128, _mouseVoxel.blue + 128); diff --git a/interface/src/Application.h b/interface/src/Application.h index f1c1d53a66..aca11301b2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -295,6 +295,8 @@ private: glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit bool _justEditedVoxel; // set when we've just added/deleted/colored a voxel + VoxelDetail _nudgeVoxel; // details of the voxel to be nudged + bool _isLookingAtOtherAvatar; glm::vec3 _lookatOtherPosition; float _lookatIndicatorScale; @@ -353,8 +355,6 @@ private: NodeToJurisdictionMap _voxelServerJurisdictions; std::vector _voxelFades; - - int _nudgeCount; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 937ef5b74c..3cfc804a89 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -206,6 +206,9 @@ Menu::Menu() : QAction* colorVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelColorMode, Qt::Key_B); _voxelModeActionsGroup->addAction(colorVoxelMode); + + QAction* nudgeVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelNudgeMode, Qt::Key_N); + _voxelModeActionsGroup->addAction(nudgeVoxelMode); QAction* selectVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelSelectMode, Qt::Key_O); _voxelModeActionsGroup->addAction(selectVoxelMode); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6934f09d8f..57840604b5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -195,6 +195,7 @@ namespace MenuOption { const QString VoxelGetColorMode = "Get Color Mode"; const QString VoxelMode = "Cycle Voxel Mode"; const QString VoxelPaintColor = "Voxel Paint Color"; + const QString VoxelNudgeMode = "Nudge Voxel Mode"; const QString VoxelSelectMode = "Select Voxel Mode"; const QString VoxelStats = "Voxel Stats"; const QString VoxelTextures = "Voxel Textures"; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 743957128c..6de1bee2c7 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -414,6 +414,32 @@ void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, co glEnd(); } +void renderNudgeGrid(const float& mouseVoxelX, const float& mouseVoxelY, const float& mouseVoxelZ, const float& mouseVoxelS) { + glm::vec3 origin = glm::vec3(mouseVoxelX, mouseVoxelY, mouseVoxelZ); + + glLineWidth(1.0); + + const int GRID_DIMENSIONS = 4; + glBegin(GL_LINES); + + for (int i = 0; i <= GRID_DIMENSIONS; i++) { + for (int j = -GRID_DIMENSIONS / 2; j <= GRID_DIMENSIONS / 2; j++) { + glm::vec3 xColor(0.0, 0.6, 0.0); + glColor3fv(&xColor.x); + + glVertex3f(origin.x + GRID_DIMENSIONS * mouseVoxelS, i * mouseVoxelS, origin.z + j * mouseVoxelS); + glVertex3f(origin.x - GRID_DIMENSIONS * mouseVoxelS, i * mouseVoxelS, origin.z + j * mouseVoxelS); + + glm::vec3 zColor(0.0, 0.0, 0.6); + glColor3fv(&zColor.x); + + glVertex3f(origin.x + j * mouseVoxelS, i * mouseVoxelS, origin.z + GRID_DIMENSIONS * mouseVoxelS); + glVertex3f(origin.x + j * mouseVoxelS, i * mouseVoxelS, origin.z - GRID_DIMENSIONS * mouseVoxelS); + } + } + glEnd(); +} + void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness) { glColor4f(0.0f, 0.0f, 0.0f, darkness); diff --git a/interface/src/Util.h b/interface/src/Util.h index c1bb2949fa..dd41b2bab7 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -61,6 +61,8 @@ void renderGroundPlaneGrid(float size, float impact); void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, const float& mouseVoxelZ, const float& mouseVoxelS); +void renderNudgeGrid(const float& mouseVoxelX, const float& mouseVoxelY, const float& mouseVoxelZ, const float& mouseVoxelS); + void renderCollisionOverlay(int width, int height, float magnitude); void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index bb20dd1d4a..6a8ba7b28d 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1922,6 +1922,7 @@ const nodeColor blue = {0, 0, 255, 0}; class NodeChunkArgs { public: VoxelTree* thisVoxelTree; + float ancestorSize; float newSize; glm::vec3 nudgeVec; VoxelEditPacketSender* voxelEditSenderPtr; @@ -1953,31 +1954,21 @@ bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) { return false; } else { // break the current leaf into smaller chunks - args->thisVoxelTree->chunkifyLeaf(node, extraData); + args->thisVoxelTree->chunkifyLeaf(node); } } return true; } -void VoxelTree::chunkifyLeaf(VoxelNode* node, void* extraData) { +void VoxelTree::chunkifyLeaf(VoxelNode* node) { // because this function will continue being called recursively // we only need to worry about breaking this specific leaf down if (!node->isColored()) { return; } - NodeChunkArgs* args = (NodeChunkArgs*)extraData; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { node->addChildAtIndex(i); - if (args->colorIndex == 0) { - node->getChildAtIndex(i)->setColor(red); - } else if (args->colorIndex == 1) { - node->getChildAtIndex(i)->setColor(green); - } else if (args->colorIndex == 2) { - node->getChildAtIndex(i)->setColor(blue); - } - args->colorIndex++; - args->colorIndex = args->colorIndex % 3; - // node->getChildAtIndex(i)->setColor(node->getColor()); + node->getChildAtIndex(i)->setColor(node->getColor()); } } @@ -1992,39 +1983,35 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { // get voxel position/size VoxelPositionSize unNudgedDetails; voxelDetailsForCode(octalCode, unNudgedDetails); + + qDebug("UnNudged xyz: %f, %f, %f\n", unNudgedDetails.x, unNudgedDetails.y, unNudgedDetails.z); + VoxelDetail voxelDetails; voxelDetails.x = unNudgedDetails.x; voxelDetails.y = unNudgedDetails.y; voxelDetails.z = unNudgedDetails.z; voxelDetails.s = unNudgedDetails.s; voxelDetails.red = node->getColor()[0]; - qDebug("rgb: %u, %u, %u\n", node->getColor()[0], node->getColor()[1], node->getColor()[2]); voxelDetails.green = node->getColor()[1]; voxelDetails.blue = node->getColor()[2]; - - qDebug("UnNudged xyz: %f, %f, %f\n", unNudgedDetails.x, unNudgedDetails.y, unNudgedDetails.z); + glm::vec3 nudge = args->nudgeVec; // delete the old node - // creating a voxel is inherently destructive - // args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); - // deleteVoxelAt(unNudgedDetails.x, unNudgedDetails.y, unNudgedDetails.z, unNudgedDetails.s); - // qDebug("unNudged voxel deleted!\n"); + if (nudge.x >= args->ancestorSize && nudge.y >= args->ancestorSize && nudge.z >= args->ancestorSize) { + args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); + qDebug("unNudged voxel deleted!\n"); + } - // create a new voxel in its stead - glm::vec3 nudge = args->nudgeVec; + // nudge the old node qDebug("nudged by %f, %f, %f\n", nudge.x, nudge.y, nudge.z); - // createVoxel(unNudgedDetails.x + nudge.x, unNudgedDetails.y + nudge.y, unNudgedDetails.z + nudge.z, unNudgedDetails.s, - // node->getColor()[0], node->getColor()[1], node->getColor()[2], true); + voxelDetails.x = unNudgedDetails.x + nudge.x; voxelDetails.y = unNudgedDetails.y + nudge.y; voxelDetails.z = unNudgedDetails.z + nudge.z; - qDebug("Nudged xyz: %f, %f, %f\n", voxelDetails.x, voxelDetails.y, voxelDetails.z); - args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_SET_VOXEL, voxelDetails); - // unsigned char* newOctalCode = pointToVoxel(unNudgedDetails.x + nudge.x, unNudgedDetails.y + nudge.y, unNudgedDetails.z + nudge.z, - // unNudgedDetails.s, node->getColor()[0], node->getColor()[1], node->getColor()[2]); - // // node = new VoxelNode(newOctalCode); - // node = NULL; + // create a new voxel in its stead + args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_SET_VOXEL, voxelDetails); + qDebug("Nudged xyz: %f, %f, %f\n", voxelDetails.x, voxelDetails.y, voxelDetails.z); qDebug("nudged node created!\n"); } @@ -2033,8 +2020,16 @@ void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmoun float minNudgeAmount = fmin(nudgeAmount.x, nudgeAmount.y); minNudgeAmount = fmin(minNudgeAmount, nudgeAmount.z); + // get octal code of this node + unsigned char* octalCode = nodeToNudge->getOctalCode(); + + // get voxel position/size + VoxelPositionSize ancestorDetails; + voxelDetailsForCode(octalCode, ancestorDetails); + NodeChunkArgs args; args.thisVoxelTree = this; + args.ancestorSize = ancestorDetails.s; args.newSize = minNudgeAmount; args.nudgeVec = nudgeAmount; args.voxelEditSenderPtr = &voxelEditSender; diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index b684c96923..281cef63e8 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -261,7 +261,7 @@ private: // helper functions for nudgeSubTree static bool nudgeCheck(VoxelNode* node, void* extraData); void nudgeLeaf(VoxelNode* node, void* extraData); - void chunkifyLeaf(VoxelNode* node, void* extraData); + void chunkifyLeaf(VoxelNode* node); }; float boundaryDistanceForRenderLevel(unsigned int renderLevel);