diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7989d8b715..13dd81b28a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1160,8 +1160,16 @@ const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mo (_mouseVoxel.z + _mouseVoxel.s / 2.f) * TREE_SCALE); } +const float NUDGE_PRECISION_LIMIT = 1 / pow(2.0, 12.0); + void Application::decreaseVoxelSize() { - _mouseVoxelScale /= 2; + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { + if (_mouseVoxelScale >= NUDGE_PRECISION_LIMIT) { + _mouseVoxelScale /= 2; + } + } else { + _mouseVoxelScale /= 2; + } } void Application::increaseVoxelSize() { @@ -2315,17 +2323,18 @@ void Application::displaySide(Camera& whichCamera) { } else { glColor3ub(_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue); } - glTranslatef(_mouseVoxel.x + _mouseVoxel.s*0.5f, - _mouseVoxel.y + _mouseVoxel.s*0.5f, - _mouseVoxel.z + _mouseVoxel.s*0.5f); - glLineWidth(4.0f); + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { - if (_nudgeVoxel.s) { - glutWireCube(_nudgeVoxel.s); - } else { - glutWireCube(_mouseVoxel.s); - } + glTranslatef(_mouseVoxel.x + _nudgeVoxel.s*0.5f, + _mouseVoxel.y + _nudgeVoxel.s*0.5f, + _mouseVoxel.z + _nudgeVoxel.s*0.5f); + glLineWidth(4.0f); + glutWireCube(_nudgeVoxel.s); } else { + glTranslatef(_mouseVoxel.x + _mouseVoxel.s*0.5f, + _mouseVoxel.y + _mouseVoxel.s*0.5f, + _mouseVoxel.z + _mouseVoxel.s*0.5f); + glLineWidth(4.0f); glutWireCube(_mouseVoxel.s); } glLineWidth(1.0f); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 2e4fbdf26e..0880af33ee 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1861,9 +1861,9 @@ void VoxelTree::cancelImport() { class NodeChunkArgs { public: VoxelTree* thisVoxelTree; - float ancestorSize; glm::vec3 nudgeVec; VoxelEditPacketSender* voxelEditSenderPtr; + int childOrder[NUMBER_OF_CHILDREN]; }; float findNewLeafSize(const glm::vec3& nudgeAmount, float leafSize) { @@ -1885,6 +1885,65 @@ float findNewLeafSize(const glm::vec3& nudgeAmount, float leafSize) { return newLeafSize; } +void reorderChildrenForNudge(void* extraData) { + NodeChunkArgs* args = (NodeChunkArgs*)extraData; + glm::vec3 nudgeVec = args->nudgeVec; + int lastToNudgeVote[NUMBER_OF_CHILDREN] = { 0 }; + + const int POSITIVE_X_ORDERING[4] = {0, 1, 2, 3}; + const int NEGATIVE_X_ORDERING[4] = {4, 5, 6, 7}; + const int POSITIVE_Y_ORDERING[4] = {0, 1, 4, 5}; + const int NEGATIVE_Y_ORDERING[4] = {2, 3, 6, 7}; + const int POSITIVE_Z_ORDERING[4] = {0, 2, 4, 6}; + const int NEGATIVE_Z_ORDERING[4] = {1, 3, 5, 7}; + + if (nudgeVec.x > 0) { + for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { + lastToNudgeVote[POSITIVE_X_ORDERING[i]]++; + } + } else if (nudgeVec.x < 0) { + for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { + lastToNudgeVote[NEGATIVE_X_ORDERING[i]]++; + } + } + if (nudgeVec.y > 0) { + for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { + lastToNudgeVote[POSITIVE_Y_ORDERING[i]]++; + } + } else if (nudgeVec.y < 0) { + for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { + lastToNudgeVote[NEGATIVE_Y_ORDERING[i]]++; + } + } + if (nudgeVec.z > 0) { + for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { + lastToNudgeVote[POSITIVE_Z_ORDERING[i]]++; + } + } else if (nudgeVec.z > 0) { + for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { + lastToNudgeVote[NEGATIVE_Z_ORDERING[i]]++; + } + } + + int nUncountedVotes = NUMBER_OF_CHILDREN; + + while (nUncountedVotes > 0) { + int maxNumVotes = 0; + int maxVoteIndex = -1; + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + if (lastToNudgeVote[i] > maxNumVotes) { + maxNumVotes = lastToNudgeVote[i]; + maxVoteIndex = i; + } else if (lastToNudgeVote[i] == maxNumVotes && maxVoteIndex == -1) { + maxVoteIndex = i; + } + } + lastToNudgeVote[maxVoteIndex] = -1; + args->childOrder[nUncountedVotes - 1] = maxVoteIndex; + nUncountedVotes--; + } +} + bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) { if (node->isLeaf()) { // we have reached the deepest level of nodes/voxels @@ -1953,20 +2012,30 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { glm::vec3 nudge = args->nudgeVec; // delete the old node - // 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); - } + args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); // nudge the old node - voxelDetails.x = unNudgedDetails.x + nudge.x; - voxelDetails.y = unNudgedDetails.y + nudge.y; - voxelDetails.z = unNudgedDetails.z + nudge.z; + voxelDetails.x += nudge.x; + voxelDetails.y += nudge.y; + voxelDetails.z += nudge.z; // create a new voxel in its stead args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_SET_VOXEL_DESTRUCTIVE, voxelDetails); } +// Recurses voxel node with an operation function +void VoxelTree::recurseNodeForNudge(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData) { + NodeChunkArgs* args = (NodeChunkArgs*)extraData; + if (operation(node, extraData)) { + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + VoxelNode* child = node->getChildAtIndex(args->childOrder[i]); + if (child) { + recurseNodeForNudge(child, operation, extraData); + } + } + } +} + void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount, VoxelEditPacketSender& voxelEditSender) { if (nudgeAmount == glm::vec3(0, 0, 0)) { return; @@ -1981,9 +2050,9 @@ void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmoun NodeChunkArgs args; args.thisVoxelTree = this; - args.ancestorSize = ancestorDetails.s; args.nudgeVec = nudgeAmount; args.voxelEditSenderPtr = &voxelEditSender; + reorderChildrenForNudge(&args); - recurseNodeWithOperation(nodeToNudge, nudgeCheck, &args); + recurseNodeForNudge(nodeToNudge, nudgeCheck, &args); } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 48550956b2..a379ba910c 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -253,6 +253,7 @@ private: void emptyDeleteQueue(); // helper functions for nudgeSubTree + void recurseNodeForNudge(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData); static bool nudgeCheck(VoxelNode* node, void* extraData); void nudgeLeaf(VoxelNode* node, void* extraData); void chunkifyLeaf(VoxelNode* node);