From 62b29d26d28e468a27714012e5f693b1b77fdd6e Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Thu, 29 Aug 2013 18:17:06 -0700 Subject: [PATCH 01/44] Nudge function added. Testing nudge. --- interface/src/Application.cpp | 3 + interface/src/VoxelSystem.h | 1 + libraries/voxels/src/VoxelNode.cpp | 2 +- libraries/voxels/src/VoxelTree.cpp | 93 +++++++++++++++++++++++++++++- libraries/voxels/src/VoxelTree.h | 7 +++ 5 files changed, 102 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d69770678c..e22f1c0ccb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1543,6 +1543,9 @@ void Application::update(float deltaTime) { hoveredNode->setColor(_hoverVoxelOriginalColor); _isHoverVoxelSounding = false; } + glm::vec3 nudgeVec(1, 1, 1); + _voxels.getVoxelTree()->nudgeSubTree(hoveredNode, nudgeVec); + // qDebug("nudge called!\n"); } else { // Voxel is not found, clear all _isHoverVoxelSounding = false; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 7b6c001e8a..c51df3ce70 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -60,6 +60,7 @@ public: float getVoxelsCreatedPerSecondAverage(); float getVoxelsColoredPerSecondAverage(); float getVoxelsBytesReadPerSecondAverage(); + VoxelTree* getVoxelTree() {return _tree;} void killLocalVoxels(); diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 7355e91243..72fb72d466 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -422,4 +422,4 @@ void VoxelNode::notifyDeleteHooks() { for (int i = 0; i < _hooks.size(); i++) { _hooks[i]->nodeDeleted(this); } -} +} \ No newline at end of file diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index b17200448b..b06562fa7b 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -206,7 +206,7 @@ VoxelNode* VoxelTree::nodeForOctalCode(VoxelNode* ancestorNode, return childNode; } else { // we need to go deeper - return nodeForOctalCode(childNode, needleCode,parentOfFoundNode); + return nodeForOctalCode(childNode, needleCode, parentOfFoundNode); } } } @@ -452,10 +452,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); @@ -1911,3 +1911,90 @@ void VoxelTree::emptyDeleteQueue() { void VoxelTree::cancelImport() { _stopImport = true; } + +class NodeChunkArgs { +public: + VoxelTree* thisVoxelTree; + float newSize; + glm::vec3 nudgeVec; +}; + +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 + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + node->addChildAtIndex(i); + if (node->isColored()) { + 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); + + // delete the old node + deleteVoxelAt(unNudgedDetails.x, unNudgedDetails.y, unNudgedDetails.z, unNudgedDetails.s); + qDebug("unNudged voxel deleted!\n"); + + // create a new voxel in its stead + glm::vec3 nudge = args->nudgeVec; + 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); + createVoxel(unNudgedDetails.x + nudge.x, unNudgedDetails.y + nudge.y, unNudgedDetails.z + nudge.z, unNudgedDetails.s, + 0, 0, 0, true); + qDebug("nudged voxel created!\n"); +} + +void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount) { + // 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); + + NodeChunkArgs args; + args.thisVoxelTree = this; + args.newSize = minNudgeAmount; + args.nudgeVec = nudgeAmount; + + recurseNodeWithOperation(nodeToNudge, nudgeCheck, &args); +} diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 4128ba6cbd..396edcc542 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -195,6 +195,8 @@ public: RecurseVoxelTreeOperation operation, const glm::vec3& point, void* extraData); + void nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount); + signals: void importSize(float x, float y, float z); void importProgress(int progress); @@ -254,6 +256,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); From 6e37bc3644c728b044317538bc2e6408b1ef2875 Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Thu, 5 Sep 2013 11:06:12 -0700 Subject: [PATCH 02/44] Nudge code working for nudge that is greater than or equal to leaf size. --- interface/src/Application.cpp | 57 ++++++++++++++++-- interface/src/Application.h | 3 + interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + libraries/voxels/src/VoxelEditPacketSender.h | 1 + libraries/voxels/src/VoxelTree.cpp | 61 +++++++++++++++++--- libraries/voxels/src/VoxelTree.h | 5 +- 7 files changed, 113 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e22f1c0ccb..b90b8cbe0a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -130,7 +130,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _bytesPerSecond(0), _bytesCount(0), _swatch(NULL), - _pasteMode(false) + _pasteMode(false), + _nudgeCount(0) { _applicationStartupTime = startup_time; _window->setWindowTitle("Interface"); @@ -1272,6 +1273,50 @@ void Application::pasteVoxels() { } } +void Application::nudgeVoxels() { + 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(); + + // 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(); + } +} + void Application::setListenModeNormal() { _audio.setListenMode(AudioRingBuffer::NORMAL); } @@ -1543,9 +1588,11 @@ void Application::update(float deltaTime) { hoveredNode->setColor(_hoverVoxelOriginalColor); _isHoverVoxelSounding = false; } - glm::vec3 nudgeVec(1, 1, 1); - _voxels.getVoxelTree()->nudgeSubTree(hoveredNode, nudgeVec); - // qDebug("nudge called!\n"); + // if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode)) { + // nudgeVoxels(); + // _nudgeCount++; + // qDebug("nudgeCount = %d\n", _nudgeCount); + // } } else { // Voxel is not found, clear all _isHoverVoxelSounding = false; @@ -1637,7 +1684,7 @@ 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 { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked() diff --git a/interface/src/Application.h b/interface/src/Application.h index a88ea3269f..f1c1d53a66 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -142,6 +142,7 @@ public slots: void cutVoxels(); void copyVoxels(); void pasteVoxels(); + void nudgeVoxels(); void setRenderVoxels(bool renderVoxels); void doKillLocalVoxels(); @@ -352,6 +353,8 @@ 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 119f21df60..937ef5b74c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -249,6 +249,7 @@ Menu::Menu() : 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())); QMenu* debugMenu = addMenu("Debug"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 252c9a8707..6934f09d8f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -158,6 +158,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 Oscilloscope = "Audio Oscilloscope"; const QString Pair = "Pair"; diff --git a/libraries/voxels/src/VoxelEditPacketSender.h b/libraries/voxels/src/VoxelEditPacketSender.h index e07bd11baa..bda2c8006d 100644 --- a/libraries/voxels/src/VoxelEditPacketSender.h +++ b/libraries/voxels/src/VoxelEditPacketSender.h @@ -12,6 +12,7 @@ #define __shared__VoxelEditPacketSender__ #include +#include #include // for VoxelDetail #include "JurisdictionMap.h" diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index b06562fa7b..6f125e0d6b 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -31,6 +31,7 @@ #include "VoxelConstants.h" #include "VoxelNodeBag.h" #include "VoxelTree.h" +#include float boundaryDistanceForRenderLevel(unsigned int renderLevel) { return ::VOXEL_SIZE_SCALE / powf(2, renderLevel); @@ -1912,11 +1913,20 @@ 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 newSize; glm::vec3 nudgeVec; + VoxelEditPacketSender* voxelEditSenderPtr; + + int colorIndex; }; bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) { @@ -1943,20 +1953,31 @@ bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) { return false; } else { // break the current leaf into smaller chunks - args->thisVoxelTree->chunkifyLeaf(node); + args->thisVoxelTree->chunkifyLeaf(node, extraData); } } return true; } -void VoxelTree::chunkifyLeaf(VoxelNode* node) { +void VoxelTree::chunkifyLeaf(VoxelNode* node, void* extraData) { // 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 (node->isColored()) { - node->getChildAtIndex(i)->setColor(node->getColor()); + 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()); } } @@ -1971,9 +1992,21 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { // get voxel position/size VoxelPositionSize unNudgedDetails; voxelDetailsForCode(octalCode, unNudgedDetails); + 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); // delete the old node - deleteVoxelAt(unNudgedDetails.x, unNudgedDetails.y, unNudgedDetails.z, unNudgedDetails.s); + args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); + // deleteVoxelAt(unNudgedDetails.x, unNudgedDetails.y, unNudgedDetails.z, unNudgedDetails.s); qDebug("unNudged voxel deleted!\n"); // create a new voxel in its stead @@ -1981,12 +2014,20 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { 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); - createVoxel(unNudgedDetails.x + nudge.x, unNudgedDetails.y + nudge.y, unNudgedDetails.z + nudge.z, unNudgedDetails.s, - 0, 0, 0, true); - qDebug("nudged voxel created!\n"); + 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; + qDebug("nudged node created!\n"); } -void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount) { +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); @@ -1995,6 +2036,8 @@ void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmoun args.thisVoxelTree = this; args.newSize = minNudgeAmount; args.nudgeVec = nudgeAmount; + args.voxelEditSenderPtr = &voxelEditSender; + args.colorIndex = 0; recurseNodeWithOperation(nodeToNudge, nudgeCheck, &args); } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 396edcc542..b684c96923 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -19,6 +19,7 @@ #include "VoxelNode.h" #include "VoxelNodeBag.h" #include "VoxelSceneStats.h" +#include "VoxelEditPacketSender.h" #include @@ -195,7 +196,7 @@ public: RecurseVoxelTreeOperation operation, const glm::vec3& point, void* extraData); - void nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount); + void nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount, VoxelEditPacketSender& voxelEditSender); signals: void importSize(float x, float y, float z); @@ -260,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 chunkifyLeaf(VoxelNode* node, void* extraData); }; float boundaryDistanceForRenderLevel(unsigned int renderLevel); From 647bd5b704922d79b973a7d16c1673f6265aa46a Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Thu, 5 Sep 2013 11:30:23 -0700 Subject: [PATCH 03/44] Got rid of delete in nudge. Create is already destructive. --- interface/src/Application.cpp | 2 ++ libraries/voxels/src/VoxelTree.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b90b8cbe0a..2d963f939d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1314,6 +1314,8 @@ void Application::nudgeVoxels() { // _clipboard.recurseTreeWithOperation(sendVoxelsOperation, &args); // _voxelEditSender.flushQueue(); + } else { + qDebug("selectedNode is NULL\n"); } } diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 6f125e0d6b..bb20dd1d4a 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -2005,9 +2005,10 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { qDebug("UnNudged xyz: %f, %f, %f\n", unNudgedDetails.x, unNudgedDetails.y, unNudgedDetails.z); // delete the old node - args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); + // 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"); + // qDebug("unNudged voxel deleted!\n"); // create a new voxel in its stead glm::vec3 nudge = args->nudgeVec; From 868ef8bec67922f4488be9f7341e29d762aa5778 Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Thu, 5 Sep 2013 17:42:25 -0700 Subject: [PATCH 04/44] 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); From f8a74acb02c35fa9e67abfe3c44aa9b4eb8edfa9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 6 Sep 2013 10:19:17 -0700 Subject: [PATCH 05/44] Special frustum handling for mirrored mode. --- interface/src/Application.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eefbc69d25..296a3e2df2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -446,6 +446,13 @@ void Application::updateProjectionMatrix() { nearVal = _viewFrustumOffsetCamera.getNearClip(); farVal = _viewFrustumOffsetCamera.getFarClip(); } + + // when mirrored, we must flip left and right + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + float tmp = left; + left = -right; + right = -tmp; + } glFrustum(left, right, bottom, top, nearVal, farVal); glMatrixMode(GL_MODELVIEW); @@ -1812,8 +1819,9 @@ void Application::update(float deltaTime) { updateProjectionMatrix(); } else if (_webcam.isActive()) { - const float EYE_OFFSET_SCALE = 5.0f; - _myCamera.setEyeOffsetPosition(_webcam.getEstimatedPosition() * EYE_OFFSET_SCALE); + const float EYE_OFFSET_SCALE = 0.1f; + glm::vec3 position = _webcam.getEstimatedPosition() * EYE_OFFSET_SCALE; + _myCamera.setEyeOffsetPosition(glm::vec3(-position.x, -position.y, position.z)); updateProjectionMatrix(); } } @@ -1966,7 +1974,15 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { viewFrustum.setFieldOfView(fov); viewFrustum.setNearClip(nearClip); viewFrustum.setFarClip(farClip); - viewFrustum.setEyeOffsetPosition(camera.getEyeOffsetPosition()); + + // when mirrored, we must flip the eye offset in x to get the correct frustum + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + glm::vec3 position = camera.getEyeOffsetPosition(); + viewFrustum.setEyeOffsetPosition(glm::vec3(-position.x, position.y, position.z)); + + } else { + viewFrustum.setEyeOffsetPosition(camera.getEyeOffsetPosition()); + } viewFrustum.setEyeOffsetOrientation(camera.getEyeOffsetOrientation()); // Ask the ViewFrustum class to calculate our corners From d9657898127dc34a4e79b32b67a2363ba7674459 Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Fri, 6 Sep 2013 11:40:35 -0700 Subject: [PATCH 06/44] Switching nudge to cut/paste implementation. Preliminary. --- interface/src/Application.cpp | 60 ++++++++++++++++++++++++-------- interface/src/Menu.cpp | 9 ++--- interface/src/Util.cpp | 24 ++++++------- interface/src/Util.h | 2 +- libraries/voxels/src/VoxelTree.h | 4 --- 5 files changed, 59 insertions(+), 40 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2a69cb55a1..857951a670 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1287,22 +1287,52 @@ 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); - 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); + // 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; - // 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); + // 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; } } + + + + // 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() { @@ -2278,10 +2308,10 @@ 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); - } + // 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); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3992189c99..1d9e12cc96 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -108,6 +108,7 @@ Menu::Menu() : addActionToQMenuAndActionHash(editMenu, MenuOption::CutVoxels, Qt::CTRL | Qt::Key_X, appInstance, SLOT(cutVoxels())); addActionToQMenuAndActionHash(editMenu, MenuOption::CopyVoxels, Qt::CTRL | Qt::Key_C, appInstance, SLOT(copyVoxels())); addActionToQMenuAndActionHash(editMenu, MenuOption::PasteVoxels, Qt::CTRL | Qt::Key_V, appInstance, SLOT(pasteVoxels())); + addActionToQMenuAndActionHash(editMenu, MenuOption::NudgeVoxels, Qt::CTRL | Qt::Key_N, appInstance, SLOT(nudgeVoxels())); addDisabledActionAndSeparator(editMenu, "Physics"); addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, true); @@ -132,7 +133,7 @@ Menu::Menu() : QAction* colorVoxelMode = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::VoxelColorMode, Qt::Key_B); _voxelModeActionsGroup->addAction(colorVoxelMode); - QAction* nudgeVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelNudgeMode, Qt::Key_N); + QAction* nudgeVoxelMode = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::VoxelNudgeMode, Qt::Key_N); _voxelModeActionsGroup->addAction(nudgeVoxelMode); QAction* selectVoxelMode = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::VoxelSelectMode, Qt::Key_O); @@ -180,12 +181,6 @@ 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, diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index b251500cd2..19c49c2418 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -414,28 +414,26 @@ 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); +void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS) { + glm::vec3 origin = glm::vec3(voxelX, voxelY, voxelZ); 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); + for (int xz = - (GRID_DIMENSIONS / 2); xz <= GRID_DIMENSIONS / 2 + 1; xz++) { + 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); + glVertex3f(origin.x + GRID_DIMENSIONS * voxelS, 0, origin.z + xz * voxelS); + glVertex3f(origin.x - (GRID_DIMENSIONS - 1) * voxelS, 0, origin.z + xz * voxelS); - glm::vec3 zColor(0.0, 0.0, 0.6); - glColor3fv(&zColor.x); + 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); - } + glVertex3f(origin.x + xz * voxelS, 0, origin.z + GRID_DIMENSIONS * voxelS); + glVertex3f(origin.x + xz * voxelS, 0, origin.z - (GRID_DIMENSIONS - 1) * voxelS); } glEnd(); } diff --git a/interface/src/Util.h b/interface/src/Util.h index cad5bc3495..dc61eaca97 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -61,7 +61,7 @@ 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 renderNudgeGrid(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.h b/libraries/voxels/src/VoxelTree.h index c793261433..48550956b2 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -190,10 +190,6 @@ public: 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: From 26411a42b1c5ad132c24fd98a47d5647d1e3f794 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 6 Sep 2013 15:07:15 -0700 Subject: [PATCH 07/44] More focal length bits. --- interface/src/Application.cpp | 32 ++++++++++++++++++++++++---- libraries/voxels/src/ViewFrustum.cpp | 30 +++++++++++++++++--------- libraries/voxels/src/ViewFrustum.h | 15 +++++++------ 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 296a3e2df2..741cb6ad52 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -638,8 +638,8 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_J: if (isShifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(0, 0.002f, 0)) * _myCamera.getEyeOffsetOrientation())); + _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); + } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); } @@ -648,8 +648,8 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_M: if (isShifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(0, -0.002f, 0)) * _myCamera.getEyeOffsetOrientation())); + _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); + } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); } @@ -2934,6 +2934,30 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { // left plane - top edge - viewFrustum.getNear to distant glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); + + // focal plane - bottom edge + glColor3f(1.0f, 0.0f, 1.0f); + float focalProportion = (viewFrustum.getFocalLength() - viewFrustum.getNearClip()) / + (viewFrustum.getFarClip() - viewFrustum.getNearClip()); + glm::vec3 focalBottomLeft = glm::mix(viewFrustum.getNearBottomLeft(), viewFrustum.getFarBottomLeft(), focalProportion); + glm::vec3 focalBottomRight = glm::mix(viewFrustum.getNearBottomRight(), + viewFrustum.getFarBottomRight(), focalProportion); + glVertex3f(focalBottomLeft.x, focalBottomLeft.y, focalBottomLeft.z); + glVertex3f(focalBottomRight.x, focalBottomRight.y, focalBottomRight.z); + + // focal plane - top edge + glm::vec3 focalTopLeft = glm::mix(viewFrustum.getNearTopLeft(), viewFrustum.getFarTopLeft(), focalProportion); + glm::vec3 focalTopRight = glm::mix(viewFrustum.getNearTopRight(), viewFrustum.getFarTopRight(), focalProportion); + glVertex3f(focalTopLeft.x, focalTopLeft.y, focalTopLeft.z); + glVertex3f(focalTopRight.x, focalTopRight.y, focalTopRight.z); + + // focal plane - left edge + glVertex3f(focalBottomLeft.x, focalBottomLeft.y, focalBottomLeft.z); + glVertex3f(focalTopLeft.x, focalTopLeft.y, focalTopLeft.z); + + // focal plane - right edge + glVertex3f(focalBottomRight.x, focalBottomRight.y, focalBottomRight.z); + glVertex3f(focalTopRight.x, focalTopRight.y, focalTopRight.z); } glEnd(); glEnable(GL_LIGHTING); diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index a35dc49ec0..7914ad0165 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -32,6 +32,7 @@ ViewFrustum::ViewFrustum() : _aspectRatio(1.0), _nearClip(0.1), _farClip(500.0), + _focalLength(0.25f), _keyholeRadius(DEFAULT_KEYHOLE_RADIUS), _farTopLeft(0,0,0), _farTopRight(0,0,0), @@ -310,15 +311,16 @@ bool testMatches(float lhs, float rhs) { bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { bool result = - testMatches(compareTo._position, _position ) && - testMatches(compareTo._direction, _direction ) && - testMatches(compareTo._up, _up ) && - testMatches(compareTo._right, _right ) && - testMatches(compareTo._fieldOfView, _fieldOfView ) && - testMatches(compareTo._aspectRatio, _aspectRatio ) && - testMatches(compareTo._nearClip, _nearClip ) && - testMatches(compareTo._farClip, _farClip ) && - testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition ) && + testMatches(compareTo._position, _position) && + testMatches(compareTo._direction, _direction) && + testMatches(compareTo._up, _up) && + testMatches(compareTo._right, _right) && + testMatches(compareTo._fieldOfView, _fieldOfView) && + testMatches(compareTo._aspectRatio, _aspectRatio) && + testMatches(compareTo._nearClip, _nearClip) && + testMatches(compareTo._farClip, _farClip) && + testMatches(compareTo._focalLength, _focalLength) && + testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition) && testMatches(compareTo._eyeOffsetOrientation, _eyeOffsetOrientation); if (!result && debug) { @@ -351,6 +353,9 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { qDebug("%s -- compareTo._farClip=%f _farClip=%f\n", (testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"), compareTo._farClip, _farClip); + qDebug("%s -- compareTo._focalLength=%f _focalLength=%f\n", + (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"), + compareTo._focalLength, _focalLength); qDebug("%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f\n", (testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition) ? "MATCHES " : "NO MATCH"), compareTo._eyeOffsetPosition.x, compareTo._eyeOffsetPosition.y, compareTo._eyeOffsetPosition.z, @@ -401,13 +406,17 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom nearClipPlane = glm::vec4(-normal.x, -normal.y, -normal.z, glm::dot(normal, corners[0])); farClipPlane = glm::vec4(normal.x, normal.y, normal.z, -glm::dot(normal, corners[4])); + // compute the focal proportion (zero is near clip, one is far clip) + float focalProportion = (_focalLength - _nearClip) / (_farClip - _nearClip); + // get the extents at Z = -near left = FLT_MAX; right = -FLT_MAX; bottom = FLT_MAX; top = -FLT_MAX; for (int i = 0; i < 4; i++) { - glm::vec4 intersection = corners[i] * (-near / corners[i].z); + glm::vec4 corner = glm::mix(corners[i], corners[i + 4], focalProportion); + glm::vec4 intersection = corner * (-near / corner.z); left = min(left, intersection.x); right = max(right, intersection.x); bottom = min(bottom, intersection.y); @@ -426,6 +435,7 @@ void ViewFrustum::printDebugDetails() const { qDebug("_keyHoleRadius=%f\n", _keyholeRadius); qDebug("_nearClip=%f\n", _nearClip); qDebug("_farClip=%f\n", _farClip); + qDebug("_focalLength=%f\n", _focalLength); qDebug("_eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z ); qDebug("_eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y, _eyeOffsetOrientation.z, _eyeOffsetOrientation.w ); diff --git a/libraries/voxels/src/ViewFrustum.h b/libraries/voxels/src/ViewFrustum.h index 22830cb48d..803e52908e 100644 --- a/libraries/voxels/src/ViewFrustum.h +++ b/libraries/voxels/src/ViewFrustum.h @@ -39,6 +39,7 @@ public: void setAspectRatio(float a) { _aspectRatio = a; } void setNearClip(float n) { _nearClip = n; } void setFarClip(float f) { _farClip = f; } + void setFocalLength(float length) { _focalLength = length; } void setEyeOffsetPosition(const glm::vec3& p) { _eyeOffsetPosition = p; } void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; } @@ -47,6 +48,7 @@ public: float getAspectRatio() const { return _aspectRatio; } float getNearClip() const { return _nearClip; } float getFarClip() const { return _farClip; } + float getFocalLength() const { return _focalLength; } const glm::vec3& getEyeOffsetPosition() const { return _eyeOffsetPosition; } const glm::quat& getEyeOffsetOrientation() const { return _eyeOffsetOrientation; } @@ -111,12 +113,13 @@ private: glm::vec3 _right; // Lens attributes - float _fieldOfView; - float _aspectRatio; - float _nearClip; - float _farClip; - glm::vec3 _eyeOffsetPosition; - glm::quat _eyeOffsetOrientation; + float _fieldOfView; + float _aspectRatio; + float _nearClip; + float _farClip; + float _focalLength; + glm::vec3 _eyeOffsetPosition; + glm::quat _eyeOffsetOrientation; // keyhole attributes float _keyholeRadius; From f18a40dc89f6933e801aff4510a9845e045b26e7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 6 Sep 2013 15:12:53 -0700 Subject: [PATCH 08/44] correct timing for assignment-client check in --- assignment-client/src/main.cpp | 65 +++++++++++++++++-------------- libraries/shared/src/NodeList.cpp | 1 + 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index f3d6b8c0cd..ac34fb0723 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -16,7 +16,7 @@ #include #include -const int ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; +const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; int main(int argc, char* const argv[]) { @@ -28,6 +28,8 @@ int main(int argc, char* const argv[]) { // change the timeout on the nodelist socket to be as often as we want to re-request nodeList->getNodeSocket()->setBlockingReceiveTimeoutInUsecs(ASSIGNMENT_REQUEST_INTERVAL_USECS); + timeval lastRequest = {}; + unsigned char packetData[MAX_PACKET_SIZE]; ssize_t receivedBytes = 0; @@ -51,38 +53,41 @@ int main(int argc, char* const argv[]) { Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); while (true) { - // if we're here we have no assignment, so send a request - qDebug() << "Sending an assignment request -" << requestAssignment; - nodeList->sendAssignment(requestAssignment); + if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { + gettimeofday(&lastRequest, NULL); + // if we're here we have no assignment, so send a request + qDebug() << "Sending an assignment request -" << requestAssignment; + nodeList->sendAssignment(requestAssignment); + } - while (nodeList->getNodeSocket()->receive(packetData, &receivedBytes)) { - if (packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { + if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && + packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { + + // construct the deployed assignment from the packet data + Assignment deployedAssignment(packetData, receivedBytes); + + qDebug() << "Received an assignment - " << deployedAssignment << "\n"; + + // switch our nodelist DOMAIN_IP to the ip receieved in the assignment + if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { + in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; + nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); - // construct the deployed assignment from the packet data - Assignment deployedAssignment(packetData, receivedBytes); - - qDebug() << "Received an assignment - " << deployedAssignment << "\n"; - - // switch our nodelist DOMAIN_IP to the ip receieved in the assignment - if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { - in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; - nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); - - qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr); - } - - if (deployedAssignment.getType() == Assignment::AudioMixer) { - AudioMixer::run(); - } else { - AvatarMixer::run(); - } - - qDebug() << "Assignment finished or never started - waiting for new assignment"; - - // reset our NodeList by switching back to unassigned and clearing the list - nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); - nodeList->clear(); + qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr); } + + if (deployedAssignment.getType() == Assignment::AudioMixer) { + AudioMixer::run(); + } else { + qDebug() << "Running as an avatar mixer!"; + AvatarMixer::run(); + } + + qDebug() << "Assignment finished or never started - waiting for new assignment"; + + // reset our NodeList by switching back to unassigned and clearing the list + nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); + nodeList->clear(); } } } \ No newline at end of file diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index c650190a4a..db90856251 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -255,6 +255,7 @@ void NodeList::clear() { } _numNodes = 0; + _numNoReplyDomainCheckIns = 0; } void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest) { From 3b78678a7686393e2f7165fa87cab78a094bb1b0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 6 Sep 2013 15:21:55 -0700 Subject: [PATCH 09/44] cleanup pool grabbing for DS and AC --- assignment-client/src/main.cpp | 19 +++---------------- domain-server/src/main.cpp | 20 +++++--------------- libraries/shared/src/NodeList.cpp | 2 +- 3 files changed, 9 insertions(+), 32 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index ac34fb0723..d33bf10e2e 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -18,7 +18,7 @@ const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; -int main(int argc, char* const argv[]) { +int main(int argc, const char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); @@ -33,21 +33,8 @@ int main(int argc, char* const argv[]) { unsigned char packetData[MAX_PACKET_SIZE]; ssize_t receivedBytes = 0; - // loop the parameters to see if we were passed a pool - int parameter = -1; - const char ALLOWED_PARAMETERS[] = "p::"; - const char POOL_PARAMETER_CHAR = 'p'; - - char* assignmentPool = NULL; - - while ((parameter = getopt(argc, argv, ALLOWED_PARAMETERS)) != -1) { - if (parameter == POOL_PARAMETER_CHAR) { - // copy the passed assignment pool - int poolLength = strlen(optarg); - assignmentPool = new char[poolLength + sizeof(char)]; - strcpy(assignmentPool, optarg); - } - } + // grab the assignment pool from argv, if it was passed + const char* assignmentPool = getCmdOption(argc, argv, "-p"); // create a request assignment, accept all assignments, pass the desired pool (if it exists) Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 882fa85098..4bb554ab53 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -48,7 +48,7 @@ unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* no return currentPosition; } -int main(int argc, char* const argv[]) { +int main(int argc, const char* argv[]) { NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, DOMAIN_LISTEN_PORT); // If user asks to run in "local" mode then we do NOT replace the IP // with the EC2 IP. Otherwise, we will replace the IP like we used to @@ -85,21 +85,11 @@ int main(int argc, char* const argv[]) { timeval lastStatSendTime = {}; - // loop the parameters to see if we were passed a pool for assignment - int parameter = -1; - const char ALLOWED_PARAMETERS[] = "p::-local::"; - const char POOL_PARAMETER_CHAR = 'p'; + // set our assignment pool from argv, if it exists + const char* assignmentPool = getCmdOption(argc, argv, "-p"); - char* assignmentPool = NULL; - - while ((parameter = getopt(argc, argv, ALLOWED_PARAMETERS)) != -1) { - if (parameter == POOL_PARAMETER_CHAR) { - // copy the passed assignment pool - int poolLength = strlen(optarg); - assignmentPool = new char[poolLength + sizeof(char)]; - strcpy(assignmentPool, optarg); - } - } + // grab the overriden assignment-server hostname from argv, if it exists + const char* assignmentServer = getCmdOption(argc, argv, "-a"); // use a map to keep track of iterations of silence for assignment creation requests const int ASSIGNMENT_SILENCE_MAX_ITERATIONS = 5; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index db90856251..cd52ff8ded 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -375,7 +375,7 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte return readNodes; } -const char ASSIGNMENT_SERVER_HOSTNAME[] = "assignment.highfidelity.io"; +const char ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; const sockaddr_in assignmentServerSocket = socketForHostnameAndHostOrderPort(ASSIGNMENT_SERVER_HOSTNAME, ASSIGNMENT_SERVER_PORT); From 65ef778efd6482007a8fd5b55b7e92a9977677d8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 6 Sep 2013 15:31:21 -0700 Subject: [PATCH 10/44] allow passing of custom assignment-server to DS and AC --- assignment-client/src/main.cpp | 3 +++ domain-server/src/main.cpp | 2 +- libraries/shared/src/NodeList.cpp | 10 +++++++--- libraries/shared/src/NodeList.h | 2 ++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index d33bf10e2e..1da0a0215a 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -36,6 +36,9 @@ int main(int argc, const char* argv[]) { // grab the assignment pool from argv, if it was passed const char* assignmentPool = getCmdOption(argc, argv, "-p"); + // set the overriden assignment-server hostname from argv, if it exists + nodeList->setAssignmentServerHostname(getCmdOption(argc, argv, "-a")); + // create a request assignment, accept all assignments, pass the desired pool (if it exists) Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 4bb554ab53..5fcef77a8c 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -89,7 +89,7 @@ int main(int argc, const char* argv[]) { const char* assignmentPool = getCmdOption(argc, argv, "-p"); // grab the overriden assignment-server hostname from argv, if it exists - const char* assignmentServer = getCmdOption(argc, argv, "-a"); + nodeList->setAssignmentServerHostname(getCmdOption(argc, argv, "-a")); // use a map to keep track of iterations of silence for assignment creation requests const int ASSIGNMENT_SILENCE_MAX_ITERATIONS = 5; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index cd52ff8ded..ad5876f622 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -375,9 +375,7 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte return readNodes; } -const char ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; -const sockaddr_in assignmentServerSocket = socketForHostnameAndHostOrderPort(ASSIGNMENT_SERVER_HOSTNAME, - ASSIGNMENT_SERVER_PORT); +const char GLOBAL_ASSIGNMENT_SERVER_HOSTNAME[] = "assignment.highfidelity.io"; void NodeList::sendAssignment(Assignment& assignment) { unsigned char assignmentPacket[MAX_PACKET_SIZE]; @@ -388,6 +386,12 @@ void NodeList::sendAssignment(Assignment& assignment) { int numHeaderBytes = populateTypeAndVersion(assignmentPacket, assignmentPacketType); int numAssignmentBytes = assignment.packToBuffer(assignmentPacket + numHeaderBytes); + + // setup the assignmentServerSocket once, use a custom assignmentServerHostname if it is present + static sockaddr_in assignmentServerSocket = socketForHostnameAndHostOrderPort((_assignmentServerHostname != NULL + ? (const char*) _assignmentServerHostname + : GLOBAL_ASSIGNMENT_SERVER_HOSTNAME), + ASSIGNMENT_SERVER_PORT); _nodeSocket.send((sockaddr*) &assignmentServerSocket, assignmentPacket, numHeaderBytes + numAssignmentBytes); } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 8afe8e38d3..dad422a29b 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -99,6 +99,7 @@ public: void sendDomainServerCheckIn(); int processDomainServerList(unsigned char *packetData, size_t dataBytes); + void setAssignmentServerHostname(const char* serverHostname) { _assignmentServerHostname = serverHostname; } void sendAssignment(Assignment& assignment); Node* nodeWithAddress(sockaddr *senderAddress); @@ -151,6 +152,7 @@ private: pthread_t removeSilentNodesThread; pthread_t checkInWithDomainServerThread; int _numNoReplyDomainCheckIns; + const char* _assignmentServerHostname; void handlePingReply(sockaddr *nodeAddress); void timePingReply(sockaddr *nodeAddress, unsigned char *packetData); From 8424c4e38b47de0bf968b982bc53e8f96dd9a41f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 6 Sep 2013 15:44:24 -0700 Subject: [PATCH 11/44] make DS immediately request assignments instead of waiting one silent loop --- domain-server/src/main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 5fcef77a8c..6de926a7a7 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -101,9 +101,9 @@ int main(int argc, const char* argv[]) { Assignment avatarAssignment(Assignment::Create, Assignment::AvatarMixer, assignmentPool); while (true) { - if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER)) { - if (assignmentSilenceCount[&audioAssignment] == ASSIGNMENT_SILENCE_MAX_ITERATIONS) { + std::map::iterator countIt = assignmentSilenceCount.find(&audioAssignment); + if (countIt == assignmentSilenceCount.end() || countIt->second == ASSIGNMENT_SILENCE_MAX_ITERATIONS) { nodeList->sendAssignment(audioAssignment); assignmentSilenceCount[&audioAssignment] = 0; } else { @@ -114,7 +114,8 @@ int main(int argc, const char* argv[]) { } if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER)) { - if (assignmentSilenceCount[&avatarAssignment] == ASSIGNMENT_SILENCE_MAX_ITERATIONS) { + std::map::iterator countIt = assignmentSilenceCount.find(&avatarAssignment); + if (countIt == assignmentSilenceCount.end() || countIt->second == ASSIGNMENT_SILENCE_MAX_ITERATIONS) { nodeList->sendAssignment(avatarAssignment); assignmentSilenceCount[&avatarAssignment] = 0; } else { From cbf8a2c202c7b5e487c80bc758ffcf16a8c8aa30 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 6 Sep 2013 16:03:54 -0700 Subject: [PATCH 12/44] use create time already being stored with assignment to decide on re-send --- domain-server/src/main.cpp | 49 ++++++++++++++++------------- libraries/shared/src/Assignment.cpp | 38 +++++++++++----------- libraries/shared/src/Assignment.h | 5 +++ 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 6de926a7a7..32a88e8e08 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -92,40 +92,42 @@ int main(int argc, const char* argv[]) { nodeList->setAssignmentServerHostname(getCmdOption(argc, argv, "-a")); // use a map to keep track of iterations of silence for assignment creation requests - const int ASSIGNMENT_SILENCE_MAX_ITERATIONS = 5; - std::map assignmentSilenceCount; + const long long ASSIGNMENT_SILENCE_MAX_USECS = 5 * 1000 * 1000; // as a domain-server we will always want an audio mixer and avatar mixer - // setup the create assignments for those - Assignment audioAssignment(Assignment::Create, Assignment::AudioMixer, assignmentPool); - Assignment avatarAssignment(Assignment::Create, Assignment::AvatarMixer, assignmentPool); + // setup the create assignment pointers for those + Assignment *audioAssignment = NULL; + Assignment *avatarAssignment = NULL; while (true) { if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER)) { - std::map::iterator countIt = assignmentSilenceCount.find(&audioAssignment); - if (countIt == assignmentSilenceCount.end() || countIt->second == ASSIGNMENT_SILENCE_MAX_ITERATIONS) { - nodeList->sendAssignment(audioAssignment); - assignmentSilenceCount[&audioAssignment] = 0; - } else { - assignmentSilenceCount[&audioAssignment]++; + if (!audioAssignment + || usecTimestampNow() - usecTimestamp(&audioAssignment->getTime()) >= ASSIGNMENT_SILENCE_MAX_USECS) { + + if (!audioAssignment) { + audioAssignment = new Assignment(Assignment::Create, Assignment::AudioMixer, assignmentPool); + } + + nodeList->sendAssignment(*audioAssignment); + audioAssignment->setCreateTimeToNow(); } - } else { - assignmentSilenceCount[&audioAssignment] = 0; } if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER)) { - std::map::iterator countIt = assignmentSilenceCount.find(&avatarAssignment); - if (countIt == assignmentSilenceCount.end() || countIt->second == ASSIGNMENT_SILENCE_MAX_ITERATIONS) { - nodeList->sendAssignment(avatarAssignment); - assignmentSilenceCount[&avatarAssignment] = 0; - } else { - assignmentSilenceCount[&avatarAssignment]++; + if (!avatarAssignment + || usecTimestampNow() - usecTimestamp(&avatarAssignment->getTime()) >= ASSIGNMENT_SILENCE_MAX_USECS) { + if (!avatarAssignment) { + avatarAssignment = new Assignment(Assignment::Create, Assignment::AvatarMixer, assignmentPool); + } + + nodeList->sendAssignment(*avatarAssignment); + + // reset the create time on the assignment so re-request is in ASSIGNMENT_SILENCE_MAX_USECS + avatarAssignment->setCreateTimeToNow(); } - } else { - assignmentSilenceCount[&avatarAssignment] = 0; + } - if (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) && (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) && packetVersionMatch(packetData)) { @@ -236,6 +238,9 @@ int main(int argc, const char* argv[]) { } } } + + delete audioAssignment; + delete avatarAssignment; return 0; } diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 3c6e432f2c..850922396f 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -6,8 +6,6 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include - #include "PacketHeaders.h" #include "Assignment.h" @@ -86,6 +84,24 @@ Assignment::~Assignment() { delete _pool; } +void Assignment::setDomainSocket(const sockaddr* domainSocket) { + + if (_domainSocket) { + // delete the old _domainSocket if it exists + delete _domainSocket; + _domainSocket = NULL; + } + + // create a new sockaddr or sockaddr_in depending on what type of address this is + if (domainSocket->sa_family == AF_INET) { + _domainSocket = (sockaddr*) new sockaddr_in; + memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in)); + } else { + _domainSocket = (sockaddr*) new sockaddr_in6; + memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in6)); + } +} + int Assignment::packToBuffer(unsigned char* buffer) { int numPackedBytes = 0; @@ -114,24 +130,6 @@ int Assignment::packToBuffer(unsigned char* buffer) { return numPackedBytes; } -void Assignment::setDomainSocket(const sockaddr* domainSocket) { - - if (_domainSocket) { - // delete the old _domainSocket if it exists - delete _domainSocket; - _domainSocket = NULL; - } - - // create a new sockaddr or sockaddr_in depending on what type of address this is - if (domainSocket->sa_family == AF_INET) { - _domainSocket = (sockaddr*) new sockaddr_in; - memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in)); - } else { - _domainSocket = (sockaddr*) new sockaddr_in6; - memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in6)); - } -} - QDebug operator<<(QDebug debug, const Assignment &assignment) { debug << "T:" << assignment.getType() << "P:" << assignment.getPool(); return debug.nospace(); diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 2c2673f351..693cc42577 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -9,6 +9,8 @@ #ifndef __hifi__Assignment__ #define __hifi__Assignment__ +#include + #include "NodeList.h" /// Holds information used for request, creation, and deployment of assignments @@ -49,6 +51,9 @@ public: /// \return number of bytes packed into buffer int packToBuffer(unsigned char* buffer); + /// Sets _time to the current time given by gettimeofday + void setCreateTimeToNow() { gettimeofday(&_time, NULL); } + private: Assignment::Direction _direction; /// the direction of the assignment (Create, Deploy, Request) Assignment::Type _type; /// the type of the assignment, defines what the assignee will do From f475163072a5c6dd2f76ecf9eb36a0bd5c55583f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 6 Sep 2013 16:20:13 -0700 Subject: [PATCH 13/44] I believe this should fix the offset in mirror mode. --- interface/src/Application.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 741cb6ad52..a507f9c4e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2155,8 +2155,9 @@ void Application::displaySide(Camera& whichCamera) { // transform by eye offset // flip x if in mirror mode (also requires reversing winding order for backface culling) + float eyeOffsetSign = 1.0f; if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - glScalef(-1.0f, 1.0f, 1.0f); + glScalef(eyeOffsetSign = -1.0f, 1.0f, 1.0f); glFrontFace(GL_CW); } else { @@ -2167,7 +2168,7 @@ void Application::displaySide(Camera& whichCamera) { glm::quat eyeOffsetOrient = whichCamera.getEyeOffsetOrientation(); glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient); glRotatef(-glm::angle(eyeOffsetOrient), eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z); - glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z); + glTranslatef(-eyeOffsetPos.x * eyeOffsetSign, -eyeOffsetPos.y, -eyeOffsetPos.z); // transform view according to whichCamera // could be myCamera (if in normal mode) From 38dd176506cf4f4b535dd574293c2386946f838b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 6 Sep 2013 16:43:22 -0700 Subject: [PATCH 14/44] Fix for off-by-one-frame error. --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a507f9c4e0..0f7cee3da6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -423,9 +423,6 @@ void Application::resizeGL(int width, int height) { resetCamerasOnResizeGL(_viewFrustumOffsetCamera, width, height); resetCamerasOnResizeGL(_myCamera, width, height); - // Tell our viewFrustum about this change, using the application camera - loadViewFrustum(_myCamera, _viewFrustum); - glViewport(0, 0, width, height); // shouldn't this account for the menu??? updateProjectionMatrix(); @@ -436,6 +433,9 @@ void Application::updateProjectionMatrix() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); + // Tell our viewFrustum about this change, using the application camera + loadViewFrustum(_myCamera, _viewFrustum); + float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); From 1a767f3e081961779d56ebe58b1e01bb33f92472 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 6 Sep 2013 16:52:32 -0700 Subject: [PATCH 15/44] Bump up the offset scale for Faceshift. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0f7cee3da6..43c7a8f585 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1813,7 +1813,7 @@ void Application::update(float deltaTime) { if (Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { if (_faceshift.isActive()) { - const float EYE_OFFSET_SCALE = 0.005f; + const float EYE_OFFSET_SCALE = 0.025f; glm::vec3 position = _faceshift.getHeadTranslation() * EYE_OFFSET_SCALE; _myCamera.setEyeOffsetPosition(glm::vec3(-position.x, position.y, position.z)); updateProjectionMatrix(); From 699007691bd425770d44ca763729e4b91cd32790 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 6 Sep 2013 17:50:16 -0700 Subject: [PATCH 16/44] Simplification. --- interface/src/Application.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 43c7a8f585..a473469734 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1812,16 +1812,17 @@ void Application::update(float deltaTime) { } if (Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { + float xSign = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) ? 1.0f : -1.0f; if (_faceshift.isActive()) { const float EYE_OFFSET_SCALE = 0.025f; glm::vec3 position = _faceshift.getHeadTranslation() * EYE_OFFSET_SCALE; - _myCamera.setEyeOffsetPosition(glm::vec3(-position.x, position.y, position.z)); + _myCamera.setEyeOffsetPosition(glm::vec3(position.x * xSign, position.y, position.z)); updateProjectionMatrix(); } else if (_webcam.isActive()) { - const float EYE_OFFSET_SCALE = 0.1f; + const float EYE_OFFSET_SCALE = 0.5f; glm::vec3 position = _webcam.getEstimatedPosition() * EYE_OFFSET_SCALE; - _myCamera.setEyeOffsetPosition(glm::vec3(-position.x, -position.y, position.z)); + _myCamera.setEyeOffsetPosition(glm::vec3(position.x * xSign, -position.y, position.z)); updateProjectionMatrix(); } } @@ -1974,15 +1975,7 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { viewFrustum.setFieldOfView(fov); viewFrustum.setNearClip(nearClip); viewFrustum.setFarClip(farClip); - - // when mirrored, we must flip the eye offset in x to get the correct frustum - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - glm::vec3 position = camera.getEyeOffsetPosition(); - viewFrustum.setEyeOffsetPosition(glm::vec3(-position.x, position.y, position.z)); - - } else { - viewFrustum.setEyeOffsetPosition(camera.getEyeOffsetPosition()); - } + viewFrustum.setEyeOffsetPosition(camera.getEyeOffsetPosition()); viewFrustum.setEyeOffsetOrientation(camera.getEyeOffsetOrientation()); // Ask the ViewFrustum class to calculate our corners @@ -2155,9 +2148,8 @@ void Application::displaySide(Camera& whichCamera) { // transform by eye offset // flip x if in mirror mode (also requires reversing winding order for backface culling) - float eyeOffsetSign = 1.0f; if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - glScalef(eyeOffsetSign = -1.0f, 1.0f, 1.0f); + glScalef(-1.0f, 1.0f, 1.0f); glFrontFace(GL_CW); } else { @@ -2168,7 +2160,7 @@ void Application::displaySide(Camera& whichCamera) { glm::quat eyeOffsetOrient = whichCamera.getEyeOffsetOrientation(); glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient); glRotatef(-glm::angle(eyeOffsetOrient), eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z); - glTranslatef(-eyeOffsetPos.x * eyeOffsetSign, -eyeOffsetPos.y, -eyeOffsetPos.z); + glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z); // transform view according to whichCamera // could be myCamera (if in normal mode) From ddf92b39c76408836d4a54e1f7202f44f71fe63d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Sun, 8 Sep 2013 17:52:35 -0700 Subject: [PATCH 17/44] Fix for off-axis ambient occlusion. --- .../resources/shaders/ambient_occlusion.frag | 3 +-- interface/src/Application.cpp | 22 ++++++++++++------- interface/src/Application.h | 4 ++++ .../src/renderer/AmbientOcclusionEffect.cpp | 2 +- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/interface/resources/shaders/ambient_occlusion.frag b/interface/resources/shaders/ambient_occlusion.frag index 4e87ac3221..b3a054cc67 100644 --- a/interface/resources/shaders/ambient_occlusion.frag +++ b/interface/resources/shaders/ambient_occlusion.frag @@ -44,8 +44,7 @@ float texCoordToViewSpaceZ(vec2 texCoord) { // given a texture coordinate, returns the 3D view space coordinate vec3 texCoordToViewSpace(vec2 texCoord) { float z = texCoordToViewSpaceZ(texCoord); - return vec3(((texCoord * 2.0 - vec2(1.0 - gl_ProjectionMatrix[2][0], 1.0)) * - (rightTop - leftBottom) + rightTop + leftBottom) * z / (-2.0 * near), z); + return vec3((leftBottom + texCoord * (rightTop - leftBottom)) * (-z / near), z); } void main(void) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a473469734..ea61179057 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -438,7 +438,7 @@ void Application::updateProjectionMatrix() { float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); // If we're in Display Frustum mode, then we want to use the slightly adjust near/far clip values of the // _viewFrustumOffsetCamera, so that we can see more of the application content in the application's frustum @@ -446,13 +446,6 @@ void Application::updateProjectionMatrix() { nearVal = _viewFrustumOffsetCamera.getNearClip(); farVal = _viewFrustumOffsetCamera.getFarClip(); } - - // when mirrored, we must flip left and right - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - float tmp = left; - left = -right; - right = -tmp; - } glFrustum(left, right, bottom, top, nearVal, farVal); glMatrixMode(GL_MODELVIEW); @@ -2144,6 +2137,19 @@ void Application::setupWorldLight(Camera& whichCamera) { glMateriali(GL_FRONT, GL_SHININESS, 96); } +void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near, + float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { + + _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, near, far, nearClipPlane, farClipPlane); + + // when mirrored, we must flip left and right + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + float tmp = left; + left = -right; + right = -tmp; + } +} + void Application::displaySide(Camera& whichCamera) { // transform by eye offset diff --git a/interface/src/Application.h b/interface/src/Application.h index 0630d3cbca..8bb3106375 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -135,6 +135,10 @@ public: void setupWorldLight(Camera& whichCamera); + /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. + void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near, + float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; + virtual void nodeAdded(Node* node); virtual void nodeKilled(Node* node); virtual void packetSentNotification(ssize_t length); diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index 2169ec00af..907ec7a863 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -103,7 +103,7 @@ void AmbientOcclusionEffect::render() { float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - Application::getInstance()->getViewFrustum()->computeOffAxisFrustum( + Application::getInstance()->computeOffAxisFrustum( left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); _occlusionProgram->bind(); From 49050320901cf755937d7659cdc65d0e86943b04 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 09:44:43 -0700 Subject: [PATCH 18/44] allow forking of multiple assignment-clients from the main target --- assignment-client/src/main.cpp | 42 ++++++++++++++++++++++++++----- domain-server/src/main.cpp | 6 ++++- libraries/shared/src/NodeList.cpp | 18 ++++++------- libraries/shared/src/NodeList.h | 4 +-- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 1da0a0215a..67d2a1e021 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -18,13 +18,47 @@ const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; + int main(int argc, const char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); + sockaddr_in customAssignmentSocket = {}; + + // grab the overriden assignment-server hostname from argv, if it exists + const char* customAssignmentServer = getCmdOption(argc, argv, "-a"); + if (customAssignmentServer) { + customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServer, ASSIGNMENT_SERVER_PORT); + } + + const char* NUM_FORKS_PARAMETER = "-n"; + const char* numForksIncludingParentString = getCmdOption(argc, argv, NUM_FORKS_PARAMETER); + + if (numForksIncludingParentString) { + int numForksIncludingParent = atoi(numForksIncludingParentString); + qDebug() << "Starting" << numForksIncludingParent << "assignment clients."; + + int processID = 0; + + // fire off as many children as we need (this is one less than the parent since the parent will run as well) + for (int i = 0; i < numForksIncludingParent - 1; i++) { + processID = fork(); + + if (processID == 0) { + // this is one of the children, break so we don't start a fork bomb + break; + } + } + } + // create a NodeList as an unassigned client NodeList* nodeList = NodeList::createInstance(NODE_TYPE_UNASSIGNED); + // set the custom assignment socket if we have it + if (customAssignmentSocket.sin_addr.s_addr != 0) { + nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); + } + // change the timeout on the nodelist socket to be as often as we want to re-request nodeList->getNodeSocket()->setBlockingReceiveTimeoutInUsecs(ASSIGNMENT_REQUEST_INTERVAL_USECS); @@ -34,10 +68,8 @@ int main(int argc, const char* argv[]) { ssize_t receivedBytes = 0; // grab the assignment pool from argv, if it was passed - const char* assignmentPool = getCmdOption(argc, argv, "-p"); - - // set the overriden assignment-server hostname from argv, if it exists - nodeList->setAssignmentServerHostname(getCmdOption(argc, argv, "-a")); + const char* ASSIGNMENT_POOL_PARAMETER = "-p"; + const char* assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_PARAMETER); // create a request assignment, accept all assignments, pass the desired pool (if it exists) Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); @@ -46,7 +78,6 @@ int main(int argc, const char* argv[]) { if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { gettimeofday(&lastRequest, NULL); // if we're here we have no assignment, so send a request - qDebug() << "Sending an assignment request -" << requestAssignment; nodeList->sendAssignment(requestAssignment); } @@ -69,7 +100,6 @@ int main(int argc, const char* argv[]) { if (deployedAssignment.getType() == Assignment::AudioMixer) { AudioMixer::run(); } else { - qDebug() << "Running as an avatar mixer!"; AvatarMixer::run(); } diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 32a88e8e08..c8916f1c59 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -89,7 +89,11 @@ int main(int argc, const char* argv[]) { const char* assignmentPool = getCmdOption(argc, argv, "-p"); // grab the overriden assignment-server hostname from argv, if it exists - nodeList->setAssignmentServerHostname(getCmdOption(argc, argv, "-a")); + const char* customAssignmentServer = getCmdOption(argc, argv, "-a"); + if (customAssignmentServer) { + sockaddr_in customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServer, ASSIGNMENT_SERVER_PORT); + nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); + } // use a map to keep track of iterations of silence for assignment creation requests const long long ASSIGNMENT_SILENCE_MAX_USECS = 5 * 1000 * 1000; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index ad5876f622..4d042b0f63 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -65,7 +65,8 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : _nodeTypesOfInterest(NULL), _ownerID(UNKNOWN_NODE_ID), _lastNodeID(UNKNOWN_NODE_ID + 1), - _numNoReplyDomainCheckIns(0) + _numNoReplyDomainCheckIns(0), + _assignmentServerSocket(NULL) { memcpy(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, sizeof(DEFAULT_DOMAIN_HOSTNAME)); memcpy(_domainIP, DEFAULT_DOMAIN_IP, sizeof(DEFAULT_DOMAIN_IP)); @@ -376,7 +377,8 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte } const char GLOBAL_ASSIGNMENT_SERVER_HOSTNAME[] = "assignment.highfidelity.io"; - +const sockaddr_in GLOBAL_ASSIGNMENT_SOCKET = socketForHostnameAndHostOrderPort(GLOBAL_ASSIGNMENT_SERVER_HOSTNAME, + ASSIGNMENT_SERVER_PORT); void NodeList::sendAssignment(Assignment& assignment) { unsigned char assignmentPacket[MAX_PACKET_SIZE]; @@ -387,13 +389,11 @@ void NodeList::sendAssignment(Assignment& assignment) { int numHeaderBytes = populateTypeAndVersion(assignmentPacket, assignmentPacketType); int numAssignmentBytes = assignment.packToBuffer(assignmentPacket + numHeaderBytes); - // setup the assignmentServerSocket once, use a custom assignmentServerHostname if it is present - static sockaddr_in assignmentServerSocket = socketForHostnameAndHostOrderPort((_assignmentServerHostname != NULL - ? (const char*) _assignmentServerHostname - : GLOBAL_ASSIGNMENT_SERVER_HOSTNAME), - ASSIGNMENT_SERVER_PORT); - - _nodeSocket.send((sockaddr*) &assignmentServerSocket, assignmentPacket, numHeaderBytes + numAssignmentBytes); + sockaddr* assignmentServerSocket = (_assignmentServerSocket == NULL) + ? (sockaddr*) &GLOBAL_ASSIGNMENT_SOCKET + : _assignmentServerSocket; + + _nodeSocket.send((sockaddr*) assignmentServerSocket, assignmentPacket, numHeaderBytes + numAssignmentBytes); } Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, char nodeType, uint16_t nodeId) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index dad422a29b..ea94e8c080 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -99,7 +99,7 @@ public: void sendDomainServerCheckIn(); int processDomainServerList(unsigned char *packetData, size_t dataBytes); - void setAssignmentServerHostname(const char* serverHostname) { _assignmentServerHostname = serverHostname; } + void setAssignmentServerSocket(sockaddr* serverSocket) { _assignmentServerSocket = serverSocket; } void sendAssignment(Assignment& assignment); Node* nodeWithAddress(sockaddr *senderAddress); @@ -152,7 +152,7 @@ private: pthread_t removeSilentNodesThread; pthread_t checkInWithDomainServerThread; int _numNoReplyDomainCheckIns; - const char* _assignmentServerHostname; + sockaddr* _assignmentServerSocket; void handlePingReply(sockaddr *nodeAddress); void timePingReply(sockaddr *nodeAddress, unsigned char *packetData); From 2fd043b55c2588cea2b059cc4e612e4ba2a9720f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 10:02:30 -0700 Subject: [PATCH 19/44] code review comments --- domain-server/src/main.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index c8916f1c59..4c13888ee3 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -85,11 +85,14 @@ int main(int argc, const char* argv[]) { timeval lastStatSendTime = {}; + const char ASSIGNMENT_POOL_OPTION = "-p"; + const char ASSIGNMENT_SERVER_OPTION = "-a"; + // set our assignment pool from argv, if it exists - const char* assignmentPool = getCmdOption(argc, argv, "-p"); + const char* assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_OPTION); // grab the overriden assignment-server hostname from argv, if it exists - const char* customAssignmentServer = getCmdOption(argc, argv, "-a"); + const char* customAssignmentServer = getCmdOption(argc, argv, ASSIGNMENT_SERVER_OPTION); if (customAssignmentServer) { sockaddr_in customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServer, ASSIGNMENT_SERVER_PORT); nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); @@ -100,8 +103,8 @@ int main(int argc, const char* argv[]) { // as a domain-server we will always want an audio mixer and avatar mixer // setup the create assignment pointers for those - Assignment *audioAssignment = NULL; - Assignment *avatarAssignment = NULL; + Assignment* audioAssignment = NULL; + Assignment* avatarAssignment = NULL; while (true) { if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER)) { From 64e3c19a8c789db748a0519e67ae8440d73d29c2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 10:07:31 -0700 Subject: [PATCH 20/44] fix an incorrectly typed const --- domain-server/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 4c13888ee3..07b67db85d 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -85,8 +85,8 @@ int main(int argc, const char* argv[]) { timeval lastStatSendTime = {}; - const char ASSIGNMENT_POOL_OPTION = "-p"; - const char ASSIGNMENT_SERVER_OPTION = "-a"; + const char ASSIGNMENT_POOL_OPTION[] = "-p"; + const char ASSIGNMENT_SERVER_OPTION[]g = "-a"; // set our assignment pool from argv, if it exists const char* assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_OPTION); From d1c602df0768960ab713ba78b7e188174de822d9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 10:10:16 -0700 Subject: [PATCH 21/44] remove an extra g --- domain-server/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 07b67db85d..0d51671e0c 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -86,7 +86,7 @@ int main(int argc, const char* argv[]) { timeval lastStatSendTime = {}; const char ASSIGNMENT_POOL_OPTION[] = "-p"; - const char ASSIGNMENT_SERVER_OPTION[]g = "-a"; + const char ASSIGNMENT_SERVER_OPTION[] = "-a"; // set our assignment pool from argv, if it exists const char* assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_OPTION); From 37aa90932237b981e9e00730afd73daf1d82e4a4 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Sep 2013 11:22:46 -0700 Subject: [PATCH 22/44] Try using the eye coefficients rather than the eye directions reported by Faceshift. --- interface/src/devices/Faceshift.cpp | 45 ++++++++++++++++++++++++++++- interface/src/devices/Faceshift.h | 10 +++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index 4418d19223..5e35d23415 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -26,7 +26,11 @@ Faceshift::Faceshift() : _browHeight(0.0f), _browUpCenterIndex(-1), _mouthSize(0.0f), - _jawOpenIndex(-1) + _jawOpenIndex(-1), + _leftEyeUpIndex(-1), + _leftEyeInIndex(-1), + _rightEyeUpIndex(-1), + _rightEyeInIndex(-1) { connect(&_socket, SIGNAL(connected()), SLOT(noteConnected())); connect(&_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(noteError(QAbstractSocket::SocketError))); @@ -108,6 +112,21 @@ void Faceshift::readFromSocket() { if (_jawOpenIndex != -1) { _mouthSize = data.m_coeffs[_jawOpenIndex]; } + const float PITCH_SCALE = 45.0f; + if (_leftEyeUpIndex != -1) { + _eyeGazeLeftPitch = PITCH_SCALE * (data.m_coeffs[_leftEyeUpIndex] - data.m_coeffs[_leftEyeDownIndex]); + } + const float YAW_SCALE = 45.0f; + if (_leftEyeInIndex != -1) { + _eyeGazeLeftYaw = YAW_SCALE * (data.m_coeffs[_leftEyeOutIndex] - data.m_coeffs[_leftEyeInIndex]); + } + if (_rightEyeUpIndex != -1) { + _eyeGazeRightPitch = PITCH_SCALE * (data.m_coeffs[_rightEyeUpIndex] - + data.m_coeffs[_rightEyeDownIndex]); + } + if (_rightEyeInIndex != -1) { + _eyeGazeRightYaw = YAW_SCALE * (data.m_coeffs[_rightEyeInIndex] - data.m_coeffs[_rightEyeOutIndex]); + } } break; } @@ -125,6 +144,30 @@ void Faceshift::readFromSocket() { } else if (names[i] == "JawOpen") { _jawOpenIndex = i; + + } else if (names[i] == "EyeUp_L") { + _leftEyeUpIndex = i; + + } else if (names[i] == "EyeDown_L") { + _leftEyeDownIndex = i; + + } else if (names[i] == "EyeIn_L") { + _leftEyeInIndex = i; + + } else if (names[i] == "EyeOut_L") { + _leftEyeOutIndex = i; + + } else if (names[i] == "EyeUp_R") { + _rightEyeUpIndex = i; + + } else if (names[i] == "EyeDown_R") { + _rightEyeDownIndex = i; + + } else if (names[i] == "EyeIn_R") { + _rightEyeInIndex = i; + + } else if (names[i] == "EyeOut_R") { + _rightEyeOutIndex = i; } } break; diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 286a7a56a1..745ce6f099 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -85,6 +85,16 @@ private: float _mouthSize; int _jawOpenIndex; + + int _leftEyeUpIndex; + int _leftEyeDownIndex; + int _leftEyeInIndex; + int _leftEyeOutIndex; + + int _rightEyeUpIndex; + int _rightEyeDownIndex; + int _rightEyeInIndex; + int _rightEyeOutIndex; }; #endif /* defined(__interface__Faceshift__) */ From bb073bdff3f4a2519ed2ae0c83cfe9549dd47b9b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 11:59:58 -0700 Subject: [PATCH 23/44] fork off n children and keep the parent process as a monitor --- assignment-client/src/main.cpp | 126 ++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 58 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 67d2a1e021..72ae826ef2 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -32,16 +32,19 @@ int main(int argc, const char* argv[]) { } const char* NUM_FORKS_PARAMETER = "-n"; - const char* numForksIncludingParentString = getCmdOption(argc, argv, NUM_FORKS_PARAMETER); + const char* numForksString = getCmdOption(argc, argv, NUM_FORKS_PARAMETER); - if (numForksIncludingParentString) { - int numForksIncludingParent = atoi(numForksIncludingParentString); - qDebug() << "Starting" << numForksIncludingParent << "assignment clients."; + int processID = 0; + int numForks = 0; + + if (numForksString) { + numForks = atoi(numForksString); + qDebug() << "Starting" << numForks << "assignment clients."; + - int processID = 0; // fire off as many children as we need (this is one less than the parent since the parent will run as well) - for (int i = 0; i < numForksIncludingParent - 1; i++) { + for (int i = 0; i < numForks; i++) { processID = fork(); if (processID == 0) { @@ -51,63 +54,70 @@ int main(int argc, const char* argv[]) { } } - // create a NodeList as an unassigned client - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_UNASSIGNED); - - // set the custom assignment socket if we have it - if (customAssignmentSocket.sin_addr.s_addr != 0) { - nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); - } - - // change the timeout on the nodelist socket to be as often as we want to re-request - nodeList->getNodeSocket()->setBlockingReceiveTimeoutInUsecs(ASSIGNMENT_REQUEST_INTERVAL_USECS); - - timeval lastRequest = {}; - - unsigned char packetData[MAX_PACKET_SIZE]; - ssize_t receivedBytes = 0; - - // grab the assignment pool from argv, if it was passed - const char* ASSIGNMENT_POOL_PARAMETER = "-p"; - const char* assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_PARAMETER); - - // create a request assignment, accept all assignments, pass the desired pool (if it exists) - Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); - - while (true) { - if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { - gettimeofday(&lastRequest, NULL); - // if we're here we have no assignment, so send a request - nodeList->sendAssignment(requestAssignment); + if (processID == 0 || numForks == 0) { + // this is one of the child forks or there is a single assignment client, continue assignment-client execution + + // create a NodeList as an unassigned client + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_UNASSIGNED); + + // set the custom assignment socket if we have it + if (customAssignmentSocket.sin_addr.s_addr != 0) { + nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); } - if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && - packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { + // change the timeout on the nodelist socket to be as often as we want to re-request + nodeList->getNodeSocket()->setBlockingReceiveTimeoutInUsecs(ASSIGNMENT_REQUEST_INTERVAL_USECS); + + timeval lastRequest = {}; + + unsigned char packetData[MAX_PACKET_SIZE]; + ssize_t receivedBytes = 0; + + // grab the assignment pool from argv, if it was passed + const char* ASSIGNMENT_POOL_PARAMETER = "-p"; + const char* assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_PARAMETER); + + // create a request assignment, accept all assignments, pass the desired pool (if it exists) + Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); + + while (true) { + if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { + gettimeofday(&lastRequest, NULL); + // if we're here we have no assignment, so send a request + nodeList->sendAssignment(requestAssignment); + } - // construct the deployed assignment from the packet data - Assignment deployedAssignment(packetData, receivedBytes); - - qDebug() << "Received an assignment - " << deployedAssignment << "\n"; - - // switch our nodelist DOMAIN_IP to the ip receieved in the assignment - if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { - in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; - nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); + if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && + packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { - qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr); + // construct the deployed assignment from the packet data + Assignment deployedAssignment(packetData, receivedBytes); + + qDebug() << "Received an assignment - " << deployedAssignment << "\n"; + + // switch our nodelist DOMAIN_IP to the ip receieved in the assignment + if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { + in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; + nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); + + qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr); + } + + if (deployedAssignment.getType() == Assignment::AudioMixer) { + AudioMixer::run(); + } else { + AvatarMixer::run(); + } + + qDebug() << "Assignment finished or never started - waiting for new assignment"; + + // reset our NodeList by switching back to unassigned and clearing the list + nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); + nodeList->clear(); } - - if (deployedAssignment.getType() == Assignment::AudioMixer) { - AudioMixer::run(); - } else { - AvatarMixer::run(); - } - - qDebug() << "Assignment finished or never started - waiting for new assignment"; - - // reset our NodeList by switching back to unassigned and clearing the list - nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); - nodeList->clear(); } + } else { + // don't bail until all children have finished + wait(NULL); } } \ No newline at end of file From 597c57a11740b529d80bded8a692ad9f05aa4d40 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Sep 2013 12:17:12 -0700 Subject: [PATCH 24/44] Revert "Try using the eye coefficients rather than the eye directions reported by" This reverts commit 37aa90932237b981e9e00730afd73daf1d82e4a4. --- interface/src/devices/Faceshift.cpp | 45 +---------------------------- interface/src/devices/Faceshift.h | 10 ------- 2 files changed, 1 insertion(+), 54 deletions(-) diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index 5e35d23415..4418d19223 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -26,11 +26,7 @@ Faceshift::Faceshift() : _browHeight(0.0f), _browUpCenterIndex(-1), _mouthSize(0.0f), - _jawOpenIndex(-1), - _leftEyeUpIndex(-1), - _leftEyeInIndex(-1), - _rightEyeUpIndex(-1), - _rightEyeInIndex(-1) + _jawOpenIndex(-1) { connect(&_socket, SIGNAL(connected()), SLOT(noteConnected())); connect(&_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(noteError(QAbstractSocket::SocketError))); @@ -112,21 +108,6 @@ void Faceshift::readFromSocket() { if (_jawOpenIndex != -1) { _mouthSize = data.m_coeffs[_jawOpenIndex]; } - const float PITCH_SCALE = 45.0f; - if (_leftEyeUpIndex != -1) { - _eyeGazeLeftPitch = PITCH_SCALE * (data.m_coeffs[_leftEyeUpIndex] - data.m_coeffs[_leftEyeDownIndex]); - } - const float YAW_SCALE = 45.0f; - if (_leftEyeInIndex != -1) { - _eyeGazeLeftYaw = YAW_SCALE * (data.m_coeffs[_leftEyeOutIndex] - data.m_coeffs[_leftEyeInIndex]); - } - if (_rightEyeUpIndex != -1) { - _eyeGazeRightPitch = PITCH_SCALE * (data.m_coeffs[_rightEyeUpIndex] - - data.m_coeffs[_rightEyeDownIndex]); - } - if (_rightEyeInIndex != -1) { - _eyeGazeRightYaw = YAW_SCALE * (data.m_coeffs[_rightEyeInIndex] - data.m_coeffs[_rightEyeOutIndex]); - } } break; } @@ -144,30 +125,6 @@ void Faceshift::readFromSocket() { } else if (names[i] == "JawOpen") { _jawOpenIndex = i; - - } else if (names[i] == "EyeUp_L") { - _leftEyeUpIndex = i; - - } else if (names[i] == "EyeDown_L") { - _leftEyeDownIndex = i; - - } else if (names[i] == "EyeIn_L") { - _leftEyeInIndex = i; - - } else if (names[i] == "EyeOut_L") { - _leftEyeOutIndex = i; - - } else if (names[i] == "EyeUp_R") { - _rightEyeUpIndex = i; - - } else if (names[i] == "EyeDown_R") { - _rightEyeDownIndex = i; - - } else if (names[i] == "EyeIn_R") { - _rightEyeInIndex = i; - - } else if (names[i] == "EyeOut_R") { - _rightEyeOutIndex = i; } } break; diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 745ce6f099..286a7a56a1 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -85,16 +85,6 @@ private: float _mouthSize; int _jawOpenIndex; - - int _leftEyeUpIndex; - int _leftEyeDownIndex; - int _leftEyeInIndex; - int _leftEyeOutIndex; - - int _rightEyeUpIndex; - int _rightEyeDownIndex; - int _rightEyeInIndex; - int _rightEyeOutIndex; }; #endif /* defined(__interface__Faceshift__) */ From f770dd623bb4d69c9fc7c8dee6b03ed0d39e5969 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 12:31:53 -0700 Subject: [PATCH 25/44] have parent assignment-client make sure there are always n --- assignment-client/src/main.cpp | 207 ++++++++++++++++++++++----------- 1 file changed, 137 insertions(+), 70 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 72ae826ef2..50e4f069a5 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -7,6 +7,8 @@ // #include +#include +#include #include #include @@ -18,106 +20,171 @@ const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; +pid_t* childForks = NULL; +sockaddr_in customAssignmentSocket = {}; +const char* assignmentPool = NULL; +int numForks = 0; + +void childClient() { + // this is one of the child forks or there is a single assignment client, continue assignment-client execution + + // create a NodeList as an unassigned client + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_UNASSIGNED); + + // set the custom assignment socket if we have it + if (customAssignmentSocket.sin_addr.s_addr != 0) { + nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); + } + + // change the timeout on the nodelist socket to be as often as we want to re-request + nodeList->getNodeSocket()->setBlockingReceiveTimeoutInUsecs(ASSIGNMENT_REQUEST_INTERVAL_USECS); + + timeval lastRequest = {}; + + unsigned char packetData[MAX_PACKET_SIZE]; + ssize_t receivedBytes = 0; + + // create a request assignment, accept all assignments, pass the desired pool (if it exists) + Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); + + while (true) { + if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { + gettimeofday(&lastRequest, NULL); + // if we're here we have no assignment, so send a request + nodeList->sendAssignment(requestAssignment); + } + + if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && + packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { + + // construct the deployed assignment from the packet data + Assignment deployedAssignment(packetData, receivedBytes); + + qDebug() << "Received an assignment - " << deployedAssignment << "\n"; + + // switch our nodelist DOMAIN_IP to the ip receieved in the assignment + if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { + in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; + nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); + + qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr); + } + + if (deployedAssignment.getType() == Assignment::AudioMixer) { + AudioMixer::run(); + } else { + AvatarMixer::run(); + } + + qDebug() << "Assignment finished or never started - waiting for new assignment"; + + // reset our NodeList by switching back to unassigned and clearing the list + nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); + nodeList->clear(); + } + } +} + +void sigchldHandler(int sig) { + pid_t processID; + int status; + + while ((processID = waitpid(-1, &status, WNOHANG)) != -1) { + if (processID == 0) { + // there are no more children to process, break out of here + break; + } + + qDebug() << "Handling death of" << processID; + + int newForkProcessID = 0; + + // find the dead process in the array of child forks + for (int i = 0; i < ::numForks; i++) { + if (::childForks[i] == processID) { + qDebug() << "Matched" << ::childForks[i] << "with" << processID; + + newForkProcessID = fork(); + if (newForkProcessID == 0) { + // this is the child, call childClient + childClient(); + + // break out so we don't fork bomb + break; + } else { + // this is the parent, replace the dead process with the new one + ::childForks[i] = newForkProcessID; + break; + } + } + } + } +} + +void parentMonitor() { + + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sigchldHandler; + + sigaction(SIGCHLD, &sa, NULL); + + pid_t childID = 0; + + // don't bail until all children have finished + while ((childID = waitpid(-1, NULL, 0))) { + if (errno == ECHILD) { + break; + } + } + + // delete the array of pid_t holding the forked process IDs + delete[] ::childForks; +} int main(int argc, const char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); - sockaddr_in customAssignmentSocket = {}; - // grab the overriden assignment-server hostname from argv, if it exists const char* customAssignmentServer = getCmdOption(argc, argv, "-a"); if (customAssignmentServer) { - customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServer, ASSIGNMENT_SERVER_PORT); + ::customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServer, ASSIGNMENT_SERVER_PORT); } const char* NUM_FORKS_PARAMETER = "-n"; const char* numForksString = getCmdOption(argc, argv, NUM_FORKS_PARAMETER); + // grab the assignment pool from argv, if it was passed + const char* ASSIGNMENT_POOL_PARAMETER = "-p"; + ::assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_PARAMETER); + int processID = 0; - int numForks = 0; if (numForksString) { - numForks = atoi(numForksString); + ::numForks = atoi(numForksString); qDebug() << "Starting" << numForks << "assignment clients."; - + ::childForks = new pid_t[numForks]; // fire off as many children as we need (this is one less than the parent since the parent will run as well) for (int i = 0; i < numForks; i++) { processID = fork(); if (processID == 0) { - // this is one of the children, break so we don't start a fork bomb + // this is in one of the children, break so we don't start a fork bomb break; + } else { + // this is in the parent, save the ID of the forked process + childForks[i] = processID; } } } if (processID == 0 || numForks == 0) { - // this is one of the child forks or there is a single assignment client, continue assignment-client execution - - // create a NodeList as an unassigned client - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_UNASSIGNED); - - // set the custom assignment socket if we have it - if (customAssignmentSocket.sin_addr.s_addr != 0) { - nodeList->setAssignmentServerSocket((sockaddr*) &customAssignmentSocket); - } - - // change the timeout on the nodelist socket to be as often as we want to re-request - nodeList->getNodeSocket()->setBlockingReceiveTimeoutInUsecs(ASSIGNMENT_REQUEST_INTERVAL_USECS); - - timeval lastRequest = {}; - - unsigned char packetData[MAX_PACKET_SIZE]; - ssize_t receivedBytes = 0; - - // grab the assignment pool from argv, if it was passed - const char* ASSIGNMENT_POOL_PARAMETER = "-p"; - const char* assignmentPool = getCmdOption(argc, argv, ASSIGNMENT_POOL_PARAMETER); - - // create a request assignment, accept all assignments, pass the desired pool (if it exists) - Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool); - - while (true) { - if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { - gettimeofday(&lastRequest, NULL); - // if we're here we have no assignment, so send a request - nodeList->sendAssignment(requestAssignment); - } - - if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && - packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { - - // construct the deployed assignment from the packet data - Assignment deployedAssignment(packetData, receivedBytes); - - qDebug() << "Received an assignment - " << deployedAssignment << "\n"; - - // switch our nodelist DOMAIN_IP to the ip receieved in the assignment - if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { - in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; - nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); - - qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr); - } - - if (deployedAssignment.getType() == Assignment::AudioMixer) { - AudioMixer::run(); - } else { - AvatarMixer::run(); - } - - qDebug() << "Assignment finished or never started - waiting for new assignment"; - - // reset our NodeList by switching back to unassigned and clearing the list - nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); - nodeList->clear(); - } - } + childClient(); } else { - // don't bail until all children have finished - wait(NULL); + parentMonitor(); } } \ No newline at end of file From 3f941a33715abe16e994ca0e2269bec8c1034152 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 12:42:18 -0700 Subject: [PATCH 26/44] add a missing include for waitpid --- assignment-client/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 50e4f069a5..130cca9135 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include From 001ecec729c04d8a62e285b818d646e7e8f39e03 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 9 Sep 2013 14:38:57 -0600 Subject: [PATCH 27/44] Removing audio-mixer and avatar-mixer jobs --- jenkins/jobs.groovy | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jenkins/jobs.groovy b/jenkins/jobs.groovy index ed33f49723..306ee030a8 100644 --- a/jenkins/jobs.groovy +++ b/jenkins/jobs.groovy @@ -102,8 +102,6 @@ static Closure cmakeBuild(srcDir, instCommand) { def targets = [ 'animation-server':true, 'assignment-server':true, - 'audio-mixer':true, - 'avatar-mixer':true, 'domain-server':true, 'eve':true, 'pairing-server':true, @@ -188,4 +186,4 @@ doxygenJob.with { } } -queue doxygenJob \ No newline at end of file +queue doxygenJob From 8fec78d82afb2be6ad9b0b93bcc935c77b94d6f2 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Sep 2013 13:48:46 -0700 Subject: [PATCH 28/44] Disable random saccades for own eyes. --- interface/src/avatar/Head.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 08efb32062..abf16248c2 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -146,19 +146,6 @@ void Head::resetHairPhysics() { void Head::simulate(float deltaTime, bool isMine, float gyroCameraSensitivity) { - // Update eye saccades - const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; - const float AVERAGE_SACCADE_INTERVAL = 4.0f; - const float MICROSACCADE_MAGNITUDE = 0.002f; - const float SACCADE_MAGNITUDE = 0.04; - - if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) { - _saccadeTarget = MICROSACCADE_MAGNITUDE * randVector(); - } else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) { - _saccadeTarget = SACCADE_MAGNITUDE * randVector(); - } - _saccade += (_saccadeTarget - _saccade) * 0.50f; - // Update audio trailing average for rendering facial animations Faceshift* faceshift = Application::getInstance()->getFaceshift(); if (isMine && faceshift->isActive()) { @@ -173,6 +160,19 @@ void Head::simulate(float deltaTime, bool isMine, float gyroCameraSensitivity) { _browAudioLift = faceshift->getBrowHeight() * BROW_HEIGHT_SCALE; } else { + // Update eye saccades + const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; + const float AVERAGE_SACCADE_INTERVAL = 4.0f; + const float MICROSACCADE_MAGNITUDE = 0.002f; + const float SACCADE_MAGNITUDE = 0.04f; + + if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) { + _saccadeTarget = MICROSACCADE_MAGNITUDE * randVector(); + } else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) { + _saccadeTarget = SACCADE_MAGNITUDE * randVector(); + } + _saccade += (_saccadeTarget - _saccade) * 0.50f; + const float AUDIO_AVERAGING_SECS = 0.05; _averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _averageLoudness + (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness; From 8077963bb1d2641b04bf8eeddc9f2a44f18aefc4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 14:21:33 -0700 Subject: [PATCH 29/44] add standardized logging and leverage forked assignment clients --- assignment-client/src/main.cpp | 20 ++-- domain-server/src/main.cpp | 6 +- libraries/audio/src/AudioMixer.cpp | 14 +-- libraries/shared/src/Assignment.cpp | 6 +- libraries/shared/src/Assignment.h | 2 + libraries/shared/src/Logging.cpp | 106 ++++++++++++++++++ .../shared/src/{Logstash.h => Logging.h} | 18 ++- libraries/shared/src/Logstash.cpp | 60 ---------- 8 files changed, 150 insertions(+), 82 deletions(-) create mode 100644 libraries/shared/src/Logging.cpp rename libraries/shared/src/{Logstash.h => Logging.h} (66%) delete mode 100644 libraries/shared/src/Logstash.cpp diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 130cca9135..9259e503e3 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -15,11 +15,14 @@ #include #include #include +#include #include #include #include const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; +const char PARENT_TARGET_NAME[] = "assignment-client-monitor"; +const char CHILD_TARGET_NAME[] = "assignment-client"; pid_t* childForks = NULL; sockaddr_in customAssignmentSocket = {}; @@ -61,14 +64,15 @@ void childClient() { // construct the deployed assignment from the packet data Assignment deployedAssignment(packetData, receivedBytes); - qDebug() << "Received an assignment - " << deployedAssignment << "\n"; + Logging::standardizedLog(QString("Received an assignment - %1").arg(deployedAssignment.toString()), + CHILD_TARGET_NAME); // switch our nodelist DOMAIN_IP to the ip receieved in the assignment if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); - qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr); + Logging::standardizedLog(QString("Changed Domain IP to %1").arg(inet_ntoa(domainSocketAddr)), CHILD_TARGET_NAME); } if (deployedAssignment.getType() == Assignment::AudioMixer) { @@ -77,7 +81,8 @@ void childClient() { AvatarMixer::run(); } - qDebug() << "Assignment finished or never started - waiting for new assignment"; + Logging::standardizedLog(QString("Assignment finished or never started - waiting for new assignment"), + CHILD_TARGET_NAME); // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); @@ -96,14 +101,11 @@ void sigchldHandler(int sig) { break; } - qDebug() << "Handling death of" << processID; - int newForkProcessID = 0; // find the dead process in the array of child forks for (int i = 0; i < ::numForks; i++) { if (::childForks[i] == processID) { - qDebug() << "Matched" << ::childForks[i] << "with" << processID; newForkProcessID = fork(); if (newForkProcessID == 0) { @@ -115,6 +117,10 @@ void sigchldHandler(int sig) { } else { // this is the parent, replace the dead process with the new one ::childForks[i] = newForkProcessID; + + Logging::standardizedLog(QString("Repleaced dead %1 with new fork %2").arg(processID).arg(newForkProcessID), + PARENT_TARGET_NAME); + break; } } @@ -165,7 +171,7 @@ int main(int argc, const char* argv[]) { if (numForksString) { ::numForks = atoi(numForksString); - qDebug() << "Starting" << numForks << "assignment clients."; + Logging::standardizedLog(QString("Starting %1 assignment clients").arg(numForks), PARENT_TARGET_NAME); ::childForks = new pid_t[numForks]; diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 0d51671e0c..5739639f95 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -28,7 +28,7 @@ #include "Assignment.h" #include "NodeList.h" #include "NodeTypes.h" -#include "Logstash.h" +#include "Logging.h" #include "PacketHeaders.h" #include "SharedUtil.h" @@ -234,12 +234,12 @@ int main(int argc, const char* argv[]) { } } - if (Logstash::shouldSendStats()) { + if (Logging::shouldSendStats()) { if (usecTimestampNow() - usecTimestamp(&lastStatSendTime) >= (NODE_COUNT_STAT_INTERVAL_MSECS * 1000)) { // time to send our count of nodes and servers to logstash const char NODE_COUNT_LOGSTASH_KEY[] = "ds-node-count"; - Logstash::stashValue(STAT_TYPE_TIMER, NODE_COUNT_LOGSTASH_KEY, nodeList->getNumAliveNodes()); + Logging::stashValue(STAT_TYPE_TIMER, NODE_COUNT_LOGSTASH_KEY, nodeList->getNumAliveNodes()); gettimeofday(&lastStatSendTime, NULL); } diff --git a/libraries/audio/src/AudioMixer.cpp b/libraries/audio/src/AudioMixer.cpp index c6387ce02a..b11aa9c14b 100644 --- a/libraries/audio/src/AudioMixer.cpp +++ b/libraries/audio/src/AudioMixer.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include @@ -105,8 +105,8 @@ void AudioMixer::run() { stk::StkFrames stkFrameBuffer(BUFFER_LENGTH_SAMPLES_PER_CHANNEL, 1); // if we'll be sending stats, call the Logstash::socket() method to make it load the logstash IP outside the loop - if (Logstash::shouldSendStats()) { - Logstash::socket(); + if (Logging::shouldSendStats()) { + Logging::socket(); } while (true) { @@ -114,7 +114,7 @@ void AudioMixer::run() { break; } - if (Logstash::shouldSendStats()) { + if (Logging::shouldSendStats()) { gettimeofday(&beginSendTime, NULL); } @@ -123,12 +123,12 @@ void AudioMixer::run() { gettimeofday(&lastDomainServerCheckIn, NULL); NodeList::getInstance()->sendDomainServerCheckIn(); - if (Logstash::shouldSendStats() && numStatCollections > 0) { + if (Logging::shouldSendStats() && numStatCollections > 0) { // if we should be sending stats to Logstash send the appropriate average now const char MIXER_LOGSTASH_METRIC_NAME[] = "audio-mixer-frame-time-usage"; float averageFrameTimePercentage = sumFrameTimePercentages / numStatCollections; - Logstash::stashValue(STAT_TYPE_TIMER, MIXER_LOGSTASH_METRIC_NAME, averageFrameTimePercentage); + Logging::stashValue(STAT_TYPE_TIMER, MIXER_LOGSTASH_METRIC_NAME, averageFrameTimePercentage); sumFrameTimePercentages = 0.0f; numStatCollections = 0; @@ -398,7 +398,7 @@ void AudioMixer::run() { } } - if (Logstash::shouldSendStats()) { + if (Logging::shouldSendStats()) { // send a packet to our logstash instance // calculate the percentage value for time elapsed for this send (of the max allowable time) diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 850922396f..867854030a 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -130,7 +130,11 @@ int Assignment::packToBuffer(unsigned char* buffer) { return numPackedBytes; } +QString Assignment::toString() const { + return QString("T:%1 P:%2").arg(_type).arg(_pool); +} + QDebug operator<<(QDebug debug, const Assignment &assignment) { - debug << "T:" << assignment.getType() << "P:" << assignment.getPool(); + debug << assignment.toString().toStdString().c_str(); return debug.nospace(); } \ No newline at end of file diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 693cc42577..34cf065ce5 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -54,6 +54,8 @@ public: /// Sets _time to the current time given by gettimeofday void setCreateTimeToNow() { gettimeofday(&_time, NULL); } + QString toString() const; + private: Assignment::Direction _direction; /// the direction of the assignment (Create, Deploy, Request) Assignment::Type _type; /// the type of the assignment, defines what the assignee will do diff --git a/libraries/shared/src/Logging.cpp b/libraries/shared/src/Logging.cpp new file mode 100644 index 0000000000..cb4c249620 --- /dev/null +++ b/libraries/shared/src/Logging.cpp @@ -0,0 +1,106 @@ +// +// Logging.cpp +// hifi +// +// Created by Stephen Birarda on 6/11/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include +#include +#include + +#include "SharedUtil.h" +#include "NodeList.h" + +#include "Logging.h" + +sockaddr_in Logging::logstashSocket = {}; + +sockaddr* Logging::socket() { + + if (logstashSocket.sin_addr.s_addr == 0) { + // we need to construct the socket object + + // assume IPv4 + logstashSocket.sin_family = AF_INET; + + // use the constant port + logstashSocket.sin_port = htons(LOGSTASH_UDP_PORT); + + // lookup the IP address for the constant hostname + struct hostent* logstashHostInfo; + if ((logstashHostInfo = gethostbyname(LOGSTASH_HOSTNAME))) { + memcpy(&logstashSocket.sin_addr, logstashHostInfo->h_addr_list[0], logstashHostInfo->h_length); + } else { + printf("Failed to lookup logstash IP - will try again on next log attempt.\n"); + } + } + + return (sockaddr*) &logstashSocket; +} + +bool Logging::shouldSendStats() { + static bool shouldSendStats = isInEnvironment("production"); + return shouldSendStats; +} + +void Logging::stashValue(char statType, const char* key, float value) { + static char logstashPacket[MAX_PACKET_SIZE]; + + // load up the logstash packet with the key and the passed float value + // send it to 4 decimal places + int numPacketBytes = sprintf(logstashPacket, "%c %s %.4f", statType, key, value); + + NodeList *nodeList = NodeList::getInstance(); + + if (nodeList) { + nodeList->getNodeSocket()->send(socket(), logstashPacket, numPacketBytes); + } +} + +const QString DEBUG_STRING = "DEBUG"; +const QString WARN_STRING = "WARN"; +const QString ERROR_STRING = "ERROR"; + +const QString& stringForLogType(Logging::Type logType) { + if (logType == Logging::Debug) { + return DEBUG_STRING; + } else if (logType == Logging::Warn) { + return WARN_STRING; + } else { + return ERROR_STRING; + } +} + +// the following will produce 2000-10-02 13:55:36 -0700 +const char DATE_STRING_FORMAT[] = "%F %H:%M:%S %z"; + +void Logging::standardizedLog(const QString &output, const char* targetName, Logging::Type logType) { + time_t rawTime; + time(&rawTime); + struct tm* localTime = localtime(&rawTime); + + // log prefix is in the following format + // [DEBUG] [TIMESTAMP] [PID:PARENT_PID] [TARGET] logged string + + QString prefixString = QString("[%1] ").arg(stringForLogType(logType)); + + char dateString[100]; + strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime); + + prefixString.append(QString("[%1] ").arg(dateString)); + + prefixString.append(QString("[%1").arg(getpid())); + + pid_t parentProcessID = getppid(); + if (parentProcessID != 0) { + prefixString.append(QString(":%1] ").arg(parentProcessID)); + } else { + prefixString.append("]"); + } + + prefixString.append(QString("[%1]").arg(targetName)); + + qDebug("%s %s", prefixString.toStdString().c_str(), output.toStdString().c_str()); +} \ No newline at end of file diff --git a/libraries/shared/src/Logstash.h b/libraries/shared/src/Logging.h similarity index 66% rename from libraries/shared/src/Logstash.h rename to libraries/shared/src/Logging.h index 7c805ddb23..c8f12ac8b6 100644 --- a/libraries/shared/src/Logstash.h +++ b/libraries/shared/src/Logging.h @@ -1,16 +1,18 @@ // -// Logstash.h +// Logging.h // hifi // // Created by Stephen Birarda on 6/11/13. // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#ifndef __hifi__Logstash__ -#define __hifi__Logstash__ +#ifndef __hifi__Logging__ +#define __hifi__Logging__ #include +#include + const int LOGSTASH_UDP_PORT = 9500; const char LOGSTASH_HOSTNAME[] = "graphite.highfidelity.io"; @@ -18,11 +20,19 @@ const char STAT_TYPE_TIMER = 't'; const char STAT_TYPE_COUNTER = 'c'; const char STAT_TYPE_GAUGE = 'g'; -class Logstash { +class Logging { public: + + enum Type { + Error, + Warn, + Debug + }; + static sockaddr* socket(); static bool shouldSendStats(); static void stashValue(char statType, const char* key, float value); + static void standardizedLog(const QString& output, const char* targetName, Logging::Type logType = Logging::Debug); private: static sockaddr_in logstashSocket; }; diff --git a/libraries/shared/src/Logstash.cpp b/libraries/shared/src/Logstash.cpp deleted file mode 100644 index 63d3da56d9..0000000000 --- a/libraries/shared/src/Logstash.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// Logstash.cpp -// hifi -// -// Created by Stephen Birarda on 6/11/13. -// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. -// - -#include -#include -#include - -#include "SharedUtil.h" -#include "NodeList.h" - -#include "Logstash.h" - -sockaddr_in Logstash::logstashSocket = {}; - -sockaddr* Logstash::socket() { - - if (logstashSocket.sin_addr.s_addr == 0) { - // we need to construct the socket object - - // assume IPv4 - logstashSocket.sin_family = AF_INET; - - // use the constant port - logstashSocket.sin_port = htons(LOGSTASH_UDP_PORT); - - // lookup the IP address for the constant hostname - struct hostent* logstashHostInfo; - if ((logstashHostInfo = gethostbyname(LOGSTASH_HOSTNAME))) { - memcpy(&logstashSocket.sin_addr, logstashHostInfo->h_addr_list[0], logstashHostInfo->h_length); - } else { - printf("Failed to lookup logstash IP - will try again on next log attempt.\n"); - } - } - - return (sockaddr*) &logstashSocket; -} - -bool Logstash::shouldSendStats() { - static bool shouldSendStats = isInEnvironment("production"); - return shouldSendStats; -} - -void Logstash::stashValue(char statType, const char* key, float value) { - static char logstashPacket[MAX_PACKET_SIZE]; - - // load up the logstash packet with the key and the passed float value - // send it to 4 decimal places - int numPacketBytes = sprintf(logstashPacket, "%c %s %.4f", statType, key, value); - - NodeList *nodeList = NodeList::getInstance(); - - if (nodeList) { - nodeList->getNodeSocket()->send(socket(), logstashPacket, numPacketBytes); - } -} \ No newline at end of file From f8aee88a5b03d41e5f171fffdb42b01405b3ea7b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Sep 2013 14:30:26 -0700 Subject: [PATCH 30/44] Let's try subtracting the long-term average from the eye directions. --- interface/src/Application.cpp | 11 +++++------ interface/src/devices/Faceshift.cpp | 19 ++++++++++++++++++- interface/src/devices/Faceshift.h | 10 ++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ea61179057..36e6147d1d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1531,14 +1531,15 @@ void Application::update(float deltaTime) { // Set where I am looking based on my mouse ray (so that other people can see) glm::vec3 lookAtSpot; + // Update faceshift + _faceshift.update(); + // if we have faceshift, use that to compute the lookat direction glm::vec3 lookAtRayOrigin = mouseRayOrigin, lookAtRayDirection = mouseRayDirection; if (_faceshift.isActive()) { lookAtRayOrigin = _myAvatar.getHead().calculateAverageEyePosition(); - float averagePitch = (_faceshift.getEyeGazeLeftPitch() + _faceshift.getEyeGazeRightPitch()) / 2.0f; - float averageYaw = (_faceshift.getEyeGazeLeftYaw() + _faceshift.getEyeGazeRightYaw()) / 2.0f; - lookAtRayDirection = _myAvatar.getHead().getOrientation() * - glm::quat(glm::radians(glm::vec3(averagePitch, averageYaw, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f); + lookAtRayDirection = _myAvatar.getHead().getOrientation() * glm::quat(glm::radians(glm::vec3( + _faceshift.getEstimatedEyePitch(), _faceshift.getEstimatedEyeYaw(), 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f); } _isLookingAtOtherAvatar = isLookingAtOtherAvatar(lookAtRayOrigin, lookAtRayDirection, lookAtSpot); @@ -1707,8 +1708,6 @@ void Application::update(float deltaTime) { _serialHeadSensor.readData(deltaTime); } - // Update transmitter - // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes updateAvatar(deltaTime); diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index 4418d19223..399369cdd3 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -26,13 +26,30 @@ Faceshift::Faceshift() : _browHeight(0.0f), _browUpCenterIndex(-1), _mouthSize(0.0f), - _jawOpenIndex(-1) + _jawOpenIndex(-1), + _longTermAverageEyePitch(0.0f), + _longTermAverageEyeYaw(0.0f), + _estimatedEyePitch(0.0f), + _estimatedEyeYaw(0.0f) { connect(&_socket, SIGNAL(connected()), SLOT(noteConnected())); connect(&_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(noteError(QAbstractSocket::SocketError))); connect(&_socket, SIGNAL(readyRead()), SLOT(readFromSocket())); } +void Faceshift::update() { + if (!isActive()) { + return; + } + float averageEyePitch = (_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f; + float averageEyeYaw = (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f; + const float LONG_TERM_AVERAGE_SMOOTHING = 0.999f; + _longTermAverageEyePitch = glm::mix(averageEyePitch, _longTermAverageEyePitch, LONG_TERM_AVERAGE_SMOOTHING); + _longTermAverageEyeYaw = glm::mix(averageEyeYaw, _longTermAverageEyeYaw, LONG_TERM_AVERAGE_SMOOTHING); + _estimatedEyePitch = averageEyePitch - _longTermAverageEyePitch; + _estimatedEyeYaw = averageEyeYaw - _longTermAverageEyeYaw; +} + void Faceshift::reset() { if (isActive()) { string message; diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 286a7a56a1..408513e5d7 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -35,6 +35,9 @@ public: float getEyeGazeRightPitch() const { return _eyeGazeRightPitch; } float getEyeGazeRightYaw() const { return _eyeGazeRightYaw; } + float getEstimatedEyePitch() const { return _estimatedEyePitch; } + float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } + float getLeftBlink() const { return _leftBlink; } float getRightBlink() const { return _rightBlink; } @@ -42,6 +45,7 @@ public: float getMouthSize() const { return _mouthSize; } + void update(); void reset(); public slots: @@ -85,6 +89,12 @@ private: float _mouthSize; int _jawOpenIndex; + + float _longTermAverageEyePitch; + float _longTermAverageEyeYaw; + + float _estimatedEyePitch; + float _estimatedEyeYaw; }; #endif /* defined(__interface__Faceshift__) */ From fe8fabee3830203f137bb6d7af734325b0fa9535 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 14:31:27 -0700 Subject: [PATCH 31/44] add a static method to the Logging class to change target name --- assignment-client/src/main.cpp | 19 +++++++++++-------- libraries/shared/src/Logging.cpp | 24 ++++++++++++++++++------ libraries/shared/src/Logging.h | 4 +++- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 9259e503e3..f375c74f69 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -61,18 +61,20 @@ void childClient() { if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { + // reset the logging target to the the CHILD_TARGET_NAME + Logging::setTargetName(CHILD_TARGET_NAME); + // construct the deployed assignment from the packet data Assignment deployedAssignment(packetData, receivedBytes); - Logging::standardizedLog(QString("Received an assignment - %1").arg(deployedAssignment.toString()), - CHILD_TARGET_NAME); + Logging::standardizedLog(QString("Received an assignment - %1").arg(deployedAssignment.toString())); // switch our nodelist DOMAIN_IP to the ip receieved in the assignment if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); - Logging::standardizedLog(QString("Changed Domain IP to %1").arg(inet_ntoa(domainSocketAddr)), CHILD_TARGET_NAME); + Logging::standardizedLog(QString("Changed Domain IP to %1").arg(inet_ntoa(domainSocketAddr))); } if (deployedAssignment.getType() == Assignment::AudioMixer) { @@ -81,8 +83,7 @@ void childClient() { AvatarMixer::run(); } - Logging::standardizedLog(QString("Assignment finished or never started - waiting for new assignment"), - CHILD_TARGET_NAME); + Logging::standardizedLog(QString("Assignment finished or never started - waiting for new assignment")); // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); @@ -118,8 +119,7 @@ void sigchldHandler(int sig) { // this is the parent, replace the dead process with the new one ::childForks[i] = newForkProcessID; - Logging::standardizedLog(QString("Repleaced dead %1 with new fork %2").arg(processID).arg(newForkProcessID), - PARENT_TARGET_NAME); + Logging::standardizedLog(QString("Replaced dead %1 with new fork %2").arg(processID).arg(newForkProcessID)); break; } @@ -154,6 +154,9 @@ int main(int argc, const char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); + // start the Logging class with the parent's target name + Logging::setTargetName(PARENT_TARGET_NAME); + // grab the overriden assignment-server hostname from argv, if it exists const char* customAssignmentServer = getCmdOption(argc, argv, "-a"); if (customAssignmentServer) { @@ -171,7 +174,7 @@ int main(int argc, const char* argv[]) { if (numForksString) { ::numForks = atoi(numForksString); - Logging::standardizedLog(QString("Starting %1 assignment clients").arg(numForks), PARENT_TARGET_NAME); + Logging::standardizedLog(QString("Starting %1 assignment clients").arg(numForks)); ::childForks = new pid_t[numForks]; diff --git a/libraries/shared/src/Logging.cpp b/libraries/shared/src/Logging.cpp index cb4c249620..7fb141eba9 100644 --- a/libraries/shared/src/Logging.cpp +++ b/libraries/shared/src/Logging.cpp @@ -16,6 +16,7 @@ #include "Logging.h" sockaddr_in Logging::logstashSocket = {}; +char* Logging::targetName = NULL; sockaddr* Logging::socket() { @@ -73,10 +74,19 @@ const QString& stringForLogType(Logging::Type logType) { } } +void Logging::setTargetName(const char* targetName) { + // remove the old target name, if it exists + delete Logging::targetName; + + // copy over the new target name + Logging::targetName = new char[strlen(targetName)]; + strcpy(Logging::targetName, targetName); +} + // the following will produce 2000-10-02 13:55:36 -0700 const char DATE_STRING_FORMAT[] = "%F %H:%M:%S %z"; -void Logging::standardizedLog(const QString &output, const char* targetName, Logging::Type logType) { +void Logging::standardizedLog(const QString &output, Logging::Type logType) { time_t rawTime; time(&rawTime); struct tm* localTime = localtime(&rawTime); @@ -84,23 +94,25 @@ void Logging::standardizedLog(const QString &output, const char* targetName, Log // log prefix is in the following format // [DEBUG] [TIMESTAMP] [PID:PARENT_PID] [TARGET] logged string - QString prefixString = QString("[%1] ").arg(stringForLogType(logType)); + QString prefixString = QString("[%1]").arg(stringForLogType(logType)); char dateString[100]; strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime); - prefixString.append(QString("[%1] ").arg(dateString)); + prefixString.append(QString(" [%1]").arg(dateString)); - prefixString.append(QString("[%1").arg(getpid())); + prefixString.append(QString(" [%1").arg(getpid())); pid_t parentProcessID = getppid(); if (parentProcessID != 0) { - prefixString.append(QString(":%1] ").arg(parentProcessID)); + prefixString.append(QString(":%1]").arg(parentProcessID)); } else { prefixString.append("]"); } - prefixString.append(QString("[%1]").arg(targetName)); + if (Logging::targetName) { + prefixString.append(QString(" [%1]").arg(Logging::targetName)); + } qDebug("%s %s", prefixString.toStdString().c_str(), output.toStdString().c_str()); } \ No newline at end of file diff --git a/libraries/shared/src/Logging.h b/libraries/shared/src/Logging.h index c8f12ac8b6..472063d84c 100644 --- a/libraries/shared/src/Logging.h +++ b/libraries/shared/src/Logging.h @@ -32,9 +32,11 @@ public: static sockaddr* socket(); static bool shouldSendStats(); static void stashValue(char statType, const char* key, float value); - static void standardizedLog(const QString& output, const char* targetName, Logging::Type logType = Logging::Debug); + static void setTargetName(const char* targetName); + static void standardizedLog(const QString& output, Logging::Type logType = Logging::Debug); private: static sockaddr_in logstashSocket; + static char* targetName; }; #endif /* defined(__hifi__Logstash__) */ From b0c9dfeddc3b598a88231430917d4ed84f009e79 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 14:47:15 -0700 Subject: [PATCH 32/44] more leveraging of standardized logging --- assignment-client/src/main.cpp | 9 +++++++-- libraries/audio/src/AudioMixer.cpp | 4 ++++ libraries/avatars/src/AvatarMixer.cpp | 6 ++++++ libraries/shared/src/Logging.cpp | 4 ++++ libraries/shared/src/Logging.h | 1 + libraries/shared/src/Node.cpp | 12 +++++++----- libraries/shared/src/Node.h | 2 ++ libraries/shared/src/NodeList.cpp | 16 ++++++++-------- libraries/shared/src/UDPSocket.cpp | 3 ++- 9 files changed, 41 insertions(+), 16 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index f375c74f69..896b69b274 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -32,6 +32,9 @@ int numForks = 0; void childClient() { // this is one of the child forks or there is a single assignment client, continue assignment-client execution + // set the logging target to the the CHILD_TARGET_NAME + Logging::setTargetName(CHILD_TARGET_NAME); + // create a NodeList as an unassigned client NodeList* nodeList = NodeList::createInstance(NODE_TYPE_UNASSIGNED); @@ -61,8 +64,7 @@ void childClient() { if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { - // reset the logging target to the the CHILD_TARGET_NAME - Logging::setTargetName(CHILD_TARGET_NAME); + // construct the deployed assignment from the packet data Assignment deployedAssignment(packetData, receivedBytes); @@ -88,6 +90,9 @@ void childClient() { // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); nodeList->clear(); + + // reset the logging target to the the CHILD_TARGET_NAME + Logging::setTargetName(CHILD_TARGET_NAME); } } } diff --git a/libraries/audio/src/AudioMixer.cpp b/libraries/audio/src/AudioMixer.cpp index b11aa9c14b..d4b6097134 100644 --- a/libraries/audio/src/AudioMixer.cpp +++ b/libraries/audio/src/AudioMixer.cpp @@ -57,6 +57,8 @@ const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PE const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); +const char AUDIO_MIXER_LOGGING_TARGET_NAME[] = "audio-mixer"; + void attachNewBufferToNode(Node *newNode) { if (!newNode->getLinkedData()) { if (newNode->getType() == NODE_TYPE_AGENT) { @@ -68,6 +70,8 @@ void attachNewBufferToNode(Node *newNode) { } void AudioMixer::run() { + // change the logging target name while this is running + Logging::setTargetName(AUDIO_MIXER_LOGGING_TARGET_NAME); NodeList *nodeList = NodeList::getInstance(); nodeList->setOwnerType(NODE_TYPE_AUDIO_MIXER); diff --git a/libraries/avatars/src/AvatarMixer.cpp b/libraries/avatars/src/AvatarMixer.cpp index 92e27a64af..acf77be8da 100644 --- a/libraries/avatars/src/AvatarMixer.cpp +++ b/libraries/avatars/src/AvatarMixer.cpp @@ -10,6 +10,7 @@ // The avatar mixer receives head, hand and positional data from all connected // nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms. +#include #include #include #include @@ -18,6 +19,8 @@ #include "AvatarMixer.h" +const char AVATAR_MIXER_LOGGING_NAME[] = "avatar-mixer"; + unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) { currentPosition += packNodeId(currentPosition, nodeToAdd->getNodeID()); @@ -81,6 +84,9 @@ void broadcastAvatarData(NodeList* nodeList, sockaddr* nodeAddress) { } void AvatarMixer::run() { + // change the logging target name while AvatarMixer is running + Logging::setTargetName(AVATAR_MIXER_LOGGING_NAME); + NodeList* nodeList = NodeList::getInstance(); nodeList->setOwnerType(NODE_TYPE_AVATAR_MIXER); diff --git a/libraries/shared/src/Logging.cpp b/libraries/shared/src/Logging.cpp index 7fb141eba9..9da64ec271 100644 --- a/libraries/shared/src/Logging.cpp +++ b/libraries/shared/src/Logging.cpp @@ -86,6 +86,10 @@ void Logging::setTargetName(const char* targetName) { // the following will produce 2000-10-02 13:55:36 -0700 const char DATE_STRING_FORMAT[] = "%F %H:%M:%S %z"; +void Logging::standardizedLog(const char *output, Logging::Type logType) { + standardizedLog(QString(output), logType); +} + void Logging::standardizedLog(const QString &output, Logging::Type logType) { time_t rawTime; time(&rawTime); diff --git a/libraries/shared/src/Logging.h b/libraries/shared/src/Logging.h index 472063d84c..705bad86b3 100644 --- a/libraries/shared/src/Logging.h +++ b/libraries/shared/src/Logging.h @@ -33,6 +33,7 @@ public: static bool shouldSendStats(); static void stashValue(char statType, const char* key, float value); static void setTargetName(const char* targetName); + static void standardizedLog(const char* output, Logging::Type logType = Logging::Debug); static void standardizedLog(const QString& output, Logging::Type logType = Logging::Debug); private: static sockaddr_in logstashSocket; diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index c91626d99d..09d8801068 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -144,14 +144,16 @@ float Node::getAverageKilobitsPerSecond() { } } -QDebug operator<<(QDebug debug, const Node &node) { +QString Node::toString() const { char publicAddressBuffer[16] = {'\0'}; - unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, node.getPublicSocket()); + unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, _publicSocket); //char localAddressBuffer[16] = {'\0'}; //unsigned short localAddressPort = loadBufferWithSocketInfo(localAddressBuffer, node.localSocket); - debug << "#" << node.getNodeID() << node.getTypeName() << node.getType(); - debug.nospace() << publicAddressBuffer << ":" << publicAddressPort; - return debug.nospace(); + return QString("# %1 %2 %3 %4:%5").arg(_nodeID).arg(getTypeName()).arg(_type).arg(publicAddressBuffer).arg(publicAddressPort); +} + +QDebug operator<<(QDebug debug, const Node &node) { + return debug << node.toString(); } diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index 2de75bcec1..d22d4e0076 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -72,6 +72,8 @@ public: void unlock() { pthread_mutex_unlock(&_mutex); } static void printLog(Node const&); + + QString toString() const; private: // privatize copy and assignment operator to disallow Node copying Node(const Node &otherNode); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 4d042b0f63..7b0bef7002 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -14,6 +14,7 @@ #include #include "Assignment.h" +#include "Logging.h" #include "NodeList.h" #include "NodeTypes.h" #include "PacketHeaders.h" @@ -43,7 +44,7 @@ NodeList* NodeList::createInstance(char ownerType, unsigned short int socketList if (!_sharedInstance) { _sharedInstance = new NodeList(ownerType, socketListenPort); } else { - qDebug("NodeList createInstance called with existing instance.\n"); + Logging::standardizedLog("NodeList createInstance called with existing instance."); } return _sharedInstance; @@ -51,7 +52,7 @@ NodeList* NodeList::createInstance(char ownerType, unsigned short int socketList NodeList* NodeList::getInstance() { if (!_sharedInstance) { - qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer.\n"); + Logging::standardizedLog("NodeList getInstance called before call to createInstance. Returning NULL pointer."); } return _sharedInstance; @@ -278,13 +279,12 @@ void NodeList::sendDomainServerCheckIn() { sockaddr_in tempAddress; memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr)); - - qDebug("Domain Server: %s\n", _domainHostname); + Logging::standardizedLog(QString("Domain Server: %1").arg(_domainHostname)); } else { - qDebug("Failed domain server lookup\n"); + Logging::standardizedLog("Failed domain server lookup", Logging::Warn); } } else if (!printedDomainServerIP) { - qDebug("Domain Server IP: %s\n", _domainIP); + Logging::standardizedLog(QString("Domain Server IP: %1").arg(_domainIP)); printedDomainServerIP = true; } @@ -460,7 +460,7 @@ void NodeList::addNodeToList(Node* newNode) { ++_numNodes; - qDebug() << "Added" << *newNode << "\n"; + Logging::standardizedLog(QString("Added %1").arg(newNode->toString())); notifyHooksOfAddedNode(newNode); } @@ -516,7 +516,7 @@ void* removeSilentNodes(void *args) { if ((checkTimeUSecs - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { - qDebug() << "Killed" << *node << "\n"; + Logging::standardizedLog(QString("Killed %1").arg(node->toString())); nodeList->notifyHooksOfKilledNode(&*node); diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index ab2460dd7f..f2f5129181 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -23,6 +23,7 @@ #include +#include "Logging.h" #include "UDPSocket.h" sockaddr_in destSockaddr, senderAddress; @@ -170,7 +171,7 @@ UDPSocket::UDPSocket(unsigned short int listeningPort) : const int DEFAULT_BLOCKING_SOCKET_TIMEOUT_USECS = 0.5 * 1000000; setBlockingReceiveTimeoutInUsecs(DEFAULT_BLOCKING_SOCKET_TIMEOUT_USECS); - qDebug("Created UDP socket listening on port %hu.\n", _listeningPort); + Logging::standardizedLog(QString("Created UDP Socket listening on %1").arg(_listeningPort)); } UDPSocket::~UDPSocket() { From 9a259ea618b1deecc15610dbf88fb7b5ea689a13 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 9 Sep 2013 15:51:52 -0600 Subject: [PATCH 33/44] Adding assignment-client to DSL --- jenkins/jobs.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/jenkins/jobs.groovy b/jenkins/jobs.groovy index 306ee030a8..7cab63d42d 100644 --- a/jenkins/jobs.groovy +++ b/jenkins/jobs.groovy @@ -102,6 +102,7 @@ static Closure cmakeBuild(srcDir, instCommand) { def targets = [ 'animation-server':true, 'assignment-server':true, + 'assignment-client':true, 'domain-server':true, 'eve':true, 'pairing-server':true, From 613334074f2c8d2e7c356b3c63ad4a4322afa1e6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 15:11:11 -0700 Subject: [PATCH 34/44] leverage qDebug and custom message handler for verbose logging --- assignment-client/src/main.cpp | 19 +++++++----- interface/src/Application.cpp | 4 +-- libraries/shared/src/Assignment.cpp | 6 +--- libraries/shared/src/Assignment.h | 2 -- libraries/shared/src/Logging.cpp | 46 +++++++++++++---------------- libraries/shared/src/Logging.h | 10 +------ libraries/shared/src/Node.cpp | 12 ++++---- libraries/shared/src/Node.h | 2 -- libraries/shared/src/NodeList.cpp | 14 ++++----- libraries/shared/src/UDPSocket.cpp | 2 +- 10 files changed, 49 insertions(+), 68 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 896b69b274..0579b8bb56 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -69,14 +69,14 @@ void childClient() { // construct the deployed assignment from the packet data Assignment deployedAssignment(packetData, receivedBytes); - Logging::standardizedLog(QString("Received an assignment - %1").arg(deployedAssignment.toString())); + qDebug() << "Received an assignment -" << deployedAssignment << "\n"; // switch our nodelist DOMAIN_IP to the ip receieved in the assignment if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); - Logging::standardizedLog(QString("Changed Domain IP to %1").arg(inet_ntoa(domainSocketAddr))); + qDebug("Changed Domain IP to %s\n", inet_ntoa(domainSocketAddr)); } if (deployedAssignment.getType() == Assignment::AudioMixer) { @@ -85,7 +85,7 @@ void childClient() { AvatarMixer::run(); } - Logging::standardizedLog(QString("Assignment finished or never started - waiting for new assignment")); + qDebug("Assignment finished or never started - waiting for new assignment\n"); // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NODE_TYPE_UNASSIGNED); @@ -124,7 +124,7 @@ void sigchldHandler(int sig) { // this is the parent, replace the dead process with the new one ::childForks[i] = newForkProcessID; - Logging::standardizedLog(QString("Replaced dead %1 with new fork %2").arg(processID).arg(newForkProcessID)); + qDebug("Replaced dead %d with new fork %d\n", processID, newForkProcessID); break; } @@ -159,6 +159,9 @@ int main(int argc, const char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); + // use the verbose message handler in Logging + qInstallMessageHandler(Logging::verboseMessageHandler); + // start the Logging class with the parent's target name Logging::setTargetName(PARENT_TARGET_NAME); @@ -179,12 +182,12 @@ int main(int argc, const char* argv[]) { if (numForksString) { ::numForks = atoi(numForksString); - Logging::standardizedLog(QString("Starting %1 assignment clients").arg(numForks)); + qDebug("Starting %d assignment clients\n", ::numForks); - ::childForks = new pid_t[numForks]; + ::childForks = new pid_t[::numForks]; // fire off as many children as we need (this is one less than the parent since the parent will run as well) - for (int i = 0; i < numForks; i++) { + for (int i = 0; i < ::numForks; i++) { processID = fork(); if (processID == 0) { @@ -197,7 +200,7 @@ int main(int argc, const char* argv[]) { } } - if (processID == 0 || numForks == 0) { + if (processID == 0 || ::numForks == 0) { childClient(); } else { parentMonitor(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ea61179057..7f055abe88 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -318,7 +318,7 @@ void Application::initializeGL() { const char LOGSTASH_INTERFACE_START_TIME_KEY[] = "interface-start-time"; // ask the Logstash class to record the startup time - Logstash::stashValue(STAT_TYPE_TIMER, LOGSTASH_INTERFACE_START_TIME_KEY, startupTime); + Logging::stashValue(STAT_TYPE_TIMER, LOGSTASH_INTERFACE_START_TIME_KEY, startupTime); } // update before the first render diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 867854030a..850922396f 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -130,11 +130,7 @@ int Assignment::packToBuffer(unsigned char* buffer) { return numPackedBytes; } -QString Assignment::toString() const { - return QString("T:%1 P:%2").arg(_type).arg(_pool); -} - QDebug operator<<(QDebug debug, const Assignment &assignment) { - debug << assignment.toString().toStdString().c_str(); + debug << "T:" << assignment.getType() << "P:" << assignment.getPool(); return debug.nospace(); } \ No newline at end of file diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 34cf065ce5..693cc42577 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -54,8 +54,6 @@ public: /// Sets _time to the current time given by gettimeofday void setCreateTimeToNow() { gettimeofday(&_time, NULL); } - QString toString() const; - private: Assignment::Direction _direction; /// the direction of the assignment (Create, Deploy, Request) Assignment::Type _type; /// the type of the assignment, defines what the assignee will do diff --git a/libraries/shared/src/Logging.cpp b/libraries/shared/src/Logging.cpp index 9da64ec271..bfdc3523f1 100644 --- a/libraries/shared/src/Logging.cpp +++ b/libraries/shared/src/Logging.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "SharedUtil.h" @@ -60,20 +61,6 @@ void Logging::stashValue(char statType, const char* key, float value) { } } -const QString DEBUG_STRING = "DEBUG"; -const QString WARN_STRING = "WARN"; -const QString ERROR_STRING = "ERROR"; - -const QString& stringForLogType(Logging::Type logType) { - if (logType == Logging::Debug) { - return DEBUG_STRING; - } else if (logType == Logging::Warn) { - return WARN_STRING; - } else { - return ERROR_STRING; - } -} - void Logging::setTargetName(const char* targetName) { // remove the old target name, if it exists delete Logging::targetName; @@ -83,22 +70,31 @@ void Logging::setTargetName(const char* targetName) { strcpy(Logging::targetName, targetName); } +const char* stringForLogType(QtMsgType msgType) { + switch (msgType) { + case QtDebugMsg: + return "DEBUG"; + case QtCriticalMsg: + return "CRITICAL"; + case QtFatalMsg: + return "FATAL"; + case QtWarningMsg: + return "WARNING"; + } +} + // the following will produce 2000-10-02 13:55:36 -0700 const char DATE_STRING_FORMAT[] = "%F %H:%M:%S %z"; -void Logging::standardizedLog(const char *output, Logging::Type logType) { - standardizedLog(QString(output), logType); -} - -void Logging::standardizedLog(const QString &output, Logging::Type logType) { - time_t rawTime; - time(&rawTime); - struct tm* localTime = localtime(&rawTime); - +void Logging::verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { // log prefix is in the following format // [DEBUG] [TIMESTAMP] [PID:PARENT_PID] [TARGET] logged string - QString prefixString = QString("[%1]").arg(stringForLogType(logType)); + QString prefixString = QString("[%1]").arg(stringForLogType(type)); + + time_t rawTime; + time(&rawTime); + struct tm* localTime = localtime(&rawTime); char dateString[100]; strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime); @@ -118,5 +114,5 @@ void Logging::standardizedLog(const QString &output, Logging::Type logType) { prefixString.append(QString(" [%1]").arg(Logging::targetName)); } - qDebug("%s %s", prefixString.toStdString().c_str(), output.toStdString().c_str()); + fprintf(stdout, "%s %s", prefixString.toLocal8Bit().constData(), message.toLocal8Bit().constData()); } \ No newline at end of file diff --git a/libraries/shared/src/Logging.h b/libraries/shared/src/Logging.h index 705bad86b3..0bd6197b9a 100644 --- a/libraries/shared/src/Logging.h +++ b/libraries/shared/src/Logging.h @@ -22,19 +22,11 @@ const char STAT_TYPE_GAUGE = 'g'; class Logging { public: - - enum Type { - Error, - Warn, - Debug - }; - static sockaddr* socket(); static bool shouldSendStats(); static void stashValue(char statType, const char* key, float value); static void setTargetName(const char* targetName); - static void standardizedLog(const char* output, Logging::Type logType = Logging::Debug); - static void standardizedLog(const QString& output, Logging::Type logType = Logging::Debug); + static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message); private: static sockaddr_in logstashSocket; static char* targetName; diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index 09d8801068..c91626d99d 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -144,16 +144,14 @@ float Node::getAverageKilobitsPerSecond() { } } -QString Node::toString() const { +QDebug operator<<(QDebug debug, const Node &node) { char publicAddressBuffer[16] = {'\0'}; - unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, _publicSocket); + unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, node.getPublicSocket()); //char localAddressBuffer[16] = {'\0'}; //unsigned short localAddressPort = loadBufferWithSocketInfo(localAddressBuffer, node.localSocket); - return QString("# %1 %2 %3 %4:%5").arg(_nodeID).arg(getTypeName()).arg(_type).arg(publicAddressBuffer).arg(publicAddressPort); -} - -QDebug operator<<(QDebug debug, const Node &node) { - return debug << node.toString(); + debug << "#" << node.getNodeID() << node.getTypeName() << node.getType(); + debug.nospace() << publicAddressBuffer << ":" << publicAddressPort; + return debug.nospace(); } diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index d22d4e0076..2de75bcec1 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -72,8 +72,6 @@ public: void unlock() { pthread_mutex_unlock(&_mutex); } static void printLog(Node const&); - - QString toString() const; private: // privatize copy and assignment operator to disallow Node copying Node(const Node &otherNode); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 7b0bef7002..3b16150a00 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -44,7 +44,7 @@ NodeList* NodeList::createInstance(char ownerType, unsigned short int socketList if (!_sharedInstance) { _sharedInstance = new NodeList(ownerType, socketListenPort); } else { - Logging::standardizedLog("NodeList createInstance called with existing instance."); + qDebug("NodeList createInstance called with existing instance."); } return _sharedInstance; @@ -52,7 +52,7 @@ NodeList* NodeList::createInstance(char ownerType, unsigned short int socketList NodeList* NodeList::getInstance() { if (!_sharedInstance) { - Logging::standardizedLog("NodeList getInstance called before call to createInstance. Returning NULL pointer."); + qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer."); } return _sharedInstance; @@ -279,12 +279,12 @@ void NodeList::sendDomainServerCheckIn() { sockaddr_in tempAddress; memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr)); - Logging::standardizedLog(QString("Domain Server: %1").arg(_domainHostname)); + qDebug("Domain Server: %s", _domainHostname); } else { - Logging::standardizedLog("Failed domain server lookup", Logging::Warn); + qDebug("Failed domain server lookup"); } } else if (!printedDomainServerIP) { - Logging::standardizedLog(QString("Domain Server IP: %1").arg(_domainIP)); + qDebug("Domain Server IP: %s", _domainIP); printedDomainServerIP = true; } @@ -460,7 +460,7 @@ void NodeList::addNodeToList(Node* newNode) { ++_numNodes; - Logging::standardizedLog(QString("Added %1").arg(newNode->toString())); + qDebug() << "Added" << *newNode << "\n"; notifyHooksOfAddedNode(newNode); } @@ -516,7 +516,7 @@ void* removeSilentNodes(void *args) { if ((checkTimeUSecs - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { - Logging::standardizedLog(QString("Killed %1").arg(node->toString())); + qDebug() << "Killed " << *node << "\n"; nodeList->notifyHooksOfKilledNode(&*node); diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index f2f5129181..d89265b471 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -171,7 +171,7 @@ UDPSocket::UDPSocket(unsigned short int listeningPort) : const int DEFAULT_BLOCKING_SOCKET_TIMEOUT_USECS = 0.5 * 1000000; setBlockingReceiveTimeoutInUsecs(DEFAULT_BLOCKING_SOCKET_TIMEOUT_USECS); - Logging::standardizedLog(QString("Created UDP Socket listening on %1").arg(_listeningPort)); + qDebug("Created UDP Socket listening on %hd\n", _listeningPort); } UDPSocket::~UDPSocket() { From bbc051a7641bbf5d6c6aa524cf7792bab7768d07 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 15:27:27 -0700 Subject: [PATCH 35/44] add doxygen comments to refactored Logging class --- libraries/shared/src/Logging.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libraries/shared/src/Logging.h b/libraries/shared/src/Logging.h index 0bd6197b9a..c4f921070a 100644 --- a/libraries/shared/src/Logging.h +++ b/libraries/shared/src/Logging.h @@ -20,12 +20,28 @@ const char STAT_TYPE_TIMER = 't'; const char STAT_TYPE_COUNTER = 'c'; const char STAT_TYPE_GAUGE = 'g'; +/// Handles custom message handling and sending of stats/logs to Logstash instance class Logging { public: + /// \return the socket used to send stats to logstash static sockaddr* socket(); + + /// checks if this target should send stats to logstash, given its current environment + /// \return true if the caller should send stats to logstash static bool shouldSendStats(); + + /// stashes a float value to Logstash instance + /// \param statType a stat type from the constants in this file + /// \param key the key at which to store the stat + /// \param value the value to store static void stashValue(char statType, const char* key, float value); + + /// sets the target name to output via the verboseMessageHandler, called once before logging begins + /// \param targetName the desired target name to output in logs static void setTargetName(const char* targetName); + + /// a qtMessageHandler that can be hooked up to a target that links to Qt + /// prints various process, message type, and time information static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message); private: static sockaddr_in logstashSocket; From 1c792cf46a0e1f189d03d4ba0743c6f725974649 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 15:35:28 -0700 Subject: [PATCH 36/44] some newline additions for logging in NodeList --- libraries/shared/src/NodeList.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 3b16150a00..a982e22242 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -279,12 +279,12 @@ void NodeList::sendDomainServerCheckIn() { sockaddr_in tempAddress; memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr)); - qDebug("Domain Server: %s", _domainHostname); + qDebug("Domain Server: %s\n", _domainHostname); } else { - qDebug("Failed domain server lookup"); + qDebug("Failed domain server lookup\n"); } } else if (!printedDomainServerIP) { - qDebug("Domain Server IP: %s", _domainIP); + qDebug("Domain Server IP: %s\n", _domainIP); printedDomainServerIP = true; } From 97803b827e520189be2ba64297ba27de75b8b712 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 16:45:44 -0700 Subject: [PATCH 37/44] pack destination socket for assignment as tightly as possible --- assignment-server/src/main.cpp | 2 +- libraries/shared/src/Assignment.cpp | 48 +++++++++++++---------------- libraries/shared/src/Assignment.h | 6 ++-- libraries/shared/src/UDPSocket.cpp | 2 +- libraries/shared/src/UDPSocket.h | 2 +- 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/assignment-server/src/main.cpp b/assignment-server/src/main.cpp index dbbd6b2607..d92ab46f63 100644 --- a/assignment-server/src/main.cpp +++ b/assignment-server/src/main.cpp @@ -99,7 +99,7 @@ int main(int argc, const char* argv[]) { // assignment server is on a public server // assume that the address we now have for the sender is the public address/port // and store that with the assignment so it can be given to the requestor later - createdAssignment->setDomainSocket((sockaddr*) &senderSocket); + createdAssignment->setDestinationSocket((sockaddr*) &senderSocket); // add this assignment to the queue assignmentQueue.push_back(createdAssignment); diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 850922396f..7151259b7c 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -17,7 +17,7 @@ Assignment::Assignment(Assignment::Direction direction, Assignment::Type type, c _direction(direction), _type(type), _pool(NULL), - _domainSocket(NULL) + _destinationSocket(NULL) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -34,7 +34,7 @@ Assignment::Assignment(Assignment::Direction direction, Assignment::Type type, c Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : _pool(NULL), - _domainSocket(NULL) + _destinationSocket(NULL) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -64,41 +64,39 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : } if (numBytes > numBytesRead) { + if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { // IPv4 address - sockaddr_in destinationSocket = {}; - memcpy(&destinationSocket, dataBuffer + numBytesRead, sizeof(sockaddr_in)); - destinationSocket.sin_family = AF_INET; - setDomainSocket((sockaddr*) &destinationSocket); + delete _destinationSocket; + _destinationSocket = (sockaddr*) new sockaddr_in; + unpackSocket(dataBuffer + numBytesRead, _destinationSocket); } else { - // IPv6 address - sockaddr_in6 destinationSocket = {}; - memcpy(&destinationSocket, dataBuffer + numBytesRead, sizeof(sockaddr_in6)); - setDomainSocket((sockaddr*) &destinationSocket); + // IPv6 address, or bad designator + qDebug("Received a socket that cannot be unpacked!\n"); } } } Assignment::~Assignment() { - delete _domainSocket; + delete _destinationSocket; delete _pool; } -void Assignment::setDomainSocket(const sockaddr* domainSocket) { +void Assignment::setDestinationSocket(const sockaddr* destinationSocket) { - if (_domainSocket) { + if (_destinationSocket) { // delete the old _domainSocket if it exists - delete _domainSocket; - _domainSocket = NULL; + delete _destinationSocket; + _destinationSocket = NULL; } // create a new sockaddr or sockaddr_in depending on what type of address this is - if (domainSocket->sa_family == AF_INET) { - _domainSocket = (sockaddr*) new sockaddr_in; - memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in)); + if (destinationSocket->sa_family == AF_INET) { + _destinationSocket = (sockaddr*) new sockaddr_in; + memcpy(_destinationSocket, destinationSocket, sizeof(sockaddr_in)); } else { - _domainSocket = (sockaddr*) new sockaddr_in6; - memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in6)); + _destinationSocket = (sockaddr*) new sockaddr_in6; + memcpy(_destinationSocket, destinationSocket, sizeof(sockaddr_in6)); } } @@ -118,13 +116,11 @@ int Assignment::packToBuffer(unsigned char* buffer) { numPackedBytes += sizeof(char); } - if (_domainSocket) { - buffer[numPackedBytes++] = (_domainSocket->sa_family == AF_INET) ? IPv4_ADDRESS_DESIGNATOR : IPv6_ADDRESS_DESIGNATOR; + if (_destinationSocket) { + buffer[numPackedBytes++] = (_destinationSocket->sa_family == AF_INET) + ? IPv4_ADDRESS_DESIGNATOR : IPv6_ADDRESS_DESIGNATOR; - int numSocketBytes = (_domainSocket->sa_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); - - memcpy(buffer + numPackedBytes, _domainSocket, numSocketBytes); - numPackedBytes += numSocketBytes; + numPackedBytes += packSocket(buffer + numPackedBytes, _destinationSocket); } return numPackedBytes; diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 693cc42577..de56b684b6 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -43,8 +43,8 @@ public: const char* getPool() const { return _pool; } const timeval& getTime() const { return _time; } - const sockaddr* getDomainSocket() { return _domainSocket; } - void setDomainSocket(const sockaddr* domainSocket); + const sockaddr* getDestinationSocket() { return _destinationSocket; } + void setDestinationSocket(const sockaddr* destinationSocket); /// Packs the assignment to the passed buffer /// \param buffer the buffer in which to pack the assignment @@ -58,7 +58,7 @@ private: Assignment::Direction _direction; /// the direction of the assignment (Create, Deploy, Request) Assignment::Type _type; /// the type of the assignment, defines what the assignee will do char* _pool; /// the pool this assignment is for/from - sockaddr* _domainSocket; /// pointer to socket for domain server that created assignment + sockaddr* _destinationSocket; /// pointer to destination socket for assignment timeval _time; /// time the assignment was created (set in constructor) }; diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index d89265b471..9ce9ba695c 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -68,7 +68,7 @@ int packSocket(unsigned char* packStore, sockaddr* socketToPack) { return packSocket(packStore, ((sockaddr_in*) socketToPack)->sin_addr.s_addr, ((sockaddr_in*) socketToPack)->sin_port); } -int unpackSocket(unsigned char* packedData, sockaddr* unpackDestSocket) { +int unpackSocket(const unsigned char* packedData, sockaddr* unpackDestSocket) { sockaddr_in* destinationSocket = (sockaddr_in*) unpackDestSocket; destinationSocket->sin_addr.s_addr = (packedData[0] << 24) + (packedData[1] << 16) + (packedData[2] << 8) + packedData[3]; destinationSocket->sin_port = (packedData[4] << 8) + packedData[5]; diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index 1b627dbd41..447d234ca5 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -44,7 +44,7 @@ private: bool socketMatch(const sockaddr* first, const sockaddr* second); int packSocket(unsigned char* packStore, in_addr_t inAddress, in_port_t networkOrderPort); int packSocket(unsigned char* packStore, sockaddr* socketToPack); -int unpackSocket(unsigned char* packedData, sockaddr* unpackDestSocket); +int unpackSocket(const unsigned char* packedData, sockaddr* unpackDestSocket); int getLocalAddress(); unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket); sockaddr_in socketForHostnameAndHostOrderPort(const char* hostname, unsigned short port = 0); From 93ca5278da424757eecec41169faa39d3cdf0f5a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 16:47:48 -0700 Subject: [PATCH 38/44] cleanup is assignment-client destination socket handling --- assignment-client/src/main.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 0579b8bb56..f5137aac39 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -64,25 +64,25 @@ void childClient() { if (nodeList->getNodeSocket()->receive(packetData, &receivedBytes) && packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) { - - // construct the deployed assignment from the packet data Assignment deployedAssignment(packetData, receivedBytes); qDebug() << "Received an assignment -" << deployedAssignment << "\n"; // switch our nodelist DOMAIN_IP to the ip receieved in the assignment - if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) { - in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr; + if (deployedAssignment.getDestinationSocket()->sa_family == AF_INET) { + in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDestinationSocket())->sin_addr; nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); - qDebug("Changed Domain IP to %s\n", inet_ntoa(domainSocketAddr)); - } - - if (deployedAssignment.getType() == Assignment::AudioMixer) { - AudioMixer::run(); + qDebug("Destination IP for assignment is %s\n", inet_ntoa(domainSocketAddr)); + + if (deployedAssignment.getType() == Assignment::AudioMixer) { + AudioMixer::run(); + } else { + AvatarMixer::run(); + } } else { - AvatarMixer::run(); + qDebug("Received a bad destination socket for assignment.\n"); } qDebug("Assignment finished or never started - waiting for new assignment\n"); From ac878c9c63c20f9ffa479967411dcf85483c9ccb Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Mon, 9 Sep 2013 16:53:31 -0700 Subject: [PATCH 39/44] 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; From e53807ca82b80b0e0f1d1c1e8bdea194ea9c4a23 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 17:29:33 -0700 Subject: [PATCH 40/44] store an attached local and public socket with assignment --- assignment-client/src/main.cpp | 4 +-- assignment-server/src/main.cpp | 6 ++-- libraries/shared/src/Assignment.cpp | 55 ++++++++++++++++++----------- libraries/shared/src/Assignment.h | 10 ++++-- libraries/shared/src/UDPSocket.cpp | 11 ++++++ libraries/shared/src/UDPSocket.h | 1 + 6 files changed, 58 insertions(+), 29 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index f5137aac39..96652318ed 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -70,8 +70,8 @@ void childClient() { qDebug() << "Received an assignment -" << deployedAssignment << "\n"; // switch our nodelist DOMAIN_IP to the ip receieved in the assignment - if (deployedAssignment.getDestinationSocket()->sa_family == AF_INET) { - in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDestinationSocket())->sin_addr; + if (deployedAssignment.getAttachedPublicSocket()->sa_family == AF_INET) { + in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getAttachedPublicSocket())->sin_addr; nodeList->setDomainIP(inet_ntoa(domainSocketAddr)); qDebug("Destination IP for assignment is %s\n", inet_ntoa(domainSocketAddr)); diff --git a/assignment-server/src/main.cpp b/assignment-server/src/main.cpp index d92ab46f63..764d68f879 100644 --- a/assignment-server/src/main.cpp +++ b/assignment-server/src/main.cpp @@ -96,10 +96,10 @@ int main(int argc, const char* argv[]) { qDebug() << "Received a created assignment:" << *createdAssignment; qDebug() << "Current queue size is" << assignmentQueue.size(); - // assignment server is on a public server + // assignment server is likely on a public server // assume that the address we now have for the sender is the public address/port - // and store that with the assignment so it can be given to the requestor later - createdAssignment->setDestinationSocket((sockaddr*) &senderSocket); + // and store that with the assignment so it can be given to the requestor later if necessary + createdAssignment->setAttachedPublicSocket((sockaddr*) &senderSocket); // add this assignment to the queue assignmentQueue.push_back(createdAssignment); diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 7151259b7c..5da675ced9 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -17,7 +17,8 @@ Assignment::Assignment(Assignment::Direction direction, Assignment::Type type, c _direction(direction), _type(type), _pool(NULL), - _destinationSocket(NULL) + _attachedPublicSocket(NULL), + _attachedLocalSocket(NULL) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -34,7 +35,8 @@ Assignment::Assignment(Assignment::Direction direction, Assignment::Type type, c Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : _pool(NULL), - _destinationSocket(NULL) + _attachedPublicSocket(NULL), + _attachedLocalSocket(NULL) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -65,11 +67,15 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : if (numBytes > numBytesRead) { + sockaddr* socketDestination = (_direction == Assignment::Create) + ? _attachedLocalSocket + : _attachedPublicSocket; + if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { // IPv4 address - delete _destinationSocket; - _destinationSocket = (sockaddr*) new sockaddr_in; - unpackSocket(dataBuffer + numBytesRead, _destinationSocket); + delete socketDestination; + socketDestination = (sockaddr*) new sockaddr_in; + unpackSocket(dataBuffer + numBytesRead, socketDestination); } else { // IPv6 address, or bad designator qDebug("Received a socket that cannot be unpacked!\n"); @@ -78,26 +84,30 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : } Assignment::~Assignment() { - delete _destinationSocket; + delete _attachedPublicSocket; + delete _attachedLocalSocket; delete _pool; } -void Assignment::setDestinationSocket(const sockaddr* destinationSocket) { +void Assignment::setAttachedPublicSocket(const sockaddr* attachedPublicSocket) { - if (_destinationSocket) { - // delete the old _domainSocket if it exists - delete _destinationSocket; - _destinationSocket = NULL; + if (_attachedPublicSocket) { + // delete the old socket if it exists + delete _attachedPublicSocket; + _attachedPublicSocket = NULL; } - // create a new sockaddr or sockaddr_in depending on what type of address this is - if (destinationSocket->sa_family == AF_INET) { - _destinationSocket = (sockaddr*) new sockaddr_in; - memcpy(_destinationSocket, destinationSocket, sizeof(sockaddr_in)); - } else { - _destinationSocket = (sockaddr*) new sockaddr_in6; - memcpy(_destinationSocket, destinationSocket, sizeof(sockaddr_in6)); + copySocketToEmptySocketPointer(_attachedPublicSocket, attachedPublicSocket); +} + +void Assignment::setAttachedLocalSocket(const sockaddr* attachedLocalSocket) { + if (_attachedLocalSocket) { + // delete the old socket if it exists + delete _attachedLocalSocket; + _attachedLocalSocket = NULL; } + + copySocketToEmptySocketPointer(_attachedLocalSocket, attachedLocalSocket); } int Assignment::packToBuffer(unsigned char* buffer) { @@ -116,11 +126,14 @@ int Assignment::packToBuffer(unsigned char* buffer) { numPackedBytes += sizeof(char); } - if (_destinationSocket) { - buffer[numPackedBytes++] = (_destinationSocket->sa_family == AF_INET) + if (_attachedPublicSocket || _attachedLocalSocket) { + sockaddr* socketToPack = (_attachedPublicSocket) ? _attachedPublicSocket : _attachedLocalSocket; + + // we have a socket to pack, add the designator + buffer[numPackedBytes++] = (socketToPack->sa_family == AF_INET) ? IPv4_ADDRESS_DESIGNATOR : IPv6_ADDRESS_DESIGNATOR; - numPackedBytes += packSocket(buffer + numPackedBytes, _destinationSocket); + numPackedBytes += packSocket(buffer + numPackedBytes, socketToPack); } return numPackedBytes; diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index de56b684b6..b72aafb67e 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -43,8 +43,11 @@ public: const char* getPool() const { return _pool; } const timeval& getTime() const { return _time; } - const sockaddr* getDestinationSocket() { return _destinationSocket; } - void setDestinationSocket(const sockaddr* destinationSocket); + const sockaddr* getAttachedPublicSocket() { return _attachedPublicSocket; } + void setAttachedPublicSocket(const sockaddr* attachedPublicSocket); + + const sockaddr* getAttachedLocalSocket() { return _attachedLocalSocket; } + void setAttachedLocalSocket(const sockaddr* attachedLocalSocket); /// Packs the assignment to the passed buffer /// \param buffer the buffer in which to pack the assignment @@ -58,7 +61,8 @@ private: Assignment::Direction _direction; /// the direction of the assignment (Create, Deploy, Request) Assignment::Type _type; /// the type of the assignment, defines what the assignee will do char* _pool; /// the pool this assignment is for/from - sockaddr* _destinationSocket; /// pointer to destination socket for assignment + sockaddr* _attachedPublicSocket; /// pointer to a public socket that relates to assignment, depends on direction + sockaddr* _attachedLocalSocket; /// pointer to a local socket that relates to assignment, depends on direction timeval _time; /// time the assignment was created (set in constructor) }; diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 9ce9ba695c..0405f83c85 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -75,6 +75,17 @@ int unpackSocket(const unsigned char* packedData, sockaddr* unpackDestSocket) { return 6; // this could be more if we ever need IPv6 } +void copySocketToEmptySocketPointer(sockaddr* destination, const sockaddr* source) { + // create a new sockaddr or sockaddr_in depending on what type of address this is + if (source->sa_family == AF_INET) { + destination = (sockaddr*) new sockaddr_in; + memcpy(destination, source, sizeof(sockaddr_in)); + } else { + destination = (sockaddr*) new sockaddr_in6; + memcpy(destination, source, sizeof(sockaddr_in6)); + } +} + int getLocalAddress() { // get this node's local address so we can pass that to DS struct ifaddrs* ifAddrStruct = NULL; diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index 447d234ca5..21b19920b2 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -45,6 +45,7 @@ bool socketMatch(const sockaddr* first, const sockaddr* second); int packSocket(unsigned char* packStore, in_addr_t inAddress, in_port_t networkOrderPort); int packSocket(unsigned char* packStore, sockaddr* socketToPack); int unpackSocket(const unsigned char* packedData, sockaddr* unpackDestSocket); +void copySocketToEmptySocketPointer(sockaddr* destination, const sockaddr* source); int getLocalAddress(); unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket); sockaddr_in socketForHostnameAndHostOrderPort(const char* hostname, unsigned short port = 0); From fa521a5dc99597ca7ad76a78c0483acf8b1eef3c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Sep 2013 18:15:33 -0700 Subject: [PATCH 41/44] handle case where AC is on same network as DS but not AS --- assignment-server/src/main.cpp | 9 +++++++++ domain-server/src/main.cpp | 8 ++++++++ libraries/shared/src/Assignment.cpp | 26 +++++++++++++++++--------- libraries/shared/src/UDPSocket.cpp | 11 ++++++----- libraries/shared/src/UDPSocket.h | 2 +- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/assignment-server/src/main.cpp b/assignment-server/src/main.cpp index 764d68f879..248b9fdc83 100644 --- a/assignment-server/src/main.cpp +++ b/assignment-server/src/main.cpp @@ -68,6 +68,15 @@ int main(int argc, const char* argv[]) { && strcmp((*assignment)->getPool(), requestAssignment.getPool()) == 0) || !eitherHasPool) { + // check if the requestor is on the same network as the destination for the assignment + if (senderSocket.sin_addr.s_addr == + ((sockaddr_in*) (*assignment)->getAttachedPublicSocket())->sin_addr.s_addr) { + // if this is the case we remove the public socket on the assignment by setting it to NULL + // this ensures the local IP and port sent to the requestor is the local address of destination + (*assignment)->setAttachedPublicSocket(NULL); + } + + int numAssignmentBytes = (*assignment)->packToBuffer(assignmentPacket + numSendHeaderBytes); // send the assignment diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 5739639f95..7b44648736 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -106,6 +106,12 @@ int main(int argc, const char* argv[]) { Assignment* audioAssignment = NULL; Assignment* avatarAssignment = NULL; + // construct a local socket to send with our created assignments + sockaddr_in localSocket = {}; + localSocket.sin_family = AF_INET; + localSocket.sin_port = htons(nodeList->getInstance()->getNodeSocket()->getListeningPort()); + localSocket.sin_addr.s_addr = serverLocalAddress; + while (true) { if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER)) { if (!audioAssignment @@ -113,6 +119,7 @@ int main(int argc, const char* argv[]) { if (!audioAssignment) { audioAssignment = new Assignment(Assignment::Create, Assignment::AudioMixer, assignmentPool); + audioAssignment->setAttachedLocalSocket((sockaddr*) &localSocket); } nodeList->sendAssignment(*audioAssignment); @@ -125,6 +132,7 @@ int main(int argc, const char* argv[]) { || usecTimestampNow() - usecTimestamp(&avatarAssignment->getTime()) >= ASSIGNMENT_SILENCE_MAX_USECS) { if (!avatarAssignment) { avatarAssignment = new Assignment(Assignment::Create, Assignment::AvatarMixer, assignmentPool); + avatarAssignment->setAttachedLocalSocket((sockaddr*) &localSocket); } nodeList->sendAssignment(*avatarAssignment); diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 5da675ced9..1f8ab1c388 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -67,19 +67,24 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : if (numBytes > numBytesRead) { - sockaddr* socketDestination = (_direction == Assignment::Create) - ? _attachedLocalSocket - : _attachedPublicSocket; + sockaddr* newSocket = NULL; if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) { // IPv4 address - delete socketDestination; - socketDestination = (sockaddr*) new sockaddr_in; - unpackSocket(dataBuffer + numBytesRead, socketDestination); + newSocket = (sockaddr*) new sockaddr_in; + unpackSocket(dataBuffer + numBytesRead, newSocket); } else { // IPv6 address, or bad designator qDebug("Received a socket that cannot be unpacked!\n"); } + + if (_direction == Assignment::Create) { + delete _attachedLocalSocket; + _attachedLocalSocket = newSocket; + } else { + delete _attachedPublicSocket; + _attachedPublicSocket = newSocket; + } } } @@ -90,14 +95,15 @@ Assignment::~Assignment() { } void Assignment::setAttachedPublicSocket(const sockaddr* attachedPublicSocket) { - if (_attachedPublicSocket) { // delete the old socket if it exists delete _attachedPublicSocket; _attachedPublicSocket = NULL; } - copySocketToEmptySocketPointer(_attachedPublicSocket, attachedPublicSocket); + if (attachedPublicSocket) { + copySocketToEmptySocketPointer(&_attachedPublicSocket, attachedPublicSocket); + } } void Assignment::setAttachedLocalSocket(const sockaddr* attachedLocalSocket) { @@ -107,7 +113,9 @@ void Assignment::setAttachedLocalSocket(const sockaddr* attachedLocalSocket) { _attachedLocalSocket = NULL; } - copySocketToEmptySocketPointer(_attachedLocalSocket, attachedLocalSocket); + if (attachedLocalSocket) { + copySocketToEmptySocketPointer(&_attachedLocalSocket, attachedLocalSocket); + } } int Assignment::packToBuffer(unsigned char* buffer) { diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 0405f83c85..11fd218a56 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -70,19 +70,20 @@ int packSocket(unsigned char* packStore, sockaddr* socketToPack) { int unpackSocket(const unsigned char* packedData, sockaddr* unpackDestSocket) { sockaddr_in* destinationSocket = (sockaddr_in*) unpackDestSocket; + destinationSocket->sin_family = AF_INET; destinationSocket->sin_addr.s_addr = (packedData[0] << 24) + (packedData[1] << 16) + (packedData[2] << 8) + packedData[3]; destinationSocket->sin_port = (packedData[4] << 8) + packedData[5]; return 6; // this could be more if we ever need IPv6 } -void copySocketToEmptySocketPointer(sockaddr* destination, const sockaddr* source) { +void copySocketToEmptySocketPointer(sockaddr** destination, const sockaddr* source) { // create a new sockaddr or sockaddr_in depending on what type of address this is if (source->sa_family == AF_INET) { - destination = (sockaddr*) new sockaddr_in; - memcpy(destination, source, sizeof(sockaddr_in)); + *destination = (sockaddr*) new sockaddr_in; + memcpy(*destination, source, sizeof(sockaddr_in)); } else { - destination = (sockaddr*) new sockaddr_in6; - memcpy(destination, source, sizeof(sockaddr_in6)); + *destination = (sockaddr*) new sockaddr_in6; + memcpy(*destination, source, sizeof(sockaddr_in6)); } } diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index 21b19920b2..d3f7cfac58 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -45,7 +45,7 @@ bool socketMatch(const sockaddr* first, const sockaddr* second); int packSocket(unsigned char* packStore, in_addr_t inAddress, in_port_t networkOrderPort); int packSocket(unsigned char* packStore, sockaddr* socketToPack); int unpackSocket(const unsigned char* packedData, sockaddr* unpackDestSocket); -void copySocketToEmptySocketPointer(sockaddr* destination, const sockaddr* source); +void copySocketToEmptySocketPointer(sockaddr** destination, const sockaddr* source); int getLocalAddress(); unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket); sockaddr_in socketForHostnameAndHostOrderPort(const char* hostname, unsigned short port = 0); From f41533fee6580a052f9169c7b978c716a3afc38d Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Mon, 9 Sep 2013 18:23:37 -0700 Subject: [PATCH 42/44] Add nudgeVoxel shading in grid. Fix erase bug. --- interface/src/Application.cpp | 7 +++++-- interface/src/Util.cpp | 9 +++++++++ libraries/voxels/src/VoxelTree.cpp | 3 +-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e2d857e94e..e14bfa7714 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1672,7 +1672,6 @@ void Application::update(float deltaTime) { _mouseVoxel.z += faceVector.z * _mouseVoxel.s; } } - _nudgeVoxel.s = _mouseVoxel.s; } else { _mouseVoxel.s = 0.0f; } @@ -2322,7 +2321,11 @@ void Application::displaySide(Camera& whichCamera) { _mouseVoxel.z + _mouseVoxel.s*0.5f); glLineWidth(4.0f); if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelNudgeMode)) { - glutWireCube(_nudgeVoxel.s); + if (_nudgeVoxel.s) { + glutWireCube(_nudgeVoxel.s); + } else { + glutWireCube(_mouseVoxel.s); + } } else { glutWireCube(_mouseVoxel.s); } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index c259379e15..05a68cc5a5 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -438,6 +438,15 @@ void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxe glVertex3f(origin.x + xz * voxelPrecision, 0, origin.z - (GRID_DIMENSIONS - 1) * voxelS); } glEnd(); + + glColor3f(1.0f,1.0f,1.0f); + + glBegin(GL_POLYGON);//begin drawing of square + glVertex3f(voxelX, 0.0f, voxelZ);//first vertex + glVertex3f(voxelX + voxelS, 0.0f, voxelZ);//second vertex + glVertex3f(voxelX + voxelS, 0.0f, voxelZ + voxelS);//third vertex + glVertex3f(voxelX, 0.0f, voxelZ + voxelS);//fourth vertex + glEnd();//end drawing of polygon } void renderNudgeGuide(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS) { diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index cec46998e7..3ca3ff90e6 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1907,7 +1907,6 @@ bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) { // 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 <= newLeafSize) { @@ -1957,7 +1956,7 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { // 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) { + if ((fabs(nudge.x) >= args->ancestorSize || fabs(nudge.y) >= args->ancestorSize || fabs(nudge.z) >= args->ancestorSize)) { args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); } From fb8c9dbfeaf30eb64d9d7419d5ee28dc2eadbc8e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 10 Sep 2013 09:58:42 -0700 Subject: [PATCH 43/44] fix spacing in Assignment --- libraries/shared/src/Assignment.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index b72aafb67e..11966b2dc7 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -61,7 +61,7 @@ private: Assignment::Direction _direction; /// the direction of the assignment (Create, Deploy, Request) Assignment::Type _type; /// the type of the assignment, defines what the assignee will do char* _pool; /// the pool this assignment is for/from - sockaddr* _attachedPublicSocket; /// pointer to a public socket that relates to assignment, depends on direction + sockaddr* _attachedPublicSocket; /// pointer to a public socket that relates to assignment, depends on direction sockaddr* _attachedLocalSocket; /// pointer to a local socket that relates to assignment, depends on direction timeval _time; /// time the assignment was created (set in constructor) }; From 3b464094d9113bff5a3f2a1ff866f34c02063098 Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Tue, 10 Sep 2013 11:09:50 -0700 Subject: [PATCH 44/44] Remove magic numbers, fix spacing, and other code clean up in nudge code. --- interface/src/Application.cpp | 2 +- interface/src/Util.cpp | 6 +++--- interface/src/Util.h | 4 ++-- interface/src/VoxelSystem.h | 1 - libraries/voxels/src/VoxelTree.cpp | 11 ++++------- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e14bfa7714..20889ab117 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1299,7 +1299,7 @@ void Application::nudgeVoxels() { VoxelNode* nodeToNudge = _voxels.getVoxelAt(_nudgeVoxel.x, _nudgeVoxel.y, _nudgeVoxel.z, _nudgeVoxel.s); if (nodeToNudge) { - _voxels.getVoxelTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender); + _voxels.getTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender); _finishedNudge = true; } } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 05a68cc5a5..8898ab9eab 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -414,7 +414,7 @@ void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, co glEnd(); } -void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS, const float& voxelPrecision) { +void renderNudgeGrid(float voxelX, float voxelY, float voxelZ, float voxelS, float voxelPrecision) { glm::vec3 origin = glm::vec3(voxelX, voxelY, voxelZ); glLineWidth(1.0); @@ -438,7 +438,7 @@ void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxe glVertex3f(origin.x + xz * voxelPrecision, 0, origin.z - (GRID_DIMENSIONS - 1) * voxelS); } glEnd(); - + glColor3f(1.0f,1.0f,1.0f); glBegin(GL_POLYGON);//begin drawing of square @@ -449,7 +449,7 @@ void renderNudgeGrid(const float& voxelX, const float& voxelY, const float& voxe glEnd();//end drawing of polygon } -void renderNudgeGuide(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS) { +void renderNudgeGuide(float voxelX, float voxelY, float voxelZ, float voxelS) { glm::vec3 origin = glm::vec3(voxelX, voxelY, voxelZ); glLineWidth(3.0); diff --git a/interface/src/Util.h b/interface/src/Util.h index 9401ca2e9a..3039ab1a31 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -61,9 +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, const float& voxelPrecision); +void renderNudgeGrid(float voxelX, float voxelY, float voxelZ, float voxelS, float voxelPrecision); -void renderNudgeGuide(const float& voxelX, const float& voxelY, const float& voxelZ, const float& voxelS); +void renderNudgeGuide(float voxelX, float voxelY, float voxelZ, float voxelS); void renderCollisionOverlay(int width, int height, float magnitude); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 45c0a5fee7..5ac5310b76 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -62,7 +62,6 @@ public: float getVoxelsCreatedPerSecondAverage(); float getVoxelsColoredPerSecondAverage(); float getVoxelsBytesReadPerSecondAverage(); - VoxelTree* getVoxelTree() {return _tree;} void killLocalVoxels(); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 3ca3ff90e6..2e4fbdf26e 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1864,8 +1864,6 @@ public: float ancestorSize; glm::vec3 nudgeVec; VoxelEditPacketSender* voxelEditSenderPtr; - - int colorIndex; }; float findNewLeafSize(const glm::vec3& nudgeAmount, float leafSize) { @@ -1949,14 +1947,14 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) { 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]; + voxelDetails.red = node->getColor()[RED_INDEX]; + voxelDetails.green = node->getColor()[GREEN_INDEX]; + voxelDetails.blue = node->getColor()[BLUE_INDEX]; 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)) { + if (fabs(nudge.x) >= args->ancestorSize || fabs(nudge.y) >= args->ancestorSize || fabs(nudge.z) >= args->ancestorSize) { args->voxelEditSenderPtr->sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxelDetails); } @@ -1986,7 +1984,6 @@ void VoxelTree::nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmoun args.ancestorSize = ancestorDetails.s; args.nudgeVec = nudgeAmount; args.voxelEditSenderPtr = &voxelEditSender; - args.colorIndex = 0; recurseNodeWithOperation(nodeToNudge, nudgeCheck, &args); }