From ac878c9c63c20f9ffa479967411dcf85483c9ccb Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Mon, 9 Sep 2013 16:53:31 -0700 Subject: [PATCH] UI for nudge completed! --- interface/src/Application.cpp | 91 +++++++++++++----------------- interface/src/Application.h | 1 + interface/src/Util.cpp | 39 +++++++++++-- interface/src/Util.h | 4 +- libraries/voxels/src/VoxelTree.cpp | 51 ++++++++++------- 5 files changed, 105 insertions(+), 81 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 857951a670..9653226b0e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -128,7 +128,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _bytesPerSecond(0), _bytesCount(0), _swatch(NULL), - _pasteMode(false) + _pasteMode(false), + _finishedNudge(true) { _applicationStartupTime = startup_time; _window->setWindowTitle("Interface"); @@ -844,10 +845,15 @@ void Application::mousePressEvent(QMouseEvent* event) { pasteVoxels(); } - if (MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { - if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { - _nudgeVoxel = _hoverVoxel; + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { + VoxelNode* clickedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + if (clickedNode) { + _nudgeVoxel = _mouseVoxel; + _finishedNudge = false; } + } + + if (MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { _hoverVoxelOriginalColor[0] = _hoverVoxel.red; _hoverVoxelOriginalColor[1] = _hoverVoxel.green; _hoverVoxelOriginalColor[2] = _hoverVoxel.blue; @@ -1287,52 +1293,16 @@ void Application::pasteVoxels() { void Application::nudgeVoxels() { if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { - cutVoxels(); - unsigned char* calculatedOctCode = NULL; - VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + // calculate nudgeVec + glm::vec3 nudgeVec(_mouseVoxel.x - _nudgeVoxel.x, _mouseVoxel.y - _nudgeVoxel.y, _mouseVoxel.z - _nudgeVoxel.z); - // 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; + VoxelNode* nodeToNudge = _voxels.getVoxelAt(_nudgeVoxel.x, _nudgeVoxel.y, _nudgeVoxel.z, _nudgeVoxel.s); - // 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. - if (selectedNode) { - args.newBaseOctCode = selectedNode->getOctalCode(); - } else { - args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - } - - _sharedVoxelSystem.getTree()->recurseTreeWithOperation(sendVoxelsOperation, &args); - glm::vec3 nudgeVec(0.25 * _mouseVoxel.s, 0.25 * _mouseVoxel.s, 0.25 * _mouseVoxel.s); - _voxels.getVoxelTree()->nudgeSubTree(selectedNode, nudgeVec, _voxelEditSender); - - if (_sharedVoxelSystem.getTree() != &_clipboard) { - _sharedVoxelSystem.killLocalVoxels(); - _sharedVoxelSystem.changeTree(&_clipboard); - } - - _voxelEditSender.flushQueue(); - - if (calculatedOctCode) { - delete[] calculatedOctCode; + if (nodeToNudge) { + _voxels.getVoxelTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender); + _finishedNudge = true; } } - - - - // 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); - - // // 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); - // } } void Application::setListenModeNormal() { @@ -1612,7 +1582,7 @@ void Application::update(float deltaTime) { lookAtSpot = lookAtRayOrigin + lookAtRayDirection * FAR_AWAY_STARE; _myAvatar.getHead().setLookAtPosition(lookAtSpot); } - + // Find the voxel we are hovering over, and respond if clicked float distance; BoxFace face; @@ -1702,11 +1672,13 @@ void Application::update(float deltaTime) { _mouseVoxel.z += faceVector.z * _mouseVoxel.s; } } + _nudgeVoxel.s = _mouseVoxel.s; } else { _mouseVoxel.s = 0.0f; } } else if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) - || Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode)) { + || Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode) + || Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { // place the voxel a fixed distance away float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE; glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f); @@ -2308,13 +2280,22 @@ void Application::displaySide(Camera& whichCamera) { glPushMatrix(); glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); 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); - // } + if (!_finishedNudge) { + renderNudgeGuide(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _nudgeVoxel.s); + renderNudgeGrid(_nudgeVoxel.x, _nudgeVoxel.y, _nudgeVoxel.z, _nudgeVoxel.s, _mouseVoxel.s); + glPushMatrix(); + glTranslatef(_nudgeVoxel.x + _nudgeVoxel.s * 0.5f, + _nudgeVoxel.y + _nudgeVoxel.s * 0.5f, + _nudgeVoxel.z + _nudgeVoxel.s * 0.5f); + glColor3ub(255, 255, 255); + glLineWidth(4.0f); + glutWireCube(_nudgeVoxel.s); + glPopMatrix(); + } } 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); @@ -2325,7 +2306,11 @@ void Application::displaySide(Camera& whichCamera) { _mouseVoxel.y + _mouseVoxel.s*0.5f, _mouseVoxel.z + _mouseVoxel.s*0.5f); glLineWidth(4.0f); - glutWireCube(_mouseVoxel.s); + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { + glutWireCube(_nudgeVoxel.s); + } else { + glutWireCube(_mouseVoxel.s); + } glLineWidth(1.0f); glPopMatrix(); glEnable(GL_LIGHTING); diff --git a/interface/src/Application.h b/interface/src/Application.h index 2fa97aebdc..5965293c1a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -357,6 +357,7 @@ private: Swatch _swatch; bool _pasteMode; + bool _finishedNudge; PieMenu _pieMenu; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 19c49c2418..c259379e15 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -414,30 +414,57 @@ void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, co glEnd(); } -void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS) { +void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS, const float& voxelPrecision) { glm::vec3 origin = glm::vec3(voxelX, voxelY, voxelZ); glLineWidth(1.0); const int GRID_DIMENSIONS = 4; + const int GRID_SCALER = voxelS / voxelPrecision; + const int GRID_SEGMENTS = GRID_DIMENSIONS * GRID_SCALER; glBegin(GL_LINES); - for (int xz = - (GRID_DIMENSIONS / 2); xz <= GRID_DIMENSIONS / 2 + 1; xz++) { + for (int xz = - (GRID_SEGMENTS / 2); xz <= GRID_SEGMENTS / 2 + GRID_SCALER; xz++) { glm::vec3 xColor(0.0, 0.6, 0.0); glColor3fv(&xColor.x); - glVertex3f(origin.x + GRID_DIMENSIONS * voxelS, 0, origin.z + xz * voxelS); - glVertex3f(origin.x - (GRID_DIMENSIONS - 1) * voxelS, 0, origin.z + xz * voxelS); + glVertex3f(origin.x + GRID_DIMENSIONS * voxelS, 0, origin.z + xz * voxelPrecision); + glVertex3f(origin.x - (GRID_DIMENSIONS - 1) * voxelS, 0, origin.z + xz * voxelPrecision); glm::vec3 zColor(0.0, 0.0, 0.6); glColor3fv(&zColor.x); - glVertex3f(origin.x + xz * voxelS, 0, origin.z + GRID_DIMENSIONS * voxelS); - glVertex3f(origin.x + xz * voxelS, 0, origin.z - (GRID_DIMENSIONS - 1) * voxelS); + glVertex3f(origin.x + xz * voxelPrecision, 0, origin.z + GRID_DIMENSIONS * voxelS); + glVertex3f(origin.x + xz * voxelPrecision, 0, origin.z - (GRID_DIMENSIONS - 1) * voxelS); } glEnd(); } +void renderNudgeGuide(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS) { + glm::vec3 origin = glm::vec3(voxelX, voxelY, voxelZ); + + glLineWidth(3.0); + + glBegin(GL_LINES); + + glm::vec3 guideColor(1.0, 1.0, 1.0); + glColor3fv(&guideColor.x); + + glVertex3f(origin.x + voxelS, 0, origin.z); + glVertex3f(origin.x, 0, origin.z); + + glVertex3f(origin.x, 0, origin.z); + glVertex3f(origin.x, 0, origin.z + voxelS); + + glVertex3f(origin.x + voxelS, 0, origin.z); + glVertex3f(origin.x + voxelS, 0, origin.z + voxelS); + + glVertex3f(origin.x, 0, origin.z + voxelS); + glVertex3f(origin.x + voxelS, 0, origin.z + voxelS); + + 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 dc61eaca97..9401ca2e9a 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -61,7 +61,9 @@ void renderGroundPlaneGrid(float size, float impact); void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, const float& mouseVoxelZ, const float& mouseVoxelS); -void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS); +void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS, const float& voxelPrecision); + +void renderNudgeGuide(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS); void renderCollisionOverlay(int width, int height, float magnitude); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 0e9409a795..cec46998e7 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1858,23 +1858,35 @@ void VoxelTree::cancelImport() { _stopImport = true; } -typedef unsigned char nodeColor[4]; - -const nodeColor red = {255, 0, 0, 0}; -const nodeColor green = {0, 255, 0, 0}; -const nodeColor blue = {0, 0, 255, 0}; - class NodeChunkArgs { public: VoxelTree* thisVoxelTree; float ancestorSize; - float newSize; glm::vec3 nudgeVec; VoxelEditPacketSender* voxelEditSenderPtr; int colorIndex; }; +float findNewLeafSize(const glm::vec3& nudgeAmount, float leafSize) { + // we want the smallest non-zero and non-negative new leafSize + float newLeafSizeX = fabs(fmod(nudgeAmount.x, leafSize)); + float newLeafSizeY = fabs(fmod(nudgeAmount.y, leafSize)); + float newLeafSizeZ = fabs(fmod(nudgeAmount.z, leafSize)); + + float newLeafSize = leafSize; + if (newLeafSizeX) { + newLeafSize = fmin(newLeafSize, newLeafSizeX); + } + if (newLeafSizeY) { + newLeafSize = fmin(newLeafSize, newLeafSizeY); + } + if (newLeafSizeZ) { + newLeafSize = fmin(newLeafSize, newLeafSizeZ); + } + return newLeafSize; +} + bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) { if (node->isLeaf()) { // we have reached the deepest level of nodes/voxels @@ -1893,8 +1905,12 @@ bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) { VoxelPositionSize unNudgedDetails; voxelDetailsForCode(octalCode, unNudgedDetails); + // find necessary leaf size + float newLeafSize = findNewLeafSize(args->nudgeVec, unNudgedDetails.s); + args->ancestorSize = unNudgedDetails.s; + // check to see if this unNudged node can be nudged - if (unNudgedDetails.s <= args->newSize) { + if (unNudgedDetails.s <= newLeafSize) { args->thisVoxelTree->nudgeLeaf(node, extraData); return false; } else { @@ -1928,8 +1944,6 @@ 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; @@ -1942,28 +1956,24 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { glm::vec3 nudge = args->nudgeVec; // delete the old node - if (nudge.x >= args->ancestorSize && nudge.y >= args->ancestorSize && nudge.z >= args->ancestorSize) { + // if the nudge replaces the node in an area outside of the ancestor node + if (fabs(nudge.x) >= args->ancestorSize || fabs(nudge.y) >= args->ancestorSize || fabs(nudge.z) >= args->ancestorSize) { args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); - qDebug("unNudged voxel deleted!\n"); } // nudge the old node - qDebug("nudged by %f, %f, %f\n", nudge.x, nudge.y, nudge.z); - voxelDetails.x = unNudgedDetails.x + nudge.x; voxelDetails.y = unNudgedDetails.y + nudge.y; voxelDetails.z = unNudgedDetails.z + nudge.z; // 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"); + args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_SET_VOXEL_DESTRUCTIVE, voxelDetails); } void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount, VoxelEditPacketSender& voxelEditSender) { - // calculate minNudgeAmount to check if breaking the tree into smaller chunks is necessary - float minNudgeAmount = fmin(nudgeAmount.x, nudgeAmount.y); - minNudgeAmount = fmin(minNudgeAmount, nudgeAmount.z); + if (nudgeAmount == glm::vec3(0, 0, 0)) { + return; + } // get octal code of this node unsigned char* octalCode = nodeToNudge->getOctalCode(); @@ -1975,7 +1985,6 @@ void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmoun NodeChunkArgs args; args.thisVoxelTree = this; args.ancestorSize = ancestorDetails.s; - args.newSize = minNudgeAmount; args.nudgeVec = nudgeAmount; args.voxelEditSenderPtr = &voxelEditSender; args.colorIndex = 0;