Merge branch 'nudge'

Conflicts:
	interface/src/Menu.cpp
	libraries/voxels/src/VoxelTree.h
This commit is contained in:
LionTurtle 2013-09-05 17:58:39 -07:00
commit 59943dc2e8
11 changed files with 225 additions and 6 deletions

View file

@ -701,6 +701,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;
@ -842,6 +845,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;
@ -1279,6 +1285,26 @@ void Application::pasteVoxels() {
}
}
void Application::nudgeVoxels() {
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) {
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
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(_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() {
_audio.setListenMode(AudioRingBuffer::NORMAL);
}
@ -1375,6 +1401,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(),
@ -1664,9 +1691,11 @@ void Application::update(float deltaTime) {
_mouseVoxel.red = 255;
_mouseVoxel.green = _mouseVoxel.blue = 0;
} else if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode)) {
// yellow indicates deletion
// 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<QColor>();
_mouseVoxel.red = paintColor.red();
@ -2248,7 +2277,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);

View file

@ -146,6 +146,7 @@ public slots:
void cutVoxels();
void copyVoxels();
void pasteVoxels();
void nudgeVoxels();
void setRenderVoxels(bool renderVoxels);
void doKillLocalVoxels();
@ -302,6 +303,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;

View file

@ -131,6 +131,9 @@ Menu::Menu() :
QAction* colorVoxelMode = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::VoxelColorMode, Qt::Key_B);
_voxelModeActionsGroup->addAction(colorVoxelMode);
QAction* nudgeVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelNudgeMode, Qt::Key_N);
_voxelModeActionsGroup->addAction(nudgeVoxelMode);
QAction* selectVoxelMode = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::VoxelSelectMode, Qt::Key_O);
_voxelModeActionsGroup->addAction(selectVoxelMode);
@ -177,6 +180,12 @@ Menu::Menu() :
appInstance,
SLOT(setFullscreen(bool)));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true);
addActionToQMenuAndActionHash(voxelMenu, MenuOption::ExportVoxels, Qt::CTRL | Qt::Key_E, appInstance, SLOT(exportVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::ImportVoxels, Qt::CTRL | Qt::Key_I, appInstance, SLOT(importVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::CutVoxels, Qt::CTRL | Qt::Key_X, appInstance, SLOT(cutVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::CopyVoxels, Qt::CTRL | Qt::Key_C, appInstance, SLOT(copyVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::PasteVoxels, Qt::CTRL | Qt::Key_V, appInstance, SLOT(pasteVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::NudgeVoxels, Qt::CTRL | Qt::Key_N, appInstance, SLOT(nudgeVoxels()));
addActionToQMenuAndActionHash(viewMenu,
MenuOption::IncreaseAvatarSize,

View file

@ -169,6 +169,7 @@ namespace MenuOption {
const QString LookAtVectors = "Look-at Vectors";
const QString LowRes = "Lower Resolution While Moving";
const QString Mirror = "Mirror";
const QString NudgeVoxels = "Nudge Voxels";
const QString OcclusionCulling = "Occlusion Culling";
const QString OffAxisProjection = "Off-Axis Projection";
const QString Oscilloscope = "Audio Oscilloscope";
@ -204,6 +205,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";

View file

@ -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);

View file

@ -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);

View file

@ -62,6 +62,7 @@ public:
float getVoxelsCreatedPerSecondAverage();
float getVoxelsColoredPerSecondAverage();
float getVoxelsBytesReadPerSecondAverage();
VoxelTree* getVoxelTree() {return _tree;}
void killLocalVoxels();

View file

@ -12,6 +12,7 @@
#define __shared__VoxelEditPacketSender__
#include <PacketSender.h>
#include <PacketHeaders.h>
#include <SharedUtil.h> // for VoxelDetail
#include "JurisdictionMap.h"

View file

@ -422,4 +422,4 @@ void VoxelNode::notifyDeleteHooks() {
for (int i = 0; i < _hooks.size(); i++) {
_hooks[i]->nodeDeleted(this);
}
}
}

View file

@ -31,6 +31,7 @@
#include "VoxelConstants.h"
#include "VoxelNodeBag.h"
#include "VoxelTree.h"
#include <PacketHeaders.h>
float boundaryDistanceForRenderLevel(unsigned int renderLevel) {
return ::VOXEL_SIZE_SCALE / powf(2, renderLevel);
@ -151,7 +152,7 @@ VoxelNode* VoxelTree::nodeForOctalCode(VoxelNode* ancestorNode,
return childNode;
} else {
// we need to go deeper
return nodeForOctalCode(childNode, needleCode,parentOfFoundNode);
return nodeForOctalCode(childNode, needleCode, parentOfFoundNode);
}
}
}
@ -397,10 +398,10 @@ void VoxelTree::deleteVoxelCodeFromTreeRecursion(VoxelNode* node, void* extraDat
}
}
}
int lengthOfancestorNode = numberOfThreeBitSectionsInCode(ancestorNode->getOctalCode());
int lengthOfAncestorNode = numberOfThreeBitSectionsInCode(ancestorNode->getOctalCode());
// If we've reached the parent of the target, then stop breaking up children
if (lengthOfancestorNode == (args->lengthOfCode - 1)) {
if (lengthOfAncestorNode == (args->lengthOfCode - 1)) {
break;
}
ancestorNode->addChildAtIndex(index);
@ -1856,3 +1857,128 @@ void VoxelTree::emptyDeleteQueue() {
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;
};
bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) {
if (node->isLeaf()) {
// we have reached the deepest level of nodes/voxels
// now there are two scenarios
// 1) this node's size is <= the minNudgeAmount
// in which case we will simply call nudgeLeaf on this leaf
// 2) this node's size is still not <= the minNudgeAmount
// in which case we need to break this leaf down until the leaf sizes are <= minNudgeAmount
NodeChunkArgs* args = (NodeChunkArgs*)extraData;
// get octal code of this node
unsigned char* octalCode = node->getOctalCode();
// get voxel position/size
VoxelPositionSize unNudgedDetails;
voxelDetailsForCode(octalCode, unNudgedDetails);
// check to see if this unNudged node can be nudged
if (unNudgedDetails.s <= args->newSize) {
args->thisVoxelTree->nudgeLeaf(node, extraData);
return false;
} else {
// break the current leaf into smaller chunks
args->thisVoxelTree->chunkifyLeaf(node);
}
}
return true;
}
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;
}
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
node->addChildAtIndex(i);
node->getChildAtIndex(i)->setColor(node->getColor());
}
}
// This function is called to nudge the leaves of a tree, given that the
// nudge amount is >= to the leaf scale.
void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) {
NodeChunkArgs* args = (NodeChunkArgs*)extraData;
// get octal code of this node
unsigned char* octalCode = node->getOctalCode();
// 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];
voxelDetails.green = node->getColor()[1];
voxelDetails.blue = node->getColor()[2];
glm::vec3 nudge = args->nudgeVec;
// delete the old node
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");
}
// 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");
}
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);
// 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;
args.colorIndex = 0;
recurseNodeWithOperation(nodeToNudge, nudgeCheck, &args);
}

View file

@ -18,6 +18,7 @@
#include "VoxelNode.h"
#include "VoxelNodeBag.h"
#include "VoxelSceneStats.h"
#include "VoxelEditPacketSender.h"
#include <QObject>
@ -188,6 +189,13 @@ public:
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
void recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseVoxelTreeOperation operation,
const glm::vec3& point, void* extraData);
void recurseTreeWithOperationDistanceSortedTimed(PointerStack* stackOfNodes, long allowedTime,
RecurseVoxelTreeOperation operation,
const glm::vec3& point, void* extraData);
void nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount, VoxelEditPacketSender& voxelEditSender);
signals:
void importSize(float x, float y, float z);
void importProgress(int progress);
@ -247,6 +255,11 @@ private:
void queueForLaterDelete(unsigned char* codeBuffer);
/// flushes out any Octal Codes that had to be queued
void emptyDeleteQueue();
// helper functions for nudgeSubTree
static bool nudgeCheck(VoxelNode* node, void* extraData);
void nudgeLeaf(VoxelNode* node, void* extraData);
void chunkifyLeaf(VoxelNode* node);
};
float boundaryDistanceForRenderLevel(unsigned int renderLevel);