From 14b7f58fef60052c1a8cac69d22a74568faf38aa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 5 Aug 2013 13:47:18 -0700 Subject: [PATCH 01/35] Kills local voxels if voxel server is removed from NodeList - added notification hooks to NodeList - implemented hooks in VoxelSystem to kill local voxels when voxel server is killed --- interface/src/Application.cpp | 7 +++++++ interface/src/Application.h | 1 + interface/src/VoxelSystem.cpp | 32 +++++++++++++++++++++++++++++-- interface/src/VoxelSystem.h | 5 ++++- libraries/shared/src/NodeList.cpp | 31 +++++++++++++++++++++++++++++- libraries/shared/src/NodeList.h | 16 ++++++++++++++++ 6 files changed, 88 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a3bd6c4718..2dfd51bc98 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -234,6 +234,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : NodeList::createInstance(NODE_TYPE_AGENT, listenPort); + NodeList::getInstance()->addHook(&_voxels); + + _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking"); if (!_enableNetworkThread) { NodeList::getInstance()->getNodeSocket()->setBlocking(false); @@ -317,6 +320,10 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : // initialization continues in initializeGL when OpenGL context is ready } +Application::~Application() { + NodeList::getInstance()->removeHook(&_voxels); +} + void Application::initializeGL() { qDebug( "Created Display Window.\n" ); diff --git a/interface/src/Application.h b/interface/src/Application.h index 4745196bf4..9a71365c5a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -66,6 +66,7 @@ public: static Application* getInstance() { return static_cast(QCoreApplication::instance()); } Application(int& argc, char** argv, timeval &startup_time); + ~Application(); void initializeGL(); void paintGL(); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 65d819eddc..72f1977ad6 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1553,10 +1553,38 @@ void VoxelSystem::falseColorizeOccludedV2() { VoxelProjectedPolygon::intersects_calls ); //myCoverageMapV2.erase(); - - _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } +void VoxelSystem::nodeAdded(Node* node) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + uint16_t nodeID = node->getNodeID(); + //printf("VoxelSystem... voxel server %u added...\n", nodeID); + } +} + +bool VoxelSystem::killSourceVoxelsOperation(VoxelNode* node, void* extraData) { + uint16_t killedNodeID = *(uint16_t*)extraData; + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + VoxelNode* childNode = node->getChildAtIndex(i); + if (childNode && childNode->getSourceID()== killedNodeID) { + node->safeDeepDeleteChildAtIndex(i); + } + } + return true; +} + +void VoxelSystem::nodeKilled(Node* node) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + uint16_t nodeID = node->getNodeID(); + //printf("VoxelSystem... voxel server %u removed...\n", nodeID); + + // Kill any voxels from the local tree + _tree->recurseTreeWithOperation(killSourceVoxelsOperation, &nodeID); + _tree->setDirtyBit(); + setupNewVoxelsForDrawing(); + } +} + diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 6c6bf261f9..5296d1a242 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -28,7 +28,7 @@ class ProgramObject; const int NUM_CHILDREN = 8; -class VoxelSystem : public NodeData, public VoxelNodeDeleteHook { +class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook { public: VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM); ~VoxelSystem(); @@ -99,6 +99,8 @@ public: CoverageMap myCoverageMap; virtual void nodeDeleted(VoxelNode* node); + virtual void nodeAdded(Node* node); + virtual void nodeKilled(Node* node); protected: float _treeScale; @@ -140,6 +142,7 @@ private: static bool falseColorizeSubTreeOperation(VoxelNode* node, void* extraData); static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData); static bool falseColorizeBySourceOperation(VoxelNode* node, void* extraData); + static bool killSourceVoxelsOperation(VoxelNode* node, void* extraData); int updateNodeInArraysAsFullVBO(VoxelNode* node); int updateNodeInArraysAsPartialVBO(VoxelNode* node); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 2dfd537d93..2ca07660e2 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -435,6 +435,8 @@ void NodeList::addNodeToList(Node* newNode) { ++_numNodes; qDebug() << "Added" << *newNode << "\n"; + + notifyHooksOfAddedNode(newNode); } unsigned NodeList::broadcastToNodes(unsigned char *broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes) { @@ -476,7 +478,7 @@ Node* NodeList::soloNodeOfType(char nodeType) { return NULL; } -void *removeSilentNodes(void *args) { +void* removeSilentNodes(void *args) { NodeList* nodeList = (NodeList*) args; uint64_t checkTimeUSecs; int sleepTime; @@ -490,6 +492,8 @@ void *removeSilentNodes(void *args) { qDebug() << "Killed" << *node << "\n"; + nodeList->notifyHooksOfKilledNode(&*node); + node->setAlive(false); } } @@ -619,3 +623,28 @@ void NodeListIterator::skipDeadAndStopIncrement() { } } } + +void NodeList::addHook(NodeListHook* hook) { + _hooks.push_back(hook); +} + +void NodeList::removeHook(NodeListHook* hook) { + for (int i = 0; i < _hooks.size(); i++) { + if (_hooks[i] == hook) { + _hooks.erase(_hooks.begin() + i); + return; + } + } +} + +void NodeList::notifyHooksOfAddedNode(Node* node) { + for (int i = 0; i < _hooks.size(); i++) { + _hooks[i]->nodeAdded(node); + } +} + +void NodeList::notifyHooksOfKilledNode(Node* node) { + for (int i = 0; i < _hooks.size(); i++) { + _hooks[i]->nodeKilled(node); + } +} diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 260fddf96f..804717dc66 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -45,6 +45,14 @@ const int UNKNOWN_NODE_ID = -1; class NodeListIterator; +// Callers who want to hook add/kill callbacks should implement this class +class NodeListHook { +public: + virtual void nodeAdded(Node* node) = 0; + virtual void nodeKilled(Node* node) = 0; +}; + + class NodeList { public: static NodeList* createInstance(char ownerType, unsigned int socketListenPort = NODE_SOCKET_LISTEN_PORT); @@ -111,6 +119,12 @@ public: void saveData(QSettings* settings); friend class NodeListIterator; + + void addHook(NodeListHook* hook); + void removeHook(NodeListHook* hook); + void notifyHooksOfAddedNode(Node* node); + void notifyHooksOfKilledNode(Node* node); + private: static NodeList* _sharedInstance; @@ -136,6 +150,8 @@ private: void handlePingReply(sockaddr *nodeAddress); void timePingReply(sockaddr *nodeAddress, unsigned char *packetData); + + std::vector _hooks; }; class NodeListIterator : public std::iterator { From 1c8c41463a2dcacf2a9e2abf36d92bcbb79f4b97 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 5 Aug 2013 15:02:03 -0700 Subject: [PATCH 02/35] fix compiler warning --- libraries/avatars/src/HandData.cpp | 4 ++++ libraries/avatars/src/HandData.h | 1 + 2 files changed, 5 insertions(+) diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index fb3d437489..8dbb3649ae 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -27,6 +27,10 @@ HandData::HandData(AvatarData* owningAvatar) : addNewPalm(); } +HandData::~HandData() { +} + + PalmData& HandData::addNewPalm() { _palms.push_back(PalmData(this)); return _palms.back(); diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index c280a7840f..b665c34c53 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -44,6 +44,7 @@ enum RaveGloveEffectsMode class HandData { public: HandData(AvatarData* owningAvatar); + virtual ~HandData(); // These methods return the positions in Leap-relative space. // To convert to world coordinates, use Hand::leapPositionToWorldPosition. From 7a3d254acadaf3b058527765adc06f01e40a70a1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 5 Aug 2013 15:02:24 -0700 Subject: [PATCH 03/35] small tweak --- interface/src/VoxelSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 72f1977ad6..11d4f10586 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1560,7 +1560,7 @@ void VoxelSystem::falseColorizeOccludedV2() { void VoxelSystem::nodeAdded(Node* node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { uint16_t nodeID = node->getNodeID(); - //printf("VoxelSystem... voxel server %u added...\n", nodeID); + printf("VoxelSystem... voxel server %u added...\n", nodeID); } } From f51db292a47f8c0d1a3395318dbccd651a6d4db6 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 5 Aug 2013 16:26:32 -0700 Subject: [PATCH 04/35] ya --- 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 f4b9b0999a..7f7e0f67ab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2562,7 +2562,7 @@ void Application::update(float deltaTime) { if (_renderParticleSystemOn->isChecked()) { updateParticleSystem(deltaTime); - } + } } void Application::updateAvatar(float deltaTime) { From 01ba5ee81ab449361bdd5f2e910ee6484c73fb5b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 5 Aug 2013 16:30:08 -0700 Subject: [PATCH 05/35] adding jurisdiction to scene stats to implement add/drop effect, added command line to voxel server to not send environments --- libraries/shared/src/PacketHeaders.cpp | 4 ++- libraries/voxels/src/JurisdictionMap.h | 2 ++ libraries/voxels/src/VoxelSceneStats.cpp | 31 +++++++++++++++++++++++- libraries/voxels/src/VoxelSceneStats.h | 5 +++- voxel-server/src/main.cpp | 14 +++++++++-- 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 99c887614c..04b13c8ccd 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -24,7 +24,9 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { case PACKET_TYPE_AVATAR_FACE_VIDEO: return 1; - + + case PACKET_TYPE_VOXEL_STATS: + return 1; default: return 0; } diff --git a/libraries/voxels/src/JurisdictionMap.h b/libraries/voxels/src/JurisdictionMap.h index 6c7cc4f0ca..59e08e85e9 100644 --- a/libraries/voxels/src/JurisdictionMap.h +++ b/libraries/voxels/src/JurisdictionMap.h @@ -30,6 +30,8 @@ public: bool writeToFile(const char* filename); bool readFromFile(const char* filename); + + unsigned char* getRootOctalCode() const { return _rootOctalCode; } private: void clear(); diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 9dd696eaa6..96bedcf2b1 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -22,9 +22,10 @@ VoxelSceneStats::VoxelSceneStats() : reset(); _isReadyToSend = false; _isStarted = false; + _jurisdictionRoot = NULL; } -void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* root) { +void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* root, JurisdictionMap* jurisdictionMap) { reset(); // resets packet and voxel stats _isStarted = true; _start = usecTimestampNow(); @@ -34,6 +35,7 @@ void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* r _isFullScene = isFullScene; _isMoving = isMoving; + _jurisdictionRoot = jurisdictionMap->getRootOctalCode(); } void VoxelSceneStats::sceneCompleted() { @@ -273,6 +275,20 @@ int VoxelSceneStats::packIntoMessage(unsigned char* destinationBuffer, int avail destinationBuffer += sizeof(_existsInPacketBitsWritten); memcpy(destinationBuffer, &_treesRemoved, sizeof(_treesRemoved)); destinationBuffer += sizeof(_treesRemoved); + + // add the root jurisdiction + if (_jurisdictionRoot) { + // copy the + int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_jurisdictionRoot)); + memcpy(destinationBuffer, &bytes, sizeof(bytes)); + destinationBuffer += sizeof(bytes); + memcpy(destinationBuffer, _jurisdictionRoot, bytes); + destinationBuffer += bytes; + } else { + int bytes = 0; + memcpy(destinationBuffer, &bytes, sizeof(bytes)); + destinationBuffer += sizeof(bytes); + } return destinationBuffer - bufferStart; // includes header! } @@ -363,6 +379,19 @@ int VoxelSceneStats::unpackFromMessage(unsigned char* sourceBuffer, int availabl sourceBuffer += sizeof(_existsInPacketBitsWritten); memcpy(&_treesRemoved, sourceBuffer, sizeof(_treesRemoved)); sourceBuffer += sizeof(_treesRemoved); + + // read the root jurisdiction + int bytes = 0; + memcpy(&bytes, sourceBuffer, sizeof(bytes)); + sourceBuffer += sizeof(bytes); + + if (bytes == 0) { + _jurisdictionRoot = NULL; + } else { + _jurisdictionRoot = new unsigned char[bytes]; + memcpy(_jurisdictionRoot, sourceBuffer, bytes); + sourceBuffer += bytes; + } // running averages _elapsedAverage.updateAverage((float)_elapsed); diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index ded2061a6e..a2ea4a0f40 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -12,6 +12,7 @@ #include #include +#include "JurisdictionMap.h" class VoxelNode; @@ -19,7 +20,7 @@ class VoxelSceneStats { public: VoxelSceneStats(); void reset(); - void sceneStarted(bool fullScene, bool moving, VoxelNode* root); + void sceneStarted(bool fullScene, bool moving, VoxelNode* root, JurisdictionMap* jurisdictionMap); void sceneCompleted(); void printDebugDetails(); @@ -165,6 +166,8 @@ private: static ItemInfo _ITEMS[]; static int const MAX_ITEM_VALUE_LENGTH = 128; char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH]; + + unsigned char* _jurisdictionRoot; }; #endif /* defined(__hifi__VoxelSceneStats__) */ diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 5d7489135a..4b44ec3a59 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -64,6 +64,7 @@ bool debugVoxelSending = false; bool shouldShowAnimationDebug = false; bool displayVoxelStats = false; bool debugVoxelReceiving = false; +bool sendEnvironments = true; EnvironmentData environmentData[3]; @@ -255,7 +256,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, // start tracking our stats bool isFullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging(); - nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, ::serverTree.rootNode); + nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, ::serverTree.rootNode, ::jurisdiction); } // If we have something in our nodeBag, then turn them into packets and send them out... @@ -265,7 +266,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, int packetsSentThisInterval = 0; uint64_t start = usecTimestampNow(); - bool shouldSendEnvironments = shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); + bool shouldSendEnvironments = ::sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) { // Check to see if we're taking too long, and if so bail early... uint64_t now = usecTimestampNow(); @@ -473,6 +474,15 @@ int main(int argc, const char * argv[]) { jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); } } + + // should we send environments? Default is yes, but this command line suppresses sending + const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; + bool dontSendEnvironments = cmdOptionExists(argc, argv, DONT_SEND_ENVIRONMENTS); + if (dontSendEnvironments) { + printf("Sending environments suppressed...\n"); + ::sendEnvironments = false; + } + printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); setvbuf(stdout, NULL, _IOLBF, 0); From acd3acb81e3dbdc1e3ecb617579fed01cbb978af Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 5 Aug 2013 16:51:01 -0700 Subject: [PATCH 06/35] correctly handle freeing of memory for _jurisdictionRoot in VoxelSceneStats --- interface/src/Application.cpp | 9 ++++++++- interface/src/Application.h | 1 + libraries/voxels/src/VoxelSceneStats.cpp | 21 ++++++++++++++++++++- libraries/voxels/src/VoxelSceneStats.h | 1 + 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3cef3f9e43..9a97fe7f45 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3820,6 +3820,12 @@ void Application::attachNewHeadToNode(Node* newNode) { } } +int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLength, sockaddr senderAddress) { + //Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress); + int statsMessageLength = _voxelSceneStats.unpackFromMessage(messageData, messageLength); + return statsMessageLength; +} + // Receive packets from other nodes/servers and decide what to do with them! void* Application::networkReceive(void* args) { sockaddr senderAddress; @@ -3863,7 +3869,8 @@ void* Application::networkReceive(void* args) { // immediately following them inside the same packet. So, we process the PACKET_TYPE_VOXEL_STATS first // then process any remaining bytes as if it was another packet if (messageData[0] == PACKET_TYPE_VOXEL_STATS) { - int statsMessageLength = app->_voxelSceneStats.unpackFromMessage(messageData, messageLength); + + int statsMessageLength = app->parseVoxelStats(messageData, messageLength, senderAddress); if (messageLength > statsMessageLength) { messageData += statsMessageLength; messageLength -= statsMessageLength; diff --git a/interface/src/Application.h b/interface/src/Application.h index e7ee18c2df..450d7ce3d2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -445,6 +445,7 @@ private: PieMenu _pieMenu; VoxelSceneStats _voxelSceneStats; + int parseVoxelStats(unsigned char* messageData, ssize_t messageLength, sockaddr senderAddress); }; #endif /* defined(__interface__Application__) */ diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 96bedcf2b1..d525725371 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -25,6 +25,13 @@ VoxelSceneStats::VoxelSceneStats() : _jurisdictionRoot = NULL; } +VoxelSceneStats::~VoxelSceneStats() { + if (_jurisdictionRoot) { + delete[] _jurisdictionRoot; + } +} + + void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* root, JurisdictionMap* jurisdictionMap) { reset(); // resets packet and voxel stats _isStarted = true; @@ -35,7 +42,19 @@ void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* r _isFullScene = isFullScene; _isMoving = isMoving; - _jurisdictionRoot = jurisdictionMap->getRootOctalCode(); + + if (_jurisdictionRoot) { + delete[] _jurisdictionRoot; + _jurisdictionRoot = NULL; + } + if (jurisdictionMap) { + unsigned char* jurisdictionRoot = jurisdictionMap->getRootOctalCode(); + if (jurisdictionRoot) { + int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(jurisdictionRoot)); + _jurisdictionRoot = new unsigned char[bytes]; + memcpy(_jurisdictionRoot, jurisdictionRoot, bytes); + } + } } void VoxelSceneStats::sceneCompleted() { diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index a2ea4a0f40..ac7c45a060 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -19,6 +19,7 @@ class VoxelNode; class VoxelSceneStats { public: VoxelSceneStats(); + ~VoxelSceneStats(); void reset(); void sceneStarted(bool fullScene, bool moving, VoxelNode* root, JurisdictionMap* jurisdictionMap); void sceneCompleted(); From 4ceba28632f44d1759bcd4b9658c06f858300a62 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 5 Aug 2013 17:00:50 -0700 Subject: [PATCH 07/35] working with Eric to fix transmission of hand data --- interface/src/avatar/Hand.cpp | 34 ++++++++++++++++++++++++---------- interface/src/avatar/Hand.h | 5 ++++- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index bf09096d7f..95128ec007 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -42,6 +42,9 @@ void Hand::init() { else { _ballColor = glm::vec3(0.0, 0.0, 0.4); } + + _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_NULL; + _raveGloveEffectsModeChanged = false; } void Hand::reset() { @@ -51,6 +54,14 @@ void Hand::reset() { void Hand::simulate(float deltaTime, bool isMine) { if (_isRaveGloveActive) { + if (_raveGloveEffectsModeChanged) { + + printf( "_raveGloveEffectsMode = %d\n", _raveGloveEffectsMode); + + setRaveGloveMode(_raveGloveEffectsMode); + _raveGloveEffectsModeChanged = false; + } + updateRaveGloveParticles(deltaTime); } } @@ -106,18 +117,21 @@ void Hand::calculateGeometry() { } void Hand::setRaveGloveEffectsMode(QKeyEvent* event) { + + _raveGloveEffectsModeChanged = true; + switch (event->key()) { - case Qt::Key_0: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR); break; - case Qt::Key_1: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_TRAILS ); break; - case Qt::Key_2: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FIRE ); break; - case Qt::Key_3: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_WATER ); break; - case Qt::Key_4: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FLASHY ); break; - case Qt::Key_5: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER ); break; - case Qt::Key_6: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER ); break; - case Qt::Key_7: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_SNAKE ); break; - case Qt::Key_8: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_PULSE ); break; - case Qt::Key_9: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROB ); break; + case Qt::Key_0: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR; break; + case Qt::Key_1: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_TRAILS; break; + case Qt::Key_2: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_FIRE; break; + case Qt::Key_3: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_WATER; break; + case Qt::Key_4: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_FLASHY; break; + case Qt::Key_5: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER; break; + case Qt::Key_6: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER; break; + case Qt::Key_7: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_SNAKE; break; + case Qt::Key_8: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_PULSE; break; + case Qt::Key_9: _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_THROB; break; }; } diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 39845141aa..6df97ea106 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -60,6 +60,8 @@ private: float _raveGloveClock; bool _raveGloveInitialized; int _raveGloveEmitter[NUM_FINGERS]; + int _raveGloveEffectsMode; + bool _raveGloveEffectsModeChanged; Avatar* _owningAvatar; float _renderAlpha; @@ -72,8 +74,9 @@ private: void setLeapHands(const std::vector& handPositions, const std::vector& handNormals); - void renderRaveGloveStage(); virtual void setRaveGloveMode(int mode); + + void renderRaveGloveStage(); void renderLeapHandSpheres(); void renderLeapHands(); void renderLeapHand(PalmData& hand); From cba42808c135a3c9d389b74bf201c80fd640c59c Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 5 Aug 2013 17:24:31 -0700 Subject: [PATCH 08/35] fixed initial rave glove mode --- interface/src/avatar/Hand.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 95128ec007..c78b42fcea 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -43,7 +43,7 @@ void Hand::init() { _ballColor = glm::vec3(0.0, 0.0, 0.4); } - _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_NULL; + _raveGloveEffectsMode = RAVE_GLOVE_EFFECTS_MODE_FIRE; _raveGloveEffectsModeChanged = false; } @@ -362,7 +362,6 @@ void Hand::updateRaveGloveParticles(float deltaTime) { } - void Hand::setRaveGloveMode(int mode) { _raveGloveMode = mode; From d85ce813135f6f9b28f856dc711026d73ca5e600 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Mon, 5 Aug 2013 17:27:42 -0700 Subject: [PATCH 09/35] Rave glove demo: network-glove fixes After this change, people can see each other's rave glove performances. 1. Moved hand->simulate call into avatar->simulate so that it gets called on all avatars, not just mine. 2. Hide the rave stage, so it's out of the way while we figure out the best way to darken the world, if that's still desired. --- interface/src/Application.cpp | 2 -- interface/src/avatar/Avatar.cpp | 2 ++ interface/src/avatar/Hand.cpp | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6087a4493e..8cfeaf3327 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2446,8 +2446,6 @@ void Application::update(float deltaTime) { _myAvatar.simulate(deltaTime, NULL); } - _myAvatar.getHand().simulate(deltaTime, true); - if (!OculusManager::isConnected()) { if (_lookingInMirror->isChecked()) { if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 346d5ff7d5..065501f39a 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -741,6 +741,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); _head.simulate(deltaTime, isMyAvatar()); + _hand.simulate(deltaTime, isMyAvatar()); + diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 7b74a1b7d8..bb941c9beb 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -129,7 +129,8 @@ void Hand::render(bool lookingInMirror) { calculateGeometry(); if (_isRaveGloveActive) { - renderRaveGloveStage(); + // Disable raveGloveStage while we work on the network glove features + // renderRaveGloveStage(); if (_raveGloveInitialized) { updateRaveGloveEmitters(); // do this after calculateGeometry From f9f925b70b9e4021451f05ac0e6f3e28ec631142 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 5 Aug 2013 17:30:04 -0700 Subject: [PATCH 10/35] removed printf --- interface/src/avatar/Hand.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index c78b42fcea..0e12b8c2b5 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -55,9 +55,6 @@ void Hand::simulate(float deltaTime, bool isMine) { if (_isRaveGloveActive) { if (_raveGloveEffectsModeChanged) { - - printf( "_raveGloveEffectsMode = %d\n", _raveGloveEffectsMode); - setRaveGloveMode(_raveGloveEffectsMode); _raveGloveEffectsModeChanged = false; } From 16aae5993ab64c430e6fdd9763b55d5472da2df8 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Tue, 6 Aug 2013 07:33:18 -0700 Subject: [PATCH 11/35] Rave glove fixes: removed double-stored glove mode members Uncommented glove mode switch, which now calls a non-crashing method. Fixed overlapping method names for very different methods (setRaveGloveMode becomes activateNewRaveGloveMode). --- interface/src/avatar/Hand.cpp | 10 +++++----- interface/src/avatar/Hand.h | 4 +--- libraries/avatars/src/HandData.cpp | 13 ++++++++++--- libraries/avatars/src/HandData.h | 7 ++++--- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 4043f1e42f..e445f89472 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -55,7 +55,7 @@ void Hand::simulate(float deltaTime, bool isMine) { if (_isRaveGloveActive) { if (_raveGloveEffectsModeChanged) { - setRaveGloveMode(_raveGloveEffectsMode); + activateNewRaveGloveMode(); _raveGloveEffectsModeChanged = false; } @@ -352,6 +352,7 @@ void Hand::updateRaveGloveParticles(float deltaTime) { } setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FIRE); + activateNewRaveGloveMode(); _raveGloveParticleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f)); _raveGloveInitialized = true; } else { @@ -359,11 +360,10 @@ void Hand::updateRaveGloveParticles(float deltaTime) { } } +// The rave glove mode has changed, so activate the effects. +void Hand::activateNewRaveGloveMode() { -void Hand::setRaveGloveMode(int mode) { - - _raveGloveMode = mode; - + int mode = _raveGloveEffectsMode; _raveGloveParticleSystem.killAllParticles(); for ( int f = 0; f< NUM_FINGERS; f ++ ) { diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 6df97ea106..d2a36b97b1 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -60,8 +60,6 @@ private: float _raveGloveClock; bool _raveGloveInitialized; int _raveGloveEmitter[NUM_FINGERS]; - int _raveGloveEffectsMode; - bool _raveGloveEffectsModeChanged; Avatar* _owningAvatar; float _renderAlpha; @@ -74,7 +72,7 @@ private: void setLeapHands(const std::vector& handPositions, const std::vector& handNormals); - virtual void setRaveGloveMode(int mode); + void activateNewRaveGloveMode(); void renderRaveGloveStage(); void renderLeapHandSpheres(); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 644a0764b7..e8e623decd 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -20,7 +20,8 @@ HandData::HandData(AvatarData* owningAvatar) : _baseOrientation(0.0f, 0.0f, 0.0f, 1.0f), _owningAvatarData(owningAvatar), _isRaveGloveActive(false), - _raveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR) + _raveGloveEffectsMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR), + _raveGloveEffectsModeChanged(false) { // Start with two palms addNewPalm(); @@ -160,8 +161,7 @@ int HandData::decodeRemoteData(unsigned char* sourceBuffer) { } setRaveGloveActive((gloveFlags & GLOVE_FLAG_RAVE) != 0); -// This is disabled for crash tracing. -// setRaveGloveMode(effectsMode); + setRaveGloveMode(effectsMode); // One byte for error checking safety. unsigned char requiredLength = (unsigned char)(sourceBuffer - startPosition); @@ -171,6 +171,13 @@ int HandData::decodeRemoteData(unsigned char* sourceBuffer) { return sourceBuffer - startPosition; } +void HandData::setRaveGloveMode(int effectsMode) +{ + if (effectsMode != _raveGloveEffectsMode) + _raveGloveEffectsModeChanged = true; + _raveGloveEffectsMode = effectsMode; +} + void HandData::setFingerTrailLength(unsigned int length) { for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index fd820bccc0..c871c568bb 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -70,9 +70,9 @@ public: int decodeRemoteData(unsigned char* sourceBuffer); void setRaveGloveActive(bool active) { _isRaveGloveActive = active; } - virtual void setRaveGloveMode(int effectsMode) { _raveGloveMode = effectsMode; } + void setRaveGloveMode(int effectsMode); bool isRaveGloveActive() const { return _isRaveGloveActive; } - int getRaveGloveMode() { return _raveGloveMode; } + int getRaveGloveMode() { return _raveGloveEffectsMode; } friend class AvatarData; protected: @@ -81,7 +81,8 @@ protected: AvatarData* _owningAvatarData; std::vector _palms; bool _isRaveGloveActive; - int _raveGloveMode; + int _raveGloveEffectsMode; + bool _raveGloveEffectsModeChanged; private: // privatize copy ctor and assignment operator so copies of this object cannot be made HandData(const HandData&); From 58cb85259702aa0bd25dba1f017ebde59463fe6e Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 6 Aug 2013 10:06:40 -0700 Subject: [PATCH 12/35] Touch-driven pitch happens immediately even when wearing gyros --- interface/src/Application.cpp | 1 - interface/src/avatar/Avatar.cpp | 7 +++---- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/Head.cpp | 3 ++- interface/src/avatar/Head.h | 3 +++ 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 66f414d38d..5efe365a49 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2587,7 +2587,6 @@ void Application::updateAvatar(float deltaTime) { glm::vec3(_headCameraPitchYawScale, _headCameraPitchYawScale, _headCameraPitchYawScale), - 0.f, _pitchFromTouch); if (_serialHeadSensor.isActive()) { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index cfb39d2e54..0b6484c8a7 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -295,8 +295,8 @@ void Avatar::reset() { // Update avatar head rotation with sensor data void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngle, - float yawFromTouch, float pitchFromTouch) { + _head.setMousePitch(pitchFromTouch); SerialInterface* gyros = Application::getInstance()->getSerialHeadSensor(); Webcam* webcam = Application::getInstance()->getWebcam(); glm::vec3 estimatedPosition, estimatedRotation; @@ -308,7 +308,6 @@ void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, } else { _head.setPitch(pitchFromTouch); - _head.setYaw(yawFromTouch); return; } if (webcam->isActive()) { @@ -334,8 +333,8 @@ void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, } else { _head.getFace().clearFrame(); } - _head.setPitch(estimatedRotation.x * amplifyAngle.x + pitchFromTouch); - _head.setYaw(estimatedRotation.y * amplifyAngle.y + yawFromTouch); + _head.setPitch(estimatedRotation.x * amplifyAngle.x); + _head.setYaw(estimatedRotation.y * amplifyAngle.y); _head.setRoll(estimatedRotation.z * amplifyAngle.z); _head.setCameraFollowsHead(gyroLook); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b490429ec9..ca41bdcb32 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -124,7 +124,6 @@ public: void follow(Avatar* leadingAvatar); void updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngle, - float yawFromTouch, float pitchFromTouch); void addBodyYaw(float bodyYaw) {_bodyYaw += bodyYaw;}; void addBodyYawDelta(float bodyYawDelta) {_bodyYawDelta += bodyYawDelta;} diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b88802b7f1..40ed309097 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -84,6 +84,7 @@ Head::Head(Avatar* owningAvatar) : _rightEyeBlinkVelocity(0.0f), _timeWithoutTalking(0.0f), _cameraPitch(_pitch), + _mousePitch(0.f), _cameraYaw(_yaw), _isCameraMoving(false), _cameraFollowsHead(false), @@ -428,7 +429,7 @@ glm::quat Head::getOrientation() const { glm::quat Head::getCameraOrientation () const { Avatar* owningAvatar = static_cast(_owningAvatar); return owningAvatar->getWorldAlignedOrientation() - * glm::quat(glm::radians(glm::vec3(_cameraPitch, _cameraYaw, 0.0f))); + * glm::quat(glm::radians(glm::vec3(_cameraPitch + _mousePitch, _cameraYaw, 0.0f))); } void Head::renderHeadSphere() { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 1256b05bb7..f31bc53f2a 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -57,6 +57,8 @@ public: void setCameraFollowsHead(bool cameraFollowsHead) { _cameraFollowsHead = cameraFollowsHead; } + void setMousePitch(float mousePitch) { _mousePitch = mousePitch; } + glm::quat getOrientation() const; glm::quat getCameraOrientation () const; @@ -123,6 +125,7 @@ private: float _rightEyeBlinkVelocity; float _timeWithoutTalking; float _cameraPitch; // Used to position the camera differently from the head + float _mousePitch; float _cameraYaw; bool _isCameraMoving; bool _cameraFollowsHead; From fc23eaa8257f2a92fffcd89b26477930f7a0ebc5 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Tue, 6 Aug 2013 10:28:31 -0700 Subject: [PATCH 13/35] Fixed per github feedback. Also, to prevent a repeat of yesterday's crash trouble, disabled the mode switch, so that those working on the rave mode can enable it locally for testing. --- libraries/avatars/src/HandData.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index e8e623decd..b60b423627 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -161,7 +161,8 @@ int HandData::decodeRemoteData(unsigned char* sourceBuffer) { } setRaveGloveActive((gloveFlags & GLOVE_FLAG_RAVE) != 0); - setRaveGloveMode(effectsMode); +// Jeffrey: uncomment this to test locally, before unrolling it to the team. +// setRaveGloveMode(effectsMode); // One byte for error checking safety. unsigned char requiredLength = (unsigned char)(sourceBuffer - startPosition); @@ -171,10 +172,10 @@ int HandData::decodeRemoteData(unsigned char* sourceBuffer) { return sourceBuffer - startPosition; } -void HandData::setRaveGloveMode(int effectsMode) -{ - if (effectsMode != _raveGloveEffectsMode) +void HandData::setRaveGloveMode(int effectsMode) { + if (effectsMode != _raveGloveEffectsMode) { _raveGloveEffectsModeChanged = true; + } _raveGloveEffectsMode = effectsMode; } From 73510ec9755e43a50659185d4c6e7285432c5f65 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 10:33:09 -0700 Subject: [PATCH 14/35] added notifications with jurisdiction details for when voxel servers come and go --- interface/src/Application.cpp | 39 +++++++++++++++++++++++++- interface/src/Application.h | 7 ++++- interface/src/VoxelSystem.cpp | 2 +- libraries/shared/src/NodeList.cpp | 2 ++ libraries/shared/src/OctalCode.cpp | 21 ++++++++++++++ libraries/shared/src/OctalCode.h | 5 ++++ libraries/voxels/src/VoxelSceneStats.h | 3 ++ 7 files changed, 76 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9a0ec2b483..c00f514e05 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -235,6 +235,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : NodeList::createInstance(NODE_TYPE_AGENT, listenPort); NodeList::getInstance()->addHook(&_voxels); + NodeList::getInstance()->addHook(this); _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking"); @@ -322,6 +323,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : Application::~Application() { NodeList::getInstance()->removeHook(&_voxels); + NodeList::getInstance()->removeHook(this); } void Application::initializeGL() { @@ -3824,9 +3826,44 @@ void Application::attachNewHeadToNode(Node* newNode) { } } +void Application::nodeAdded(Node* node) { +} + +void Application::nodeKilled(Node* node) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + uint16_t nodeID = node->getNodeID(); + // see if this is the first we've heard of this node... + if (_voxelServerJurisdictions.find(nodeID) != _voxelServerJurisdictions.end()) { + VoxelPositionSize jurisditionDetails; + jurisditionDetails = _voxelServerJurisdictions[nodeID]; + + printf("voxel server going away...... v[%f, %f, %f, %f]\n", + jurisditionDetails.x, jurisditionDetails.y, jurisditionDetails.z, jurisditionDetails.s); + } + } +} + int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLength, sockaddr senderAddress) { - //Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress); + + // parse the incoming stats data, and stick it into our averaging stats object for now... even though this + // means mixing in stats from potentially multiple servers. int statsMessageLength = _voxelSceneStats.unpackFromMessage(messageData, messageLength); + + // But, also identify the sender, and keep track of the contained jurisdiction root for this server + Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress); + uint16_t nodeID = voxelServer->getNodeID(); + + VoxelPositionSize jurisditionDetails; + voxelDetailsForCode(_voxelSceneStats.getJurisdictionRoot(), jurisditionDetails); + + // see if this is the first we've heard of this node... + if (_voxelServerJurisdictions.find(nodeID) == _voxelServerJurisdictions.end()) { + printf("stats from new voxel server... v[%f, %f, %f, %f]\n", + jurisditionDetails.x, jurisditionDetails.y, jurisditionDetails.z, jurisditionDetails.s); + } + // store jurisdiction details for later use + _voxelServerJurisdictions[nodeID] = jurisditionDetails; + return statsMessageLength; } diff --git a/interface/src/Application.h b/interface/src/Application.h index dbfc7abe49..52299fac98 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -59,7 +59,7 @@ class QWheelEvent; class Node; class ProgramObject; -class Application : public QApplication { +class Application : public QApplication, public NodeListHook { Q_OBJECT public: @@ -109,6 +109,9 @@ public: void resetSongMixMenuItem(); + virtual void nodeAdded(Node* node); + virtual void nodeKilled(Node* node); + public slots: void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); @@ -447,6 +450,8 @@ private: VoxelSceneStats _voxelSceneStats; int parseVoxelStats(unsigned char* messageData, ssize_t messageLength, sockaddr senderAddress); + + std::map _voxelServerJurisdictions; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 11d4f10586..c3d2ce0b70 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1578,7 +1578,7 @@ bool VoxelSystem::killSourceVoxelsOperation(VoxelNode* node, void* extraData) { void VoxelSystem::nodeKilled(Node* node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { uint16_t nodeID = node->getNodeID(); - //printf("VoxelSystem... voxel server %u removed...\n", nodeID); + printf("VoxelSystem... voxel server %u removed...\n", nodeID); // Kill any voxels from the local tree _tree->recurseTreeWithOperation(killSourceVoxelsOperation, &nodeID); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 2ca07660e2..69b19d2e75 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -639,12 +639,14 @@ void NodeList::removeHook(NodeListHook* hook) { void NodeList::notifyHooksOfAddedNode(Node* node) { for (int i = 0; i < _hooks.size(); i++) { +printf("NodeList::notifyHooksOfAddedNode() i=%d\n", i); _hooks[i]->nodeAdded(node); } } void NodeList::notifyHooksOfKilledNode(Node* node) { for (int i = 0; i < _hooks.size(); i++) { +printf("NodeList::notifyHooksOfKilledNode() i=%d\n", i); _hooks[i]->nodeKilled(node); } } diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index 0a198f9832..eeea3385e9 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -115,6 +115,27 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber return newCode; } +void voxelDetailsForCode(unsigned char * octalCode, VoxelPositionSize& voxelPositionSize) { + float output[3]; + memset(&output[0], 0, 3 * sizeof(float)); + + float currentScale = 1.0; + + for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { + currentScale *= 0.5; + int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8); + + for (int j = 0; j < 3; j++) { + output[j] += currentScale * (int)oneAtBit(sectionIndex, 5 + j); + } + + } + voxelPositionSize.x = output[0]; + voxelPositionSize.y = output[1]; + voxelPositionSize.z = output[2]; + voxelPositionSize.s = currentScale; +} + void copyFirstVertexForCode(unsigned char * octalCode, float* output) { memset(output, 0, 3 * sizeof(float)); diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index 477751ea7c..297be6a137 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -36,6 +36,11 @@ bool isAncestorOf(unsigned char* possibleAncestor, unsigned char* possibleDescen float * firstVertexForCode(unsigned char * octalCode); void copyFirstVertexForCode(unsigned char * octalCode, float* output); +struct VoxelPositionSize { + float x,y,z,s; +}; +void voxelDetailsForCode(unsigned char * octalCode, VoxelPositionSize& voxelPositionSize); + typedef enum { ILLEGAL_CODE = -2, LESS_THAN = -1, diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index ac7c45a060..910859ff3e 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -80,6 +80,9 @@ public: ItemInfo& getItemInfo(int item) { return _ITEMS[item]; }; char* getItemValue(int item); + unsigned char* getJurisdictionRoot() const { return _jurisdictionRoot; } + + private: bool _isReadyToSend; unsigned char _statsMessage[MAX_PACKET_SIZE]; From 32c155ef71b0ff09b1e9a1cd7827a7b442acde11 Mon Sep 17 00:00:00 2001 From: atlante45 Date: Tue, 6 Aug 2013 10:53:10 -0700 Subject: [PATCH 15/35] Render a string to show who is following who --- interface/src/Application.cpp | 52 ++++++++++++++++++++++++++ interface/src/Application.h | 1 + interface/src/avatar/Avatar.cpp | 3 ++ interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/Head.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 15 +++++++- libraries/avatars/src/AvatarData.h | 12 ++++-- libraries/shared/src/NodeList.h | 2 +- libraries/shared/src/PacketHeaders.cpp | 2 +- 9 files changed, 83 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 772908abe5..c2f0564cec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2287,6 +2287,56 @@ void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& which renderCircle(haloOrigin, INDICATOR_RADIUS, IDENTITY_UP, NUM_SEGMENTS); } +void Application::renderFollowIndicator() { + NodeList* nodeList = NodeList::getInstance(); + + glLineWidth(5); + glBegin(GL_LINES); + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) { + if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { + Avatar* avatar = (Avatar *) node->getLinkedData(); + Avatar* leader = NULL; + + if (avatar->getLeaderID() != UNKNOWN_NODE_ID) { + if (avatar->getLeaderID() == NodeList::getInstance()->getOwnerID()) { + leader = &_myAvatar; + } else { + for (NodeList::iterator it = nodeList->begin(); it != nodeList->end(); ++it) { + if(it->getNodeID() == avatar->getLeaderID() + && it->getType() == NODE_TYPE_AGENT) { + leader = (Avatar*) it->getLinkedData(); + } + } + } + + if (leader != NULL) { + glColor3f(1.f, 0.f, 0.f); + glVertex3f(avatar->getPosition().x, + avatar->getPosition().y, + avatar->getPosition().z); + glColor3f(0.f, 1.f, 0.f); + glVertex3f(leader->getPosition().x, + leader->getPosition().y, + leader->getPosition().z); + } + } + } + } + + if (_myAvatar.getLeadingAvatar() != NULL) { + glColor3f(1.f, 0.f, 0.f); + glVertex3f(_myAvatar.getPosition().x, + _myAvatar.getPosition().y, + _myAvatar.getPosition().z); + glColor3f(0.f, 1.f, 0.f); + glVertex3f(_myAvatar.getLeadingAvatar()->getPosition().x, + _myAvatar.getLeadingAvatar()->getPosition().y, + _myAvatar.getLeadingAvatar()->getPosition().z); + } + + glEnd(); +} + void Application::update(float deltaTime) { // Use Transmitter Hand to move hand if connected, else use mouse @@ -3060,6 +3110,8 @@ void Application::displaySide(Camera& whichCamera) { // brad's frustum for debugging if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum); + + renderFollowIndicator(); } void Application::displayOverlay() { diff --git a/interface/src/Application.h b/interface/src/Application.h index cb851c1dfc..df14a4eec0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -216,6 +216,7 @@ private: bool isLookingAtMyAvatar(Avatar* avatar); void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera); + void renderFollowIndicator(); void updateAvatar(float deltaTime); void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 26192ffe5a..4ae49ce5ef 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -493,10 +493,13 @@ void Avatar::follow(Avatar* leadingAvatar) { _leadingAvatar = leadingAvatar; if (_leadingAvatar != NULL) { + _leaderID = leadingAvatar->getOwningNode()->getNodeID(); _stringLength = glm::length(_position - _leadingAvatar->getPosition()) / _scale; if (_stringLength > MAX_STRING_LENGTH) { _stringLength = MAX_STRING_LENGTH; } + } else { + _leaderID = UNKNOWN_NODE_ID; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b490429ec9..21f413a693 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -27,7 +27,7 @@ #include "world.h" -static const float MAX_SCALE = 5.f; +static const float MAX_SCALE = 10.f; static const float MIN_SCALE = .5f; static const float SCALING_RATIO = .05f; static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1 diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b88802b7f1..1188e8cb08 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -338,7 +338,7 @@ void Head::setScale (float scale) { } void Head::createMohawk() { - uint16_t nodeId = 0; + uint16_t nodeId = UNKNOWN_NODE_ID; if (_owningAvatar->getOwningNode()) { nodeId = _owningAvatar->getOwningNode()->getNodeID(); } else { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 1dd6a0787b..60307e3172 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -41,7 +41,8 @@ AvatarData::AvatarData(Node* owningNode) : _wantLowResMoving(false), _wantOcclusionCulling(true), _headData(NULL), - _handData(NULL) + _handData(NULL), + _leaderID(UNKNOWN_NODE_ID) { } @@ -91,8 +92,14 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyYaw); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyPitch); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll); + + // Body scale destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale); + // Follow mode info + memcpy(destinationBuffer, &_leaderID, sizeof(_leaderID)); + destinationBuffer += sizeof(uint16_t); + // Head rotation (NOTE: This needs to become a quaternion to save two bytes) destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_yaw); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_pitch); @@ -188,8 +195,14 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyYaw); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyPitch); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyRoll); + + // Body scale sourceBuffer += unpackFloatRatioFromTwoByte( sourceBuffer, _newScale); + // Follow mode info + memcpy(&_leaderID, sourceBuffer, sizeof(_leaderID)); + sourceBuffer += sizeof(uint16_t); + // Head rotation (NOTE: This needs to become a quaternion to save two bytes) float headYaw, headPitch, headRoll; sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headYaw); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a9e14caaa6..bdcf74904e 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -92,10 +92,11 @@ public: const std::string& chatMessage () const { return _chatMessage; } // related to Voxel Sending strategies - bool getWantColor() const { return _wantColor; } - bool getWantDelta() const { return _wantDelta; } - bool getWantLowResMoving() const { return _wantLowResMoving; } + bool getWantColor() const { return _wantColor; } + bool getWantDelta() const { return _wantDelta; } + bool getWantLowResMoving() const { return _wantLowResMoving; } bool getWantOcclusionCulling() const { return _wantOcclusionCulling; } + uint16_t getLeaderID() const { return _leaderID; } void setWantColor(bool wantColor) { _wantColor = wantColor; } void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } @@ -118,8 +119,13 @@ protected: float _bodyYaw; float _bodyPitch; float _bodyRoll; + + // Body scale float _newScale; + // Following mode infos + uint16_t _leaderID; + // Hand state (are we grabbing something or not) char _handState; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 260fddf96f..566cd8ba40 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -66,7 +66,7 @@ public: void setDomainIPToLocalhost(); uint16_t getLastNodeID() const { return _lastNodeID; } - void increaseNodeID() { ++_lastNodeID; } + void increaseNodeID() { (++_lastNodeID == UNKNOWN_NODE_ID) ? ++_lastNodeID : _lastNodeID; } uint16_t getOwnerID() const { return _ownerID; } void setOwnerID(uint16_t ownerID) { _ownerID = ownerID; } diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 99c887614c..d435e1bd1b 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 1; case PACKET_TYPE_HEAD_DATA: - return 3; + return 4; case PACKET_TYPE_AVATAR_FACE_VIDEO: return 1; From 97239968a536b3a51d4944094ce0d858ab18fe9c Mon Sep 17 00:00:00 2001 From: atlante45 Date: Tue, 6 Aug 2013 11:05:00 -0700 Subject: [PATCH 16/35] Corrected wrong argument in sizeof --- libraries/avatars/src/AvatarData.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 60307e3172..6d5d0a6528 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -97,7 +97,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale); // Follow mode info - memcpy(destinationBuffer, &_leaderID, sizeof(_leaderID)); + memcpy(destinationBuffer, &_leaderID, sizeof(uint16_t)); destinationBuffer += sizeof(uint16_t); // Head rotation (NOTE: This needs to become a quaternion to save two bytes) @@ -200,7 +200,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackFloatRatioFromTwoByte( sourceBuffer, _newScale); // Follow mode info - memcpy(&_leaderID, sourceBuffer, sizeof(_leaderID)); + memcpy(&_leaderID, sourceBuffer, sizeof(uint16_t)); sourceBuffer += sizeof(uint16_t); // Head rotation (NOTE: This needs to become a quaternion to save two bytes) From ddf1b06bf9bc9f4c976bed39a385a207a085292c Mon Sep 17 00:00:00 2001 From: atlante45 Date: Tue, 6 Aug 2013 11:33:59 -0700 Subject: [PATCH 17/35] Add option to turn collisions on and off --- interface/src/Application.cpp | 5 +++++ interface/src/Application.h | 2 ++ interface/src/avatar/Avatar.cpp | 11 +++++++---- interface/src/avatar/Avatar.h | 2 ++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 772908abe5..2ec249677c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1944,6 +1944,7 @@ void Application::initMenu() { (_fullScreenMode = optionsMenu->addAction("Fullscreen", this, SLOT(setFullscreen(bool)), Qt::Key_F))->setCheckable(true); optionsMenu->addAction("Webcam", &_webcam, SLOT(setEnabled(bool)))->setCheckable(true); optionsMenu->addAction("Toggle Skeleton Tracking", &_webcam, SLOT(setSkeletonTrackingOn(bool)))->setCheckable(true); + (_wantCollisionsOn = optionsMenu->addAction("Turn collisions On", this, SLOT(toggleWantCollisionsOn())))->setCheckable(true); optionsMenu->addAction("Cycle Webcam Send Mode", _webcam.getGrabber(), SLOT(cycleVideoSendMode())); optionsMenu->addAction("Go Home", this, SLOT(goHome()), Qt::CTRL | Qt::Key_G); @@ -2137,6 +2138,10 @@ void Application::toggleMixedSong() { } } +void Application::toggleWantCollisionsOn() { + _myAvatar.setWantCollisionsOn(_wantCollisionsOn->isChecked()); +} + void Application::resetSongMixMenuItem() { if (_audio.getSongFileBytes() == 0) { _rawAudioMicrophoneMix->setText("Mix RAW Song"); diff --git a/interface/src/Application.h b/interface/src/Application.h index cb851c1dfc..c946e100b5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -179,6 +179,7 @@ private slots: void setListenModePoint(); void setListenModeSingleSource(); void toggleMixedSong(); + void toggleWantCollisionsOn(); void renderCoverageMap(); @@ -294,6 +295,7 @@ private: QAction* _rawAudioMicrophoneMix; // Mixing of a RAW audio file with microphone stream for rave gloves QAction* _noise; QAction* _occlusionCulling; + QAction* _wantCollisionsOn; QAction* _renderCoverageMapV2; QAction* _renderCoverageMap; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 26192ffe5a..e54f14e8f3 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -623,9 +623,12 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime); } } - updateCollisionWithEnvironment(deltaTime); - updateCollisionWithVoxels(deltaTime); - updateAvatarCollisions(deltaTime); + + if (_isCollisionsOn) { + updateCollisionWithEnvironment(deltaTime); + updateCollisionWithVoxels(deltaTime); + updateAvatarCollisions(deltaTime); + } } // update body balls @@ -633,7 +636,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // test for avatar collision response with the big sphere - if (usingBigSphereCollisionTest) { + if (usingBigSphereCollisionTest && _isCollisionsOn) { updateCollisionWithSphere(_TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b490429ec9..acb6cac098 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -142,6 +142,7 @@ public: void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction); void setOrientation (const glm::quat& orientation); void setNewScale (const float scale); + void setWantCollisionsOn (bool wantCollisionsOn ) { _isCollisionsOn = wantCollisionsOn; } //getters bool isInitialized () const { return _initialized;} @@ -263,6 +264,7 @@ private: glm::vec3 _lastCollisionPosition; bool _speedBrakes; bool _isThrustOn; + bool _isCollisionsOn; Avatar* _leadingAvatar; float _stringLength; From ab31c3f82d1e5dece3f9a66f6ad51244cf04fffb Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Tue, 6 Aug 2013 11:59:58 -0700 Subject: [PATCH 18/35] Rave glove: Fix initialization issues and activate mode switch. Note that this change will have no effect until the Avatar Mixer gets it, because the mixer will continue to send "glove mode 0" until it receives this update. --- interface/src/avatar/Hand.cpp | 6 +++++- libraries/avatars/src/HandData.cpp | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index e445f89472..43b7bfc2e3 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -54,7 +54,7 @@ void Hand::reset() { void Hand::simulate(float deltaTime, bool isMine) { if (_isRaveGloveActive) { - if (_raveGloveEffectsModeChanged) { + if (_raveGloveEffectsModeChanged && _raveGloveInitialized) { activateNewRaveGloveMode(); _raveGloveEffectsModeChanged = false; } @@ -363,6 +363,10 @@ void Hand::updateRaveGloveParticles(float deltaTime) { // The rave glove mode has changed, so activate the effects. void Hand::activateNewRaveGloveMode() { + if (!_raveGloveInitialized) { + return; + } + int mode = _raveGloveEffectsMode; _raveGloveParticleSystem.killAllParticles(); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index b60b423627..2f6e8aa560 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -161,8 +161,9 @@ int HandData::decodeRemoteData(unsigned char* sourceBuffer) { } setRaveGloveActive((gloveFlags & GLOVE_FLAG_RAVE) != 0); -// Jeffrey: uncomment this to test locally, before unrolling it to the team. -// setRaveGloveMode(effectsMode); + if (numHands > 0) { + setRaveGloveMode(effectsMode); + } // One byte for error checking safety. unsigned char requiredLength = (unsigned char)(sourceBuffer - startPosition); From 88e2e3dd3fdbbd841e1cb3e85edba323deae31a1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 12:05:43 -0700 Subject: [PATCH 19/35] added visulization for voxel add/kill --- interface/src/Application.cpp | 31 ++++++++++++++ interface/src/Application.h | 3 ++ interface/src/VoxelFade.cpp | 59 +++++++++++++++++++++++++++ interface/src/VoxelFade.h | 43 +++++++++++++++++++ libraries/shared/src/OctalCode.h | 2 +- libraries/voxels/src/VoxelConstants.h | 1 + 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 interface/src/VoxelFade.cpp create mode 100644 interface/src/VoxelFade.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c00f514e05..d6d28726f7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3069,6 +3069,19 @@ void Application::displaySide(Camera& whichCamera) { // brad's frustum for debugging if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum); + + // render voxel fades if they exist + if (_voxelFades.size() > 0) { + for(std::vector::iterator fade = _voxelFades.begin(); fade != _voxelFades.end();) { + fade->render(); + if(fade->isDone()) { + fade = _voxelFades.erase(fade); + } else { + ++fade; + } + } + } + } void Application::displayOverlay() { @@ -3839,6 +3852,15 @@ void Application::nodeKilled(Node* node) { printf("voxel server going away...... v[%f, %f, %f, %f]\n", jurisditionDetails.x, jurisditionDetails.y, jurisditionDetails.z, jurisditionDetails.s); + + // Add the jurisditionDetails object to the list of "fade outs" + const float NODE_KILLED_RED = 1.0f; + const float NODE_KILLED_GREEN = 0.0f; + const float NODE_KILLED_BLUE = 0.0f; + + VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE); + fade.voxelDetails = jurisditionDetails; + _voxelFades.push_back(fade); } } } @@ -3860,6 +3882,15 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng if (_voxelServerJurisdictions.find(nodeID) == _voxelServerJurisdictions.end()) { printf("stats from new voxel server... v[%f, %f, %f, %f]\n", jurisditionDetails.x, jurisditionDetails.y, jurisditionDetails.z, jurisditionDetails.s); + + // Add the jurisditionDetails object to the list of "fade outs" + const float NODE_ADDED_RED = 0.0f; + const float NODE_ADDED_GREEN = 1.0f; + const float NODE_ADDED_BLUE = 0.0f; + + VoxelFade fade(VoxelFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE); + fade.voxelDetails = jurisditionDetails; + _voxelFades.push_back(fade); } // store jurisdiction details for later use _voxelServerJurisdictions[nodeID] = jurisditionDetails; diff --git a/interface/src/Application.h b/interface/src/Application.h index 52299fac98..c4ae390797 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -37,6 +37,7 @@ #include "Swatch.h" #include "ToolsPalette.h" #include "ViewFrustum.h" +#include "VoxelFade.h" #include "VoxelSystem.h" #include "Webcam.h" #include "PieMenu.h" @@ -452,6 +453,8 @@ private: int parseVoxelStats(unsigned char* messageData, ssize_t messageLength, sockaddr senderAddress); std::map _voxelServerJurisdictions; + + std::vector _voxelFades; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/VoxelFade.cpp b/interface/src/VoxelFade.cpp new file mode 100644 index 0000000000..9c102ba6c5 --- /dev/null +++ b/interface/src/VoxelFade.cpp @@ -0,0 +1,59 @@ +// +// VoxelFade.cpp +// interface +// +// Created by Brad Hefta-Gaub on 8/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include // Header File For The OpenGL32 Library +#include + +#include + +#include "VoxelFade.h" + +const float VoxelFade::FADE_OUT_START = 0.5f; +const float VoxelFade::FADE_OUT_END = 0.0f; +const float VoxelFade::FADE_OUT_STEP = -0.005f; +const float VoxelFade::FADE_IN_START = 0.0f; +const float VoxelFade::FADE_IN_END = 0.5f; +const float VoxelFade::FADE_IN_STEP = 0.005f; +const float VoxelFade::DEFAULT_RED = 0.5f; +const float VoxelFade::DEFAULT_GREEN = 0.5f; +const float VoxelFade::DEFAULT_BLUE = 0.5f; + +VoxelFade::VoxelFade(FadeDirection direction, float red, float green, float blue) : + direction(direction), + red(red), + green(green), + blue(blue) +{ + opacity = (direction == FADE_OUT) ? FADE_OUT_START : FADE_IN_START; +} + +void VoxelFade::render() { + glDisable(GL_LIGHTING); + glPushMatrix(); + glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); + glColor4f(red, green, blue, opacity); + glTranslatef(voxelDetails.x + voxelDetails.s * 0.5f, + voxelDetails.y + voxelDetails.s * 0.5f, + voxelDetails.z + voxelDetails.s * 0.5f); + glLineWidth(1.0f); + glutSolidCube(voxelDetails.s); + glLineWidth(1.0f); + glPopMatrix(); + glEnable(GL_LIGHTING); + + opacity += (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP; +} + +bool VoxelFade::isDone() const { + if (direction == FADE_OUT) { + return opacity <= FADE_OUT_END; + } else { + return opacity >= FADE_IN_END; + } + return true; // unexpected case, assume we're done +} \ No newline at end of file diff --git a/interface/src/VoxelFade.h b/interface/src/VoxelFade.h new file mode 100644 index 0000000000..fd7a73135b --- /dev/null +++ b/interface/src/VoxelFade.h @@ -0,0 +1,43 @@ +// +// VoxelFade.h +// interface +// +// Created by Brad Hefta-Gaub on 8/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__VoxelFade__ +#define __interface__VoxelFade__ + +#include // for VoxelPositionSize + +class VoxelFade { +public: + + enum FadeDirection { FADE_OUT, FADE_IN}; + static const float FADE_OUT_START; + static const float FADE_OUT_END; + static const float FADE_OUT_STEP; + static const float FADE_IN_START; + static const float FADE_IN_END; + static const float FADE_IN_STEP; + static const float DEFAULT_RED; + static const float DEFAULT_GREEN; + static const float DEFAULT_BLUE; + + VoxelPositionSize voxelDetails; + FadeDirection direction; + float opacity; + + float red; + float green; + float blue; + + VoxelFade(FadeDirection direction = FADE_OUT, float red = DEFAULT_RED, + float green = DEFAULT_GREEN, float blue = DEFAULT_BLUE); + + void render(); + bool isDone() const; +}; + +#endif // __interface__VoxelFade__ diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index 297be6a137..405b85164d 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -37,7 +37,7 @@ float * firstVertexForCode(unsigned char * octalCode); void copyFirstVertexForCode(unsigned char * octalCode, float* output); struct VoxelPositionSize { - float x,y,z,s; + float x, y, z, s; }; void voxelDetailsForCode(unsigned char * octalCode, VoxelPositionSize& voxelPositionSize); diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 4b971e9515..5a5815b6b3 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -14,6 +14,7 @@ #include #include +#include // this is where the coordinate system is represented const glm::vec3 IDENTITY_RIGHT = glm::vec3( 1.0f, 0.0f, 0.0f); From 120bbbd5067efed3724bf2fc37d9ce2ff5965cdf Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 6 Aug 2013 12:34:45 -0700 Subject: [PATCH 20/35] Tuned gyro look, added better preferences --- interface/src/Application.cpp | 23 ++++++++++------------- interface/src/Application.h | 2 +- interface/src/avatar/Avatar.cpp | 19 ++++++++++++------- interface/src/avatar/Avatar.h | 3 +-- interface/src/avatar/Head.cpp | 25 ++++++++++++------------- interface/src/avatar/Head.h | 2 +- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5efe365a49..88b92e1d45 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1290,9 +1290,9 @@ void Application::editPreferences() { horizontalFieldOfView->setValue(_horizontalFieldOfView); form->addRow("Horizontal field of view (degrees):", horizontalFieldOfView); - QDoubleSpinBox* headCameraPitchYawScale = new QDoubleSpinBox(); - headCameraPitchYawScale->setValue(_headCameraPitchYawScale); - form->addRow("Head Camera Pitch/Yaw Scale:", headCameraPitchYawScale); + QDoubleSpinBox* gyroCameraSensitivity = new QDoubleSpinBox(); + gyroCameraSensitivity->setValue(_gyroCameraSensitivity); + form->addRow("Gyro Camera Sensitivity (0 - 1):", gyroCameraSensitivity); QDoubleSpinBox* leanScale = new QDoubleSpinBox(); leanScale->setValue(_myAvatar.getLeanScale()); @@ -1342,7 +1342,7 @@ void Application::editPreferences() { _myAvatar.getVoxels()->setVoxelURL(url); sendAvatarVoxelURLMessage(url); - _headCameraPitchYawScale = headCameraPitchYawScale->value(); + _gyroCameraSensitivity = gyroCameraSensitivity->value(); _myAvatar.setLeanScale(leanScale->value()); _audioJitterBufferSamples = audioJitterBufferSamples->value(); if (!shouldDynamicallySetJitterBuffer()) { @@ -2500,7 +2500,7 @@ void Application::update(float deltaTime) { if (!avatar->isInitialized()) { avatar->init(); } - avatar->simulate(deltaTime, NULL); + avatar->simulate(deltaTime, NULL, 0.f); avatar->setMouseRay(mouseRayOrigin, mouseRayDirection); } node->unlock(); @@ -2515,9 +2515,9 @@ void Application::update(float deltaTime) { } if (_transmitterDrives->isChecked() && _myTransmitter.isConnected()) { - _myAvatar.simulate(deltaTime, &_myTransmitter); + _myAvatar.simulate(deltaTime, &_myTransmitter, _gyroCameraSensitivity); } else { - _myAvatar.simulate(deltaTime, NULL); + _myAvatar.simulate(deltaTime, NULL, _gyroCameraSensitivity); } if (!OculusManager::isConnected()) { @@ -2584,9 +2584,6 @@ void Application::updateAvatar(float deltaTime) { // Update my avatar's state from gyros and/or webcam _myAvatar.updateFromGyrosAndOrWebcam(_gyroLook->isChecked(), - glm::vec3(_headCameraPitchYawScale, - _headCameraPitchYawScale, - _headCameraPitchYawScale), _pitchFromTouch); if (_serialHeadSensor.isActive()) { @@ -3951,11 +3948,11 @@ void Application::saveAction(QSettings* set, QAction* action) { } void Application::loadSettings(QSettings* settings) { - if (!settings) { + if (!settings) { settings = getSettings(); } - _headCameraPitchYawScale = loadSetting(settings, "headCameraPitchYawScale", 0.0f); + _gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f); _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); _horizontalFieldOfView = loadSetting(settings, "horizontalFieldOfView", HORIZONTAL_FIELD_OF_VIEW_DEGREES); @@ -3979,7 +3976,7 @@ void Application::saveSettings(QSettings* settings) { settings = getSettings(); } - settings->setValue("headCameraPitchYawScale", _headCameraPitchYawScale); + settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity); settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); settings->setValue("horizontalFieldOfView", _horizontalFieldOfView); settings->beginGroup("View Frustum Offset Camera"); diff --git a/interface/src/Application.h b/interface/src/Application.h index cb851c1dfc..dfb38d5dd5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -358,7 +358,7 @@ private: Environment _environment; int _headMouseX, _headMouseY; - float _headCameraPitchYawScale; + float _gyroCameraSensitivity; int _audioJitterBufferSamples; // Number of extra samples to wait before starting audio playback diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0b6484c8a7..b67a32887c 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -294,7 +294,6 @@ void Avatar::reset() { // Update avatar head rotation with sensor data void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, - const glm::vec3& amplifyAngle, float pitchFromTouch) { _head.setMousePitch(pitchFromTouch); SerialInterface* gyros = Application::getInstance()->getSerialHeadSensor(); @@ -333,9 +332,15 @@ void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, } else { _head.getFace().clearFrame(); } - _head.setPitch(estimatedRotation.x * amplifyAngle.x); - _head.setYaw(estimatedRotation.y * amplifyAngle.y); - _head.setRoll(estimatedRotation.z * amplifyAngle.z); + + // Set the rotation of the avatar's head (as seen by others, not affecting view frustum) + // to be scaled. Pitch is greater to emphasize nodding behavior / synchrony. + const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f; + const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f; + const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f; + _head.setPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); + _head.setYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); + _head.setRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); _head.setCameraFollowsHead(gyroLook); // Update torso lean distance based on accelerometer data @@ -390,7 +395,7 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { // // Gather thrust information from keyboard and sensors to apply to avatar motion // - glm::quat orientation = getHead().getOrientation(); + glm::quat orientation = getHead().getCameraOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; glm::vec3 up = orientation * IDENTITY_UP; @@ -499,7 +504,7 @@ void Avatar::follow(Avatar* leadingAvatar) { } } -void Avatar::simulate(float deltaTime, Transmitter* transmitter) { +void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity) { glm::quat orientation = getOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; @@ -746,7 +751,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); - _head.simulate(deltaTime, isMyAvatar()); + _head.simulate(deltaTime, isMyAvatar(), gyroCameraSensitivity); _hand.simulate(deltaTime, isMyAvatar()); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ca41bdcb32..fc475a5bd2 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -119,11 +119,10 @@ public: void init(); void reset(); - void simulate(float deltaTime, Transmitter* transmitter); + void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity); void updateThrust(float deltaTime, Transmitter * transmitter); void follow(Avatar* leadingAvatar); void updateFromGyrosAndOrWebcam(bool gyroLook, - const glm::vec3& amplifyAngle, float pitchFromTouch); void addBodyYaw(float bodyYaw) {_bodyYaw += bodyYaw;}; void addBodyYawDelta(float bodyYawDelta) {_bodyYawDelta += bodyYawDelta;} diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 40ed309097..08d9856634 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -146,7 +146,7 @@ void Head::resetHairPhysics() { } -void Head::simulate(float deltaTime, bool isMine) { +void Head::simulate(float deltaTime, bool isMine, float gyroCameraSensitivity) { // Update eye saccades const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; @@ -228,15 +228,18 @@ void Head::simulate(float deltaTime, bool isMine) { } // Update camera pitch and yaw independently from motion of head (for gyro-based interface) - if (isMine && _cameraFollowsHead) { + if (isMine && _cameraFollowsHead && (gyroCameraSensitivity > 0.f)) { // If we are using gyros and using gyroLook, have the camera follow head but with a null region // to create stable rendering view with small head movements. - const float CAMERA_FOLLOW_HEAD_RATE_START = 0.01f; - const float CAMERA_FOLLOW_HEAD_RATE_MAX = 0.5f; + const float CAMERA_FOLLOW_HEAD_RATE_START = 0.1f; + const float CAMERA_FOLLOW_HEAD_RATE_MAX = 1.0f; const float CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE = 1.05f; const float CAMERA_STOP_TOLERANCE_DEGREES = 0.5f; - const float CAMERA_PITCH_START_TOLERANCE_DEGREES = 20.0f; - const float CAMERA_YAW_START_TOLERANCE_DEGREES = 10.0f; + const float PITCH_START_RANGE = 20.f; + const float YAW_START_RANGE = 10.f; + float pitchStartTolerance = PITCH_START_RANGE * (1.f - gyroCameraSensitivity); + float yawStartTolerance = YAW_START_RANGE * (1.f - gyroCameraSensitivity); + float cameraHeadAngleDifference = glm::length(glm::vec2(_pitch - _cameraPitch, _yaw - _cameraYaw)); if (_isCameraMoving) { _cameraFollowHeadRate = glm::clamp(_cameraFollowHeadRate * CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE, @@ -249,17 +252,13 @@ void Head::simulate(float deltaTime, bool isMine) { _isCameraMoving = false; } } else { - if ((fabs(_pitch - _cameraPitch) > CAMERA_PITCH_START_TOLERANCE_DEGREES) || - (fabs(_yaw - _cameraYaw) > CAMERA_YAW_START_TOLERANCE_DEGREES)) { + if ((fabs(_pitch - _cameraPitch) > pitchStartTolerance) || + (fabs(_yaw - _cameraYaw) > yawStartTolerance)) { _isCameraMoving = true; _cameraFollowHeadRate = CAMERA_FOLLOW_HEAD_RATE_START; } } - } else { - // Camera always locked to head - _cameraPitch = _pitch; - _cameraYaw = _yaw; - } + } } void Head::calculateGeometry() { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index f31bc53f2a..ea9e7fab0e 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -41,7 +41,7 @@ public: void init(); void reset(); - void simulate(float deltaTime, bool isMine); + void simulate(float deltaTime, bool isMine, float gyroCameraSensitivity); void render(float alpha); void renderMohawk(); From 9a4a0e2819a595fe97f6f1e1ac43d440284dbd7c Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Tue, 6 Aug 2013 12:44:29 -0700 Subject: [PATCH 21/35] Rave glove adjustments per Ryan's requests: hide fingers and arms when raving, center hands in front of face. --- interface/src/avatar/Avatar.cpp | 11 +++++++++++ interface/src/avatar/Hand.cpp | 10 ++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0b6484c8a7..747f9dff93 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1373,6 +1373,17 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { float alpha = getBallRenderAlpha(b, lookingInMirror); + // When in rave glove mode, don't show the arms at all. + if (_hand.isRaveGloveActive()) { + if (b == BODY_BALL_LEFT_ELBOW + || b == BODY_BALL_LEFT_WRIST + || b == BODY_BALL_LEFT_FINGERTIPS + || b == BODY_BALL_RIGHT_ELBOW + || b == BODY_BALL_RIGHT_WRIST + || b == BODY_BALL_RIGHT_FINGERTIPS) { + continue; + } + } // Always render other people, and render myself when beyond threshold distance if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special if (alpha > 0.0f) { diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 43b7bfc2e3..b960f8e56b 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -64,10 +64,10 @@ void Hand::simulate(float deltaTime, bool isMine) { } void Hand::calculateGeometry() { - glm::vec3 offset(0.2, -0.2, -0.3); // place the hand in front of the face where we can see it + const glm::vec3 leapHandsOffsetFromFace(0.0, -0.2, -0.3); // place the hand in front of the face where we can see it Head& head = _owningAvatar->getHead(); - _basePosition = head.getPosition() + head.getOrientation() * offset; + _basePosition = head.getPosition() + head.getOrientation() * leapHandsOffsetFromFace; _baseOrientation = head.getOrientation(); // generate finger tip balls.... @@ -154,8 +154,10 @@ void Hand::render(bool lookingInMirror) { if ( SHOW_LEAP_HAND ) { //renderLeapHands(); - renderLeapFingerTrails(); - renderLeapHandSpheres(); + if (!isRaveGloveActive()) { + renderLeapFingerTrails(); + renderLeapHandSpheres(); + } } } From 720ae561df891ae05e91f4b870b9d4472451c3eb Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 6 Aug 2013 13:27:54 -0700 Subject: [PATCH 22/35] Working on support for a textured face mode that doesn't rely on the video stream. --- .../resources/shaders/face_textured.frag | 82 +++++ .../resources/shaders/face_textured.vert | 38 ++ interface/src/Application.h | 5 +- interface/src/VoxelSystem.cpp | 29 +- interface/src/VoxelSystem.h | 1 - interface/src/avatar/Face.cpp | 326 ++++++++++-------- interface/src/avatar/Face.h | 21 +- interface/src/renderer/TextureCache.cpp | 45 +++ interface/src/renderer/TextureCache.h | 27 ++ 9 files changed, 390 insertions(+), 184 deletions(-) create mode 100644 interface/resources/shaders/face_textured.frag create mode 100644 interface/resources/shaders/face_textured.vert create mode 100644 interface/src/renderer/TextureCache.cpp create mode 100644 interface/src/renderer/TextureCache.h diff --git a/interface/resources/shaders/face_textured.frag b/interface/resources/shaders/face_textured.frag new file mode 100644 index 0000000000..fefefc6817 --- /dev/null +++ b/interface/resources/shaders/face_textured.frag @@ -0,0 +1,82 @@ +#version 120 + +// +// face_textured.frag +// fragment shader +// +// Created by Andrzej Kapolka on 8/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the texture coordinate vector from left to right +uniform vec2 texCoordRight; + +// the texture coordinate vector from bottom to the top +uniform vec2 texCoordUp; + +// the permutation/normal texture +uniform sampler2D permutationNormalTexture; + +// the depth texture +uniform sampler2D depthTexture; + +// the position in model space +varying vec3 position; + +// returns the gradient at a single corner of our sampling cube +vec3 grad(vec3 location) { + float p1 = texture2D(permutationNormalTexture, vec2(location.x / 256.0, 0.25)).r; + float p2 = texture2D(permutationNormalTexture, vec2(p1 + location.y / 256.0, 0.25)).r; + return texture2D(permutationNormalTexture, vec2(p2 + location.z / 256.0, 0.75)).xyz * 2.0 - vec3(1.0, 1.0, 1.0); +} + +// returns the perlin noise value for the specified location +float perlin(vec3 location) { + vec3 floors = floor(location); + vec3 ceils = ceil(location); + vec3 fff = grad(floors); + vec3 ffc = grad(vec3(floors.x, floors.y, ceils.z)); + vec3 fcf = grad(vec3(floors.x, ceils.y, floors.z)); + vec3 fcc = grad(vec3(floors.x, ceils.y, ceils.z)); + vec3 cff = grad(vec3(ceils.x, floors.y, floors.z)); + vec3 cfc = grad(vec3(ceils.x, floors.y, ceils.z)); + vec3 ccf = grad(vec3(ceils.x, ceils.y, floors.z)); + vec3 ccc = grad(ceils); + vec3 ffracts = fract(location); + vec3 cfracts = ffracts - vec3(1.0, 1.0, 1.0); + vec3 params = ffracts*ffracts*(3.0 - 2.0*ffracts); + + float fffv = dot(fff, ffracts); + float ffcv = dot(ffc, vec3(ffracts.x, ffracts.y, cfracts.z)); + float fcfv = dot(fcf, vec3(ffracts.x, cfracts.y, ffracts.z)); + float fccv = dot(fcc, vec3(ffracts.x, cfracts.y, cfracts.z)); + float cffv = dot(cff, vec3(cfracts.x, ffracts.y, ffracts.z)); + float cfcv = dot(cfc, vec3(cfracts.x, ffracts.y, cfracts.z)); + float ccfv = dot(ccf, vec3(cfracts.x, cfracts.y, ffracts.z)); + float cccv = dot(ccc, cfracts); + + return mix( + mix(mix(fffv, cffv, params.x), mix(fcfv, ccfv, params.x), params.y), + mix(mix(ffcv, cfcv, params.x), mix(fccv, cccv, params.x), params.y), + params.z); +} + +void main(void) { + // compute normal from adjacent depth values + float left = texture2D(depthTexture, gl_TexCoord[0].st - texCoordRight * 0.01).r; + float right = texture2D(depthTexture, gl_TexCoord[0].st + texCoordRight * 0.01).r; + float bottom = texture2D(depthTexture, gl_TexCoord[0].st - texCoordUp * 0.01).r; + float top = texture2D(depthTexture, gl_TexCoord[0].st + texCoordUp * 0.01).r; + vec3 normal = normalize(gl_NormalMatrix * vec3(left - right, top - bottom, -0.05)); + + // compute the specular component (sans exponent) based on the normal OpenGL lighting model + float specular = max(0.0, dot(normalize(gl_LightSource[0].position.xyz + vec3(0.0, 0.0, 1.0)), normal)); + + vec3 color = mix(vec3(1.0, 1.0, 1.0), vec3(0.75, 0.75, 0.75), + sin(dot(position, vec3(25.0, 25.0, 25.0)) + 2.0 * perlin(position * 10.0))); + + // standard lighting + gl_FragColor = vec4(color * ( gl_LightModel.ambient.rgb + /* gl_LightSource[0].ambient.rgb + */ + gl_LightSource[0].diffuse.rgb * max(0.0, dot(normal, gl_LightSource[0].position.xyz))) + + pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, gl_Color.a); +} diff --git a/interface/resources/shaders/face_textured.vert b/interface/resources/shaders/face_textured.vert new file mode 100644 index 0000000000..28bda9a84d --- /dev/null +++ b/interface/resources/shaders/face_textured.vert @@ -0,0 +1,38 @@ +#version 120 + +// +// face_textured.vert +// vertex shader +// +// Created by Andrzej Kapolka on 8/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the lower left texture coordinate +uniform vec2 texCoordCorner; + +// the texture coordinate vector from left to right +uniform vec2 texCoordRight; + +// the texture coordinate vector from bottom to the top +uniform vec2 texCoordUp; + +// the depth texture +uniform sampler2D depthTexture; + +// the position in model space +varying vec3 position; + +void main(void) { + gl_TexCoord[0] = vec4(texCoordCorner + gl_Vertex.x * texCoordRight + gl_Vertex.y * texCoordUp, 0.0, 1.0); + float depth = texture2D(depthTexture, gl_TexCoord[0].st).r; + + // store the model space vertex + position = gl_Vertex.xyz; + + // set alpha to zero for invalid depth values + const float MIN_VISIBLE_DEPTH = 1.0 / 255.0; + const float MAX_VISIBLE_DEPTH = 254.0 / 255.0; + gl_FrontColor = vec4(1.0, 1.0, 1.0, step(MIN_VISIBLE_DEPTH, depth) * (1.0 - step(MAX_VISIBLE_DEPTH, depth))); + gl_Position = gl_ModelViewProjectionMatrix * vec4(0.5 - gl_Vertex.x, gl_Vertex.y - 0.5, depth - 0.5, 1.0); +} diff --git a/interface/src/Application.h b/interface/src/Application.h index cb851c1dfc..3621f04a94 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -31,7 +31,6 @@ #include "Environment.h" #include "PacketHeaders.h" #include "ParticleSystem.h" -#include "renderer/GeometryCache.h" #include "SerialInterface.h" #include "Stars.h" #include "Swatch.h" @@ -42,6 +41,8 @@ #include "PieMenu.h" #include "avatar/Avatar.h" #include "avatar/HandControl.h" +#include "renderer/GeometryCache.h" +#include "renderer/TextureCache.h" #include "ui/BandwidthDialog.h" #include "ui/ChatEntry.h" #include "ui/VoxelStatsDialog.h" @@ -105,6 +106,7 @@ public: QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; } GeometryCache* getGeometryCache() { return &_geometryCache; } + TextureCache* getTextureCache() { return &_textureCache; } void resetSongMixMenuItem(); @@ -419,6 +421,7 @@ private: int _hmdWarpParamLocation; GeometryCache _geometryCache; + TextureCache _textureCache; ParticleSystem _particleSystem; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 65d819eddc..aed01412f7 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -17,8 +17,6 @@ #include // to load voxels from file #include -#include - #include #include #include @@ -493,7 +491,6 @@ glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float vo } ProgramObject* VoxelSystem::_perlinModulateProgram = 0; -GLuint VoxelSystem::_permutationNormalTextureID = 0; void VoxelSystem::init() { @@ -585,29 +582,9 @@ void VoxelSystem::init() { _perlinModulateProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); _perlinModulateProgram->link(); + _perlinModulateProgram->bind(); _perlinModulateProgram->setUniformValue("permutationNormalTexture", 0); - - // create the permutation/normal texture - glGenTextures(1, &_permutationNormalTextureID); - glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); - - // the first line consists of random permutation offsets - unsigned char data[256 * 2 * 3]; - for (int i = 0; i < 256 * 3; i++) { - data[i] = rand() % 256; - } - // the next, random unit normals - for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) { - glm::vec3 randvec = glm::sphericalRand(1.0f); - data[i] = ((randvec.x + 1.0f) / 2.0f) * 255.0f; - data[i + 1] = ((randvec.y + 1.0f) / 2.0f) * 255.0f; - data[i + 2] = ((randvec.z + 1.0f) / 2.0f) * 255.0f; - } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glBindTexture(GL_TEXTURE_2D, 0); + _perlinModulateProgram->release(); } void VoxelSystem::updateFullVBOs() { @@ -734,7 +711,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { if (texture) { _perlinModulateProgram->bind(); - glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); } } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 6c6bf261f9..950993a434 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -193,7 +193,6 @@ private: bool _voxelsDirty; static ProgramObject* _perlinModulateProgram; - static GLuint _permutationNormalTextureID; int _hookID; std::vector _freeIndexes; diff --git a/interface/src/avatar/Face.cpp b/interface/src/avatar/Face.cpp index ffc88d4b5b..9573cd4e4b 100644 --- a/interface/src/avatar/Face.cpp +++ b/interface/src/avatar/Face.cpp @@ -22,10 +22,10 @@ using namespace cv; -ProgramObject* Face::_program = 0; -int Face::_texCoordCornerLocation; -int Face::_texCoordRightLocation; -int Face::_texCoordUpLocation; +ProgramObject* Face::_videoProgram = 0; +Face::Locations Face::_videoProgramLocations; +ProgramObject* Face::_texturedProgram = 0; +Face::Locations Face::_texturedProgramLocations; GLuint Face::_vboID; GLuint Face::_iboID; @@ -71,6 +71,7 @@ void Face::setFrameFromWebcam() { void Face::clearFrame() { _colorTextureID = 0; + _depthTextureID = 0; } int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) { @@ -119,120 +120,130 @@ int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) { _lastFullFrame = fullFrame; } - if (_colorCodec.name == 0) { - // initialize decoder context - vpx_codec_dec_init(&_colorCodec, vpx_codec_vp8_dx(), 0, 0); + // read the color data, if non-empty + Mat color; + const uint8_t* colorData = (const uint8_t*)(_arrivingFrame.constData() + sizeof(float) + sizeof(size_t)); + size_t colorSize = *(const size_t*)(_arrivingFrame.constData() + sizeof(float)); + if (colorSize > 0) { + if (_colorCodec.name == 0) { + // initialize decoder context + vpx_codec_dec_init(&_colorCodec, vpx_codec_vp8_dx(), 0, 0); + } + vpx_codec_decode(&_colorCodec, colorData, colorSize, 0, 0); + vpx_codec_iter_t iterator = 0; + vpx_image_t* image; + while ((image = vpx_codec_get_frame(&_colorCodec, &iterator)) != 0) { + // convert from YV12 to RGB: see http://www.fourcc.org/yuv.php and + // http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor + color.create(image->d_h, image->d_w, CV_8UC3); + uchar* yline = image->planes[0]; + uchar* vline = image->planes[1]; + uchar* uline = image->planes[2]; + const int RED_V_WEIGHT = (int)(1.403 * 256); + const int GREEN_V_WEIGHT = (int)(0.714 * 256); + const int GREEN_U_WEIGHT = (int)(0.344 * 256); + const int BLUE_U_WEIGHT = (int)(1.773 * 256); + for (int i = 0; i < image->d_h; i += 2) { + uchar* ysrc = yline; + uchar* vsrc = vline; + uchar* usrc = uline; + for (int j = 0; j < image->d_w; j += 2) { + uchar* tl = color.ptr(i, j); + uchar* tr = color.ptr(i, j + 1); + uchar* bl = color.ptr(i + 1, j); + uchar* br = color.ptr(i + 1, j + 1); + + int v = *vsrc++ - 128; + int u = *usrc++ - 128; + + int redOffset = (RED_V_WEIGHT * v) >> 8; + int greenOffset = (GREEN_V_WEIGHT * v + GREEN_U_WEIGHT * u) >> 8; + int blueOffset = (BLUE_U_WEIGHT * u) >> 8; + + int ytl = ysrc[0]; + int ytr = ysrc[1]; + int ybl = ysrc[image->w]; + int ybr = ysrc[image->w + 1]; + ysrc += 2; + + tl[0] = saturate_cast(ytl + redOffset); + tl[1] = saturate_cast(ytl - greenOffset); + tl[2] = saturate_cast(ytl + blueOffset); + + tr[0] = saturate_cast(ytr + redOffset); + tr[1] = saturate_cast(ytr - greenOffset); + tr[2] = saturate_cast(ytr + blueOffset); + + bl[0] = saturate_cast(ybl + redOffset); + bl[1] = saturate_cast(ybl - greenOffset); + bl[2] = saturate_cast(ybl + blueOffset); + + br[0] = saturate_cast(ybr + redOffset); + br[1] = saturate_cast(ybr - greenOffset); + br[2] = saturate_cast(ybr + blueOffset); + } + yline += image->stride[0] * 2; + vline += image->stride[1]; + uline += image->stride[2]; + } + } + } else if (_colorCodec.name != 0) { + vpx_codec_destroy(&_colorCodec); + _colorCodec.name = 0; } - size_t colorSize = *(const size_t*)(_arrivingFrame.constData() + sizeof(float)); - const uint8_t* colorData = (const uint8_t*)(_arrivingFrame.constData() + sizeof(float) + sizeof(size_t)); - vpx_codec_decode(&_colorCodec, colorData, colorSize, 0, 0); - vpx_codec_iter_t iterator = 0; - vpx_image_t* image; - while ((image = vpx_codec_get_frame(&_colorCodec, &iterator)) != 0) { - // convert from YV12 to RGB: see http://www.fourcc.org/yuv.php and - // http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor - Mat color(image->d_h, image->d_w, CV_8UC3); - uchar* yline = image->planes[0]; - uchar* vline = image->planes[1]; - uchar* uline = image->planes[2]; - const int RED_V_WEIGHT = (int)(1.403 * 256); - const int GREEN_V_WEIGHT = (int)(0.714 * 256); - const int GREEN_U_WEIGHT = (int)(0.344 * 256); - const int BLUE_U_WEIGHT = (int)(1.773 * 256); - for (int i = 0; i < image->d_h; i += 2) { - uchar* ysrc = yline; - uchar* vsrc = vline; - uchar* usrc = uline; - for (int j = 0; j < image->d_w; j += 2) { - uchar* tl = color.ptr(i, j); - uchar* tr = color.ptr(i, j + 1); - uchar* bl = color.ptr(i + 1, j); - uchar* br = color.ptr(i + 1, j + 1); - - int v = *vsrc++ - 128; - int u = *usrc++ - 128; - - int redOffset = (RED_V_WEIGHT * v) >> 8; - int greenOffset = (GREEN_V_WEIGHT * v + GREEN_U_WEIGHT * u) >> 8; - int blueOffset = (BLUE_U_WEIGHT * u) >> 8; - - int ytl = ysrc[0]; - int ytr = ysrc[1]; - int ybl = ysrc[image->w]; - int ybr = ysrc[image->w + 1]; - ysrc += 2; - - tl[0] = saturate_cast(ytl + redOffset); - tl[1] = saturate_cast(ytl - greenOffset); - tl[2] = saturate_cast(ytl + blueOffset); - - tr[0] = saturate_cast(ytr + redOffset); - tr[1] = saturate_cast(ytr - greenOffset); - tr[2] = saturate_cast(ytr + blueOffset); - - bl[0] = saturate_cast(ybl + redOffset); - bl[1] = saturate_cast(ybl - greenOffset); - bl[2] = saturate_cast(ybl + blueOffset); - - br[0] = saturate_cast(ybr + redOffset); - br[1] = saturate_cast(ybr - greenOffset); - br[2] = saturate_cast(ybr + blueOffset); - } - yline += image->stride[0] * 2; - vline += image->stride[1]; - uline += image->stride[2]; + // read the depth data, if non-empty + Mat depth; + const uint8_t* depthData = colorData + colorSize; + int depthSize = _arrivingFrame.size() - ((const char*)depthData - _arrivingFrame.constData()); + if (depthSize > 0) { + if (_depthCodec.name == 0) { + // initialize decoder context + vpx_codec_dec_init(&_depthCodec, vpx_codec_vp8_dx(), 0, 0); } - Mat depth; - - const uint8_t* depthData = colorData + colorSize; - int depthSize = _arrivingFrame.size() - ((const char*)depthData - _arrivingFrame.constData()); - if (depthSize > 0) { - if (_depthCodec.name == 0) { - // initialize decoder context - vpx_codec_dec_init(&_depthCodec, vpx_codec_vp8_dx(), 0, 0); - } - vpx_codec_decode(&_depthCodec, depthData, depthSize, 0, 0); - vpx_codec_iter_t iterator = 0; - vpx_image_t* image; - while ((image = vpx_codec_get_frame(&_depthCodec, &iterator)) != 0) { - depth.create(image->d_h, image->d_w, CV_8UC1); - uchar* yline = image->planes[0]; - uchar* vline = image->planes[1]; - const uchar EIGHT_BIT_MAXIMUM = 255; - const uchar MASK_THRESHOLD = 192; - for (int i = 0; i < image->d_h; i += 2) { - uchar* ysrc = yline; - uchar* vsrc = vline; - for (int j = 0; j < image->d_w; j += 2) { - if (*vsrc++ < MASK_THRESHOLD) { - *depth.ptr(i, j) = EIGHT_BIT_MAXIMUM; - *depth.ptr(i, j + 1) = EIGHT_BIT_MAXIMUM; - *depth.ptr(i + 1, j) = EIGHT_BIT_MAXIMUM; - *depth.ptr(i + 1, j + 1) = EIGHT_BIT_MAXIMUM; - - } else { - *depth.ptr(i, j) = ysrc[0]; - *depth.ptr(i, j + 1) = ysrc[1]; - *depth.ptr(i + 1, j) = ysrc[image->stride[0]]; - *depth.ptr(i + 1, j + 1) = ysrc[image->stride[0] + 1]; - } - ysrc += 2; + vpx_codec_decode(&_depthCodec, depthData, depthSize, 0, 0); + vpx_codec_iter_t iterator = 0; + vpx_image_t* image; + while ((image = vpx_codec_get_frame(&_depthCodec, &iterator)) != 0) { + depth.create(image->d_h, image->d_w, CV_8UC1); + uchar* yline = image->planes[0]; + uchar* vline = image->planes[1]; + const uchar EIGHT_BIT_MAXIMUM = 255; + const uchar MASK_THRESHOLD = 192; + for (int i = 0; i < image->d_h; i += 2) { + uchar* ysrc = yline; + uchar* vsrc = vline; + for (int j = 0; j < image->d_w; j += 2) { + if (*vsrc++ < MASK_THRESHOLD) { + *depth.ptr(i, j) = EIGHT_BIT_MAXIMUM; + *depth.ptr(i, j + 1) = EIGHT_BIT_MAXIMUM; + *depth.ptr(i + 1, j) = EIGHT_BIT_MAXIMUM; + *depth.ptr(i + 1, j + 1) = EIGHT_BIT_MAXIMUM; + + } else { + *depth.ptr(i, j) = ysrc[0]; + *depth.ptr(i, j + 1) = ysrc[1]; + *depth.ptr(i + 1, j) = ysrc[image->stride[0]]; + *depth.ptr(i + 1, j + 1) = ysrc[image->stride[0] + 1]; } - yline += image->stride[0] * 2; - vline += image->stride[1]; + ysrc += 2; } + yline += image->stride[0] * 2; + vline += image->stride[1]; } } - QMetaObject::invokeMethod(this, "setFrame", Q_ARG(cv::Mat, color), - Q_ARG(cv::Mat, depth), Q_ARG(float, aspectRatio)); + } else if (_depthCodec.name != 0) { + vpx_codec_destroy(&_depthCodec); + _depthCodec.name = 0; } + QMetaObject::invokeMethod(this, "setFrame", Q_ARG(cv::Mat, color), + Q_ARG(cv::Mat, depth), Q_ARG(float, aspectRatio)); return dataBytes; } bool Face::render(float alpha) { - if (_colorTextureID == 0 || _textureRect.size.area() == 0) { + if (!isActive()) { return false; } glPushMatrix(); @@ -275,20 +286,9 @@ bool Face::render(float alpha) { const int INDICES_PER_TRIANGLE = 3; const int INDEX_COUNT = QUAD_COUNT * TRIANGLES_PER_QUAD * INDICES_PER_TRIANGLE; - if (_program == 0) { - _program = new ProgramObject(); - _program->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/face.vert"); - _program->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/face.frag"); - _program->link(); - - _program->bind(); - _program->setUniformValue("depthTexture", 0); - _program->setUniformValue("colorTexture", 1); - _program->release(); - - _texCoordCornerLocation = _program->uniformLocation("texCoordCorner"); - _texCoordRightLocation = _program->uniformLocation("texCoordRight"); - _texCoordUpLocation = _program->uniformLocation("texCoordUp"); + if (_videoProgram == 0) { + _videoProgram = loadProgram(QString(), "colorTexture", _videoProgramLocations); + _texturedProgram = loadProgram("_textured", "permutationNormalTexture", _texturedProgramLocations); glGenBuffers(1, &_vboID); glBindBuffer(GL_ARRAY_BUFFER, _vboID); @@ -328,14 +328,23 @@ bool Face::render(float alpha) { glBindTexture(GL_TEXTURE_2D, _depthTextureID); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - _program->bind(); - _program->setUniformValue(_texCoordCornerLocation, + ProgramObject* program = _videoProgram; + Locations* locations = &_videoProgramLocations; + if (false && _colorTextureID != 0) { + glBindTexture(GL_TEXTURE_2D, _colorTextureID); + + } else { + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); + program = _texturedProgram; + locations = &_texturedProgramLocations; + } + program->bind(); + program->setUniformValue(locations->texCoordCorner, points[0].x / _textureSize.width, points[0].y / _textureSize.height); - _program->setUniformValue(_texCoordRightLocation, + program->setUniformValue(locations->texCoordRight, (points[3].x - points[0].x) / _textureSize.width, (points[3].y - points[0].y) / _textureSize.height); - _program->setUniformValue(_texCoordUpLocation, + program->setUniformValue(locations->texCoordUp, (points[1].x - points[0].x) / _textureSize.width, (points[1].y - points[0].y) / _textureSize.height); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, 0); @@ -357,7 +366,7 @@ bool Face::render(float alpha) { glDisableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); - _program->release(); + program->release(); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); @@ -392,32 +401,24 @@ void Face::cycleRenderMode() { } void Face::setFrame(const cv::Mat& color, const cv::Mat& depth, float aspectRatio) { - if (color.empty()) { - // release our textures, if any; there's no more video - if (_colorTextureID != 0) { - glDeleteTextures(1, &_colorTextureID); - _colorTextureID = 0; + Size2f textureSize; + if (!color.empty()) { + if (_colorTextureID == 0) { + glGenTextures(1, &_colorTextureID); } - if (_depthTextureID != 0) { - glDeleteTextures(1, &_depthTextureID); - _depthTextureID = 0; + glBindTexture(GL_TEXTURE_2D, _colorTextureID); + if (_textureSize.width != color.cols || _textureSize.height != color.rows) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, color.cols, color.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, color.ptr()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + textureSize = color.size(); + _textureRect = RotatedRect(Point2f(color.cols * 0.5f, color.rows * 0.5f), textureSize, 0.0f); + + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, color.cols, color.rows, GL_RGB, GL_UNSIGNED_BYTE, color.ptr()); } - return; - } - - if (_colorTextureID == 0) { - glGenTextures(1, &_colorTextureID); - } - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - bool recreateTextures = (_textureSize.width != color.cols || _textureSize.height != color.rows); - if (recreateTextures) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, color.cols, color.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, color.ptr()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - _textureSize = color.size(); - _textureRect = RotatedRect(Point2f(color.cols * 0.5f, color.rows * 0.5f), _textureSize, 0.0f); - - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, color.cols, color.rows, GL_RGB, GL_UNSIGNED_BYTE, color.ptr()); + } else if (_colorTextureID != 0) { + glDeleteTextures(1, &_colorTextureID); + _colorTextureID = 0; } if (!depth.empty()) { @@ -425,20 +426,25 @@ void Face::setFrame(const cv::Mat& color, const cv::Mat& depth, float aspectRati glGenTextures(1, &_depthTextureID); } glBindTexture(GL_TEXTURE_2D, _depthTextureID); - if (recreateTextures) { + if (_textureSize.width != depth.cols || _textureSize.height != depth.rows) { glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, depth.cols, depth.rows, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, depth.ptr()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + textureSize = depth.size(); + _textureRect = RotatedRect(Point2f(depth.cols * 0.5f, depth.rows * 0.5f), textureSize, 0.0f); } else { - glBindTexture(GL_TEXTURE_2D, _depthTextureID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, depth.cols, depth.rows, GL_LUMINANCE, GL_UNSIGNED_BYTE, depth.ptr()); } + } else if (_depthTextureID != 0) { + glDeleteTextures(1, &_depthTextureID); + _depthTextureID = 0; } glBindTexture(GL_TEXTURE_2D, 0); _aspectRatio = aspectRatio; + _textureSize = textureSize; } void Face::destroyCodecs() { @@ -451,3 +457,21 @@ void Face::destroyCodecs() { _depthCodec.name = 0; } } + +ProgramObject* Face::loadProgram(const QString& suffix, const char* secondTextureUniform, Locations& locations) { + ProgramObject* program = new ProgramObject(); + program->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/face" + suffix + ".vert"); + program->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/face" + suffix + ".frag"); + program->link(); + + program->bind(); + program->setUniformValue("depthTexture", 0); + program->setUniformValue(secondTextureUniform, 1); + program->release(); + + locations.texCoordCorner = program->uniformLocation("texCoordCorner"); + locations.texCoordRight = program->uniformLocation("texCoordRight"); + locations.texCoordUp = program->uniformLocation("texCoordUp"); + + return program; +} diff --git a/interface/src/avatar/Face.h b/interface/src/avatar/Face.h index 893318f186..5e82148f8d 100644 --- a/interface/src/avatar/Face.h +++ b/interface/src/avatar/Face.h @@ -30,7 +30,8 @@ public: Face(Head* owningHead); ~Face(); - bool isFullFrame() const { return _colorTextureID != 0 && _aspectRatio == FULL_FRAME_ASPECT; } + bool isActive() const { return _colorTextureID != 0 || _depthTextureID != 0; } + bool isFullFrame() const { return isActive() && _aspectRatio == FULL_FRAME_ASPECT; } void setFrameFromWebcam(); void clearFrame(); @@ -69,10 +70,20 @@ private: int _frameCount; int _frameBytesRemaining; - static ProgramObject* _program; - static int _texCoordCornerLocation; - static int _texCoordRightLocation; - static int _texCoordUpLocation; + struct Locations { + int texCoordCorner; + int texCoordRight; + int texCoordUp; + }; + + static ProgramObject* loadProgram(const QString& suffix, const char* secondTextureUniform, Locations& locations); + + static ProgramObject* _videoProgram; + static Locations _videoProgramLocations; + + static ProgramObject* _texturedProgram; + static Locations _texturedProgramLocations; + static GLuint _vboID; static GLuint _iboID; }; diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp new file mode 100644 index 0000000000..1c832a648e --- /dev/null +++ b/interface/src/renderer/TextureCache.cpp @@ -0,0 +1,45 @@ +// +// TextureCache.cpp +// interface +// +// Created by Andrzej Kapolka on 8/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +#include + +#include "TextureCache.h" + +TextureCache::TextureCache() : _permutationNormalTextureID(0) { +} + +TextureCache::~TextureCache() { + if (_permutationNormalTextureID != 0) { + glDeleteTextures(1, &_permutationNormalTextureID); + } +} + +GLuint TextureCache::getPermutationNormalTextureID() { + if (_permutationNormalTextureID == 0) { + glGenTextures(1, &_permutationNormalTextureID); + glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); + + // the first line consists of random permutation offsets + unsigned char data[256 * 2 * 3]; + for (int i = 0; i < 256 * 3; i++) { + data[i] = rand() % 256; + } + // the next, random unit normals + for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) { + glm::vec3 randvec = glm::sphericalRand(1.0f); + data[i] = ((randvec.x + 1.0f) / 2.0f) * 255.0f; + data[i + 1] = ((randvec.y + 1.0f) / 2.0f) * 255.0f; + data[i + 2] = ((randvec.z + 1.0f) / 2.0f) * 255.0f; + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, 0); + } + return _permutationNormalTextureID; +} diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h new file mode 100644 index 0000000000..9804f038ba --- /dev/null +++ b/interface/src/renderer/TextureCache.h @@ -0,0 +1,27 @@ +// +// TextureCache.h +// interface +// +// Created by Andrzej Kapolka on 8/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__TextureCache__ +#define __interface__TextureCache__ + +#include "InterfaceConfig.h" + +class TextureCache { +public: + + TextureCache(); + ~TextureCache(); + + GLuint getPermutationNormalTextureID(); + +private: + + GLuint _permutationNormalTextureID; +}; + +#endif /* defined(__interface__TextureCache__) */ From c93c6687bf33c4840b6f4ac665aa3cc4b55ffe56 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 13:48:30 -0700 Subject: [PATCH 23/35] fix build buster --- interface/src/VoxelFade.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/VoxelFade.cpp b/interface/src/VoxelFade.cpp index 9c102ba6c5..0bbcbeedc1 100644 --- a/interface/src/VoxelFade.cpp +++ b/interface/src/VoxelFade.cpp @@ -6,8 +6,7 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // -#include // Header File For The OpenGL32 Library -#include +#include "InterfaceConfig.h" #include From 2e5dade4138b0dc1453fe0d32485a2b5ff23ad53 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Tue, 6 Aug 2013 14:29:30 -0700 Subject: [PATCH 24/35] Rave demo changes per Ryan's request: Darken the world when you're in rave mode, but leave the avatars and effects un-darkened. Also fixed a warning in AvatarData.cpp initialization --- interface/src/Application.cpp | 2 ++ interface/src/avatar/Avatar.cpp | 9 +++++++++ interface/src/avatar/Avatar.h | 10 ++++++++++ interface/src/avatar/Hand.cpp | 2 ++ interface/src/avatar/Hand.h | 2 +- libraries/avatars/src/AvatarData.cpp | 4 ++-- 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58d5ce19c4..1142e9ebbe 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3067,6 +3067,8 @@ void Application::displaySide(Camera& whichCamera) { glEnable(GL_LIGHTING); } + _myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS); + if (_renderAvatarsOn->isChecked()) { // Render avatars of other nodes NodeList* nodeList = NodeList::getInstance(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c52e990605..f9b2e843a0 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1214,6 +1214,15 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { } } +void Avatar::renderScreenTint(ScreenTintLayer layer) { + + if (layer == SCREEN_TINT_BEFORE_AVATARS) { + if (_hand.isRaveGloveActive()) { + _hand.renderRaveGloveStage(); + } + } +} + void Avatar::resetBodyBalls() { for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 69629f1b83..1e5f9ce448 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -112,6 +112,15 @@ enum AvatarMode NUM_AVATAR_MODES }; +enum ScreenTintLayer +{ + SCREEN_TINT_BEFORE_LANDSCAPE = 0, + SCREEN_TINT_BEFORE_AVATARS, + SCREEN_TINT_BEFORE_MY_AVATAR, + SCREEN_TINT_AFTER_MY_AVATAR, + NUM_SCREEN_TINT_LAYERS +}; + class Avatar : public AvatarData { public: Avatar(Node* owningNode = NULL); @@ -128,6 +137,7 @@ public: void addBodyYaw(float bodyYaw) {_bodyYaw += bodyYaw;}; void addBodyYawDelta(float bodyYawDelta) {_bodyYawDelta += bodyYawDelta;} void render(bool lookingInMirror, bool renderAvatarBalls); + void renderScreenTint(ScreenTintLayer layer); //setters void setMousePressed (bool mousePressed ) { _mousePressed = mousePressed;} diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index b960f8e56b..484ce0de9a 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -174,6 +174,7 @@ void Hand::renderRaveGloveStage() { glm::vec3 v3 = headOrientation * (glm::vec3(-1.0f, 1.0f, 0.0f) * scale) + vc; glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBegin(GL_TRIANGLE_FAN); glColor4f(0.0f, 0.0f, 0.0f, 1.0f); @@ -185,6 +186,7 @@ void Hand::renderRaveGloveStage() { glVertex3fv((float*)&v3); glVertex3fv((float*)&v0); glEnd(); + glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); } } diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index d2a36b97b1..86995e2bdc 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -41,6 +41,7 @@ public: void reset(); void simulate(float deltaTime, bool isMine); void render(bool lookingInMirror); + void renderRaveGloveStage(); void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; } void updateRaveGloveParticles(float deltaTime); @@ -74,7 +75,6 @@ private: void activateNewRaveGloveMode(); - void renderRaveGloveStage(); void renderLeapHandSpheres(); void renderLeapHands(); void renderLeapHand(PalmData& hand); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6d5d0a6528..a02c55346c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -28,6 +28,7 @@ AvatarData::AvatarData(Node* owningNode) : _bodyPitch(0.0), _bodyRoll(0.0), _newScale(1.0f), + _leaderID(UNKNOWN_NODE_ID), _handState(0), _cameraPosition(0,0,0), _cameraOrientation(), @@ -41,8 +42,7 @@ AvatarData::AvatarData(Node* owningNode) : _wantLowResMoving(false), _wantOcclusionCulling(true), _headData(NULL), - _handData(NULL), - _leaderID(UNKNOWN_NODE_ID) + _handData(NULL) { } From 19941a4a63f52012f5f1aecf568997e49887971b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 14:51:46 -0700 Subject: [PATCH 25/35] fixed packets per second command line with new frame rate --- voxel-server/src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 4b44ec3a59..c6a8a61ca1 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -49,6 +49,7 @@ const float MAX_CUBE = 0.05f; const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps int PACKETS_PER_CLIENT_PER_INTERVAL = 20; const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels +const int INTERVALS_PER_SECOND = 1000 * 1000 / VOXEL_SEND_INTERVAL_USECS; const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; @@ -572,7 +573,7 @@ int main(int argc, const char * argv[]) { const char* PACKETS_PER_SECOND = "--packetsPerSecond"; const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); if (packetsPerSecond) { - PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10; + PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { PACKETS_PER_CLIENT_PER_INTERVAL = 1; } From facc9e1ee7a8c4bdb83a69ff2dc073aa01700531 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 14:55:40 -0700 Subject: [PATCH 26/35] add fade effect to voxel add and delete, fix crash with audio injector --- interface/src/Application.cpp | 159 +++++++++++++++++++--------------- interface/src/Application.h | 10 +++ 2 files changed, 100 insertions(+), 69 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dc1222a36e..3b43f3323f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3702,6 +3702,62 @@ void Application::shiftPaintingColor() { } +void Application::injectVoxelAddedSoundEffect() { + AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(11025); + + if (voxelInjector) { + voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); + //voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw()); + voxelInjector->setVolume (16 * pow (_mouseVoxel.s, 2) / .0000001); //255 is max, and also default value + + /* for (int i = 0; i + < 22050; i++) { + if (i % 4 == 0) { + voxelInjector->addSample(4000); + } else if (i % 4 == 1) { + voxelInjector->addSample(0); + } else if (i % 4 == 2) { + voxelInjector->addSample(-4000); + } else { + voxelInjector->addSample(0); + } + */ + + const float BIG_VOXEL_MIN_SIZE = .01f; + + for (int i = 0; i < 11025; i++) { + + /* + A440 square wave + if (sin(i * 2 * PIE / 50)>=0) { + voxelInjector->addSample(4000); + } else { + voxelInjector->addSample(-4000); + } + */ + + if (_mouseVoxel.s > BIG_VOXEL_MIN_SIZE) { + voxelInjector->addSample(20000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 200)))); + } else { + voxelInjector->addSample(16000 * sin(i / (1.5 * log (_mouseVoxel.s / .0001) * ((i + 11025) / 5512.5)))); //808 + } + } + + //voxelInjector->addSample(32500 * sin(i/(2 * 1 * ((i+5000)/5512.5)))); //80 + //voxelInjector->addSample(20000 * sin(i/(6 * (_mouseVoxel.s/.001) *((i+5512.5)/5512.5)))); //808 + //voxelInjector->addSample(20000 * sin(i/(6 * ((i+5512.5)/5512.5)))); //808 + //voxelInjector->addSample(4000 * sin(i * 2 * PIE /50)); //A440 sine wave + //voxelInjector->addSample(4000 * sin(i * 2 * PIE /50) * sin (i/500)); //A440 sine wave with amplitude modulation + + //FM library + //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(500*sin((i+1)/200)))); //FM 1 dubstep + //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(300*sin((i+1)/5.0)))); //FM 2 flange sweep + //voxelInjector->addSample(10000 * sin((i * 2 * PIE) /(500*sin((i+1)/500.0)))); //FM 3 resonant pulse + + AudioInjectionManager::threadInjector(voxelInjector); + } +} + bool Application::maybeEditVoxelUnderCursor() { if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) { if (_mouseVoxel.s != 0) { @@ -3712,65 +3768,35 @@ bool Application::maybeEditVoxelUnderCursor() { // create the voxel locally so it appears immediately _voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s, _mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, _destructiveAddVoxel->isChecked()); + + // Implement voxel fade effect + VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f); + const float VOXEL_BOUNDS_ADJUST = 0.01f; + float slightlyBigger = _mouseVoxel.s * VOXEL_BOUNDS_ADJUST; + fade.voxelDetails.x = _mouseVoxel.x - slightlyBigger; + fade.voxelDetails.y = _mouseVoxel.y - slightlyBigger; + fade.voxelDetails.z = _mouseVoxel.z - slightlyBigger; + fade.voxelDetails.s = _mouseVoxel.s + slightlyBigger + slightlyBigger; + _voxelFades.push_back(fade); + + // inject a sound effect + injectVoxelAddedSoundEffect(); // remember the position for drag detection _justEditedVoxel = true; - AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(11025); - voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); - //_myAvatar.getPosition() -// voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw()); - voxelInjector->setVolume (16 * pow (_mouseVoxel.s, 2) / .0000001); //255 is max, and also default value - - /* for (int i = 0; i - < 22050; i++) { - if (i % 4 == 0) { - voxelInjector->addSample(4000); - } else if (i % 4 == 1) { - voxelInjector->addSample(0); - } else if (i % 4 == 2) { - voxelInjector->addSample(-4000); - } else { - voxelInjector->addSample(0); - } - */ - - - const float BIG_VOXEL_MIN_SIZE = .01f; - - for (int i = 0; i < 11025; i++) { - - /* - A440 square wave - if (sin(i * 2 * PIE / 50)>=0) { - voxelInjector->addSample(4000); - } else { - voxelInjector->addSample(-4000); - } - */ - - if (_mouseVoxel.s > BIG_VOXEL_MIN_SIZE) { - voxelInjector->addSample(20000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 200)))); - } else { - voxelInjector->addSample(16000 * sin(i / (1.5 * log (_mouseVoxel.s / .0001) * ((i + 11025) / 5512.5)))); //808 - } - } - - //voxelInjector->addSample(32500 * sin(i/(2 * 1 * ((i+5000)/5512.5)))); //80 - //voxelInjector->addSample(20000 * sin(i/(6 * (_mouseVoxel.s/.001) *((i+5512.5)/5512.5)))); //808 - //voxelInjector->addSample(20000 * sin(i/(6 * ((i+5512.5)/5512.5)))); //808 - //voxelInjector->addSample(4000 * sin(i * 2 * PIE /50)); //A440 sine wave - //voxelInjector->addSample(4000 * sin(i * 2 * PIE /50) * sin (i/500)); //A440 sine wave with amplitude modulation - - //FM library - //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(500*sin((i+1)/200)))); //FM 1 dubstep - //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(300*sin((i+1)/5.0)))); //FM 2 flange sweep - //voxelInjector->addSample(10000 * sin((i * 2 * PIE) /(500*sin((i+1)/500.0)))); //FM 3 resonant pulse - - AudioInjectionManager::threadInjector(voxelInjector); } } else if (_deleteVoxelMode->isChecked()) { deleteVoxelUnderCursor(); + VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE); + const float VOXEL_BOUNDS_ADJUST = 0.01f; + float slightlyBigger = _mouseVoxel.s * VOXEL_BOUNDS_ADJUST; + fade.voxelDetails.x = _mouseVoxel.x - slightlyBigger; + fade.voxelDetails.y = _mouseVoxel.y - slightlyBigger; + fade.voxelDetails.z = _mouseVoxel.z - slightlyBigger; + fade.voxelDetails.s = _mouseVoxel.s + slightlyBigger + slightlyBigger; + _voxelFades.push_back(fade); + } else if (_eyedropperMode->isChecked()) { eyedropperVoxelUnderCursor(); } else { @@ -3785,17 +3811,20 @@ void Application::deleteVoxelUnderCursor() { // sending delete to the server is sufficient, server will send new version so we see updates soon enough sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, _mouseVoxel); AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(5000); - voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); -// voxelInjector->setBearing(0); //straight down the z axis - voxelInjector->setVolume (255); //255 is max, and also default value - - for (int i = 0; i < 5000; i++) { - voxelInjector->addSample(10000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 500.0)))); //FM 3 resonant pulse - //voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter + if (voxelInjector) { + voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); + //voxelInjector->setBearing(0); //straight down the z axis + voxelInjector->setVolume (255); //255 is max, and also default value + + + for (int i = 0; i < 5000; i++) { + voxelInjector->addSample(10000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 500.0)))); //FM 3 resonant pulse + //voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter + } + + AudioInjectionManager::threadInjector(voxelInjector); } - - AudioInjectionManager::threadInjector(voxelInjector); } // remember the position for drag detection _justEditedVoxel = true; @@ -3907,10 +3936,6 @@ void Application::nodeKilled(Node* node) { jurisditionDetails.x, jurisditionDetails.y, jurisditionDetails.z, jurisditionDetails.s); // Add the jurisditionDetails object to the list of "fade outs" - const float NODE_KILLED_RED = 1.0f; - const float NODE_KILLED_GREEN = 0.0f; - const float NODE_KILLED_BLUE = 0.0f; - VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE); fade.voxelDetails = jurisditionDetails; _voxelFades.push_back(fade); @@ -3937,10 +3962,6 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng jurisditionDetails.x, jurisditionDetails.y, jurisditionDetails.z, jurisditionDetails.s); // Add the jurisditionDetails object to the list of "fade outs" - const float NODE_ADDED_RED = 0.0f; - const float NODE_ADDED_GREEN = 1.0f; - const float NODE_ADDED_BLUE = 0.0f; - VoxelFade fade(VoxelFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE); fade.voxelDetails = jurisditionDetails; _voxelFades.push_back(fade); diff --git a/interface/src/Application.h b/interface/src/Application.h index e6abd5f8d9..68738e62c2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -60,6 +60,15 @@ class QWheelEvent; class Node; class ProgramObject; +static const float NODE_ADDED_RED = 0.0f; +static const float NODE_ADDED_GREEN = 1.0f; +static const float NODE_ADDED_BLUE = 0.0f; +static const float NODE_KILLED_RED = 1.0f; +static const float NODE_KILLED_GREEN = 0.0f; +static const float NODE_KILLED_BLUE = 0.0f; + + + class Application : public QApplication, public NodeListHook { Q_OBJECT @@ -240,6 +249,7 @@ private: void deleteVoxelUnderCursor(); void eyedropperVoxelUnderCursor(); void resetSensors(); + void injectVoxelAddedSoundEffect(); void setMenuShortcutsEnabled(bool enabled); From 558255ca3d4a5574e0d46cf07b0619598031fc85 Mon Sep 17 00:00:00 2001 From: atlante45 Date: Tue, 6 Aug 2013 16:13:31 -0700 Subject: [PATCH 27/35] - Made collision On by default --- interface/src/Application.cpp | 1 + interface/src/avatar/Avatar.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 454a691fd5..359975339d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1954,6 +1954,7 @@ void Application::initMenu() { optionsMenu->addAction("Webcam", &_webcam, SLOT(setEnabled(bool)))->setCheckable(true); optionsMenu->addAction("Toggle Skeleton Tracking", &_webcam, SLOT(setSkeletonTrackingOn(bool)))->setCheckable(true); (_wantCollisionsOn = optionsMenu->addAction("Turn collisions On", this, SLOT(toggleWantCollisionsOn())))->setCheckable(true); + _wantCollisionsOn->setChecked(true); optionsMenu->addAction("Cycle Webcam Send Mode", _webcam.getGrabber(), SLOT(cycleVideoSendMode())); optionsMenu->addAction("Go Home", this, SLOT(goHome()), Qt::CTRL | Qt::Key_G); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e16ab73c93..d695cb4759 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -101,6 +101,7 @@ Avatar::Avatar(Node* owningNode) : _lastCollisionPosition(0, 0, 0), _speedBrakes(false), _isThrustOn(false), + _isCollisionsOn(true), _leadingAvatar(NULL), _voxels(this) { From bd3c235fe4178d1e86c5b0cca27163164307dd99 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 6 Aug 2013 16:23:58 -0700 Subject: [PATCH 28/35] Switching between textured and untextured modes. --- .../resources/shaders/face_textured.frag | 1 + interface/src/Application.cpp | 3 +- interface/src/Webcam.cpp | 285 ++++++++++-------- interface/src/Webcam.h | 2 + interface/src/avatar/Face.cpp | 22 +- interface/src/avatar/Face.h | 1 + 6 files changed, 179 insertions(+), 135 deletions(-) diff --git a/interface/resources/shaders/face_textured.frag b/interface/resources/shaders/face_textured.frag index fefefc6817..2170074e25 100644 --- a/interface/resources/shaders/face_textured.frag +++ b/interface/resources/shaders/face_textured.frag @@ -72,6 +72,7 @@ void main(void) { // compute the specular component (sans exponent) based on the normal OpenGL lighting model float specular = max(0.0, dot(normalize(gl_LightSource[0].position.xyz + vec3(0.0, 0.0, 1.0)), normal)); + // the base color is a subtle marble texture produced by modulating the phase of a sine wave by perlin noise vec3 color = mix(vec3(1.0, 1.0, 1.0), vec3(0.75, 0.75, 0.75), sin(dot(position, vec3(25.0, 25.0, 25.0)) + 2.0 * perlin(position * 10.0))); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 66f414d38d..1077eda7d9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1943,8 +1943,9 @@ void Application::initMenu() { _testPing->setChecked(true); (_fullScreenMode = optionsMenu->addAction("Fullscreen", this, SLOT(setFullscreen(bool)), Qt::Key_F))->setCheckable(true); optionsMenu->addAction("Webcam", &_webcam, SLOT(setEnabled(bool)))->setCheckable(true); - optionsMenu->addAction("Toggle Skeleton Tracking", &_webcam, SLOT(setSkeletonTrackingOn(bool)))->setCheckable(true); + optionsMenu->addAction("Skeleton Tracking", &_webcam, SLOT(setSkeletonTrackingOn(bool)))->setCheckable(true); optionsMenu->addAction("Cycle Webcam Send Mode", _webcam.getGrabber(), SLOT(cycleVideoSendMode())); + optionsMenu->addAction("Webcam Texture", _webcam.getGrabber(), SLOT(setDepthOnly(bool)))->setCheckable(true); optionsMenu->addAction("Go Home", this, SLOT(goHome()), Qt::CTRL | Qt::Key_G); QMenu* audioMenu = menuBar->addMenu("Audio"); diff --git a/interface/src/Webcam.cpp b/interface/src/Webcam.cpp index 4d2edcac37..0deae62e46 100644 --- a/interface/src/Webcam.cpp +++ b/interface/src/Webcam.cpp @@ -71,26 +71,28 @@ void Webcam::reset() { } void Webcam::renderPreview(int screenWidth, int screenHeight) { - if (_enabled && _colorTextureID != 0) { - glBindTexture(GL_TEXTURE_2D, _colorTextureID); + if (_enabled) { glEnable(GL_TEXTURE_2D); glColor3f(1.0f, 1.0f, 1.0f); - glBegin(GL_QUADS); - const int PREVIEW_HEIGHT = 200; - int previewWidth = _textureSize.width * PREVIEW_HEIGHT / _textureSize.height; - int top = screenHeight - 600; - int left = screenWidth - previewWidth - 10; - - glTexCoord2f(0, 0); - glVertex2f(left, top); - glTexCoord2f(1, 0); - glVertex2f(left + previewWidth, top); - glTexCoord2f(1, 1); - glVertex2f(left + previewWidth, top + PREVIEW_HEIGHT); - glTexCoord2f(0, 1); - glVertex2f(left, top + PREVIEW_HEIGHT); - glEnd(); - + + const int PREVIEW_HEIGHT = 200; + int previewWidth = _textureSize.width * PREVIEW_HEIGHT / _textureSize.height; + int top = screenHeight - 600; + int left = screenWidth - previewWidth - 10; + if (_colorTextureID != 0) { + glBindTexture(GL_TEXTURE_2D, _colorTextureID); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(left, top); + glTexCoord2f(1, 0); + glVertex2f(left + previewWidth, top); + glTexCoord2f(1, 1); + glVertex2f(left + previewWidth, top + PREVIEW_HEIGHT); + glTexCoord2f(0, 1); + glVertex2f(left, top + PREVIEW_HEIGHT); + glEnd(); + } + if (_depthTextureID != 0) { glBindTexture(GL_TEXTURE_2D, _depthTextureID); glBegin(GL_QUADS); @@ -157,22 +159,26 @@ const float METERS_PER_MM = 1.0f / 1000.0f; void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midFaceDepth, float aspectRatio, const RotatedRect& faceRect, bool sending, const JointVector& joints) { - IplImage colorImage = color; - glPixelStorei(GL_UNPACK_ROW_LENGTH, colorImage.widthStep / 3); - if (_colorTextureID == 0) { - glGenTextures(1, &_colorTextureID); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureSize.width = colorImage.width, _textureSize.height = colorImage.height, - 0, format, GL_UNSIGNED_BYTE, colorImage.imageData); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qDebug("Capturing video at %gx%g.\n", _textureSize.width, _textureSize.height); - - } else { - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _textureSize.width, _textureSize.height, format, - GL_UNSIGNED_BYTE, colorImage.imageData); + if (!color.empty()) { + IplImage colorImage = color; + glPixelStorei(GL_UNPACK_ROW_LENGTH, colorImage.widthStep / 3); + if (_colorTextureID == 0) { + glGenTextures(1, &_colorTextureID); + glBindTexture(GL_TEXTURE_2D, _colorTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureSize.width = colorImage.width, _textureSize.height = colorImage.height, + 0, format, GL_UNSIGNED_BYTE, colorImage.imageData); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + } else { + glBindTexture(GL_TEXTURE_2D, _colorTextureID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _textureSize.width, _textureSize.height, format, + GL_UNSIGNED_BYTE, colorImage.imageData); + } + } else if (_colorTextureID != 0) { + glDeleteTextures(1, &_colorTextureID); + _colorTextureID = 0; } - + if (!depth.empty()) { IplImage depthImage = depth; glPixelStorei(GL_UNPACK_ROW_LENGTH, depthImage.widthStep); @@ -189,6 +195,9 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midF glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _textureSize.width, _textureSize.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, depthImage.imageData); } + } else if (_depthTextureID != 0) { + glDeleteTextures(1, &_depthTextureID); + _depthTextureID = 0; } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glBindTexture(GL_TEXTURE_2D, 0); @@ -273,8 +282,8 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midF QTimer::singleShot(qMax((int)remaining / 1000, 0), _grabber, SLOT(grabFrame())); } -FrameGrabber::FrameGrabber() : _initialized(false), _videoSendMode(FULL_FRAME_VIDEO), _capture(0), _searchWindow(0, 0, 0, 0), - _smoothedMidFaceDepth(UNINITIALIZED_FACE_DEPTH), _colorCodec(), _depthCodec(), _frameCount(0) { +FrameGrabber::FrameGrabber() : _initialized(false), _videoSendMode(FULL_FRAME_VIDEO), _depthOnly(false), _capture(0), + _searchWindow(0, 0, 0, 0), _smoothedMidFaceDepth(UNINITIALIZED_FACE_DEPTH), _colorCodec(), _depthCodec(), _frameCount(0) { } FrameGrabber::~FrameGrabber() { @@ -374,6 +383,11 @@ void FrameGrabber::cycleVideoSendMode() { destroyCodecs(); } +void FrameGrabber::setDepthOnly(bool depthOnly) { + _depthOnly = depthOnly; + destroyCodecs(); +} + void FrameGrabber::reset() { _searchWindow = cv::Rect(0, 0, 0, 0); @@ -479,7 +493,7 @@ void FrameGrabber::grabFrame() { encodedWidth = color.cols; encodedHeight = color.rows; aspectRatio = FULL_FRAME_ASPECT; - colorBitrateMultiplier = 4.0f; + colorBitrateMultiplier = depthBitrateMultiplier = 4.0f; } else { // if we don't have a search window (yet), try using the face cascade @@ -591,108 +605,129 @@ void FrameGrabber::grabFrame() { depth.convertTo(_grayDepthFrame, CV_8UC1, 1.0, depthOffset); } - QByteArray payload; + // increment the frame count that identifies frames + _frameCount++; + + QByteArray payload; if (_videoSendMode != NO_VIDEO) { - if (_colorCodec.name == 0) { - // initialize encoder context(s) - vpx_codec_enc_cfg_t codecConfig; - vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &codecConfig, 0); - codecConfig.rc_target_bitrate = ENCODED_FACE_WIDTH * ENCODED_FACE_HEIGHT * colorBitrateMultiplier * - codecConfig.rc_target_bitrate / codecConfig.g_w / codecConfig.g_h; - codecConfig.g_w = encodedWidth; - codecConfig.g_h = encodedHeight; - vpx_codec_enc_init(&_colorCodec, vpx_codec_vp8_cx(), &codecConfig, 0); - - if (!depth.empty()) { - codecConfig.rc_target_bitrate *= depthBitrateMultiplier; - vpx_codec_enc_init(&_depthCodec, vpx_codec_vp8_cx(), &codecConfig, 0); - } - } - - Mat transform; - if (_videoSendMode == FACE_VIDEO) { - // resize/rotate face into encoding rectangle - _faceColor.create(encodedHeight, encodedWidth, CV_8UC3); - warpAffine(color, _faceColor, faceTransform, _faceColor.size()); - - } else { - _faceColor = color; - } - - // convert from RGB to YV12: see http://www.fourcc.org/yuv.php and - // http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor + // start the payload off with the aspect ratio (zero for full frame) + payload.append((const char*)&aspectRatio, sizeof(float)); + + // prepare the image in which we'll store the data const int ENCODED_BITS_PER_Y = 8; const int ENCODED_BITS_PER_VU = 2; const int ENCODED_BITS_PER_PIXEL = ENCODED_BITS_PER_Y + 2 * ENCODED_BITS_PER_VU; const int BITS_PER_BYTE = 8; _encodedFace.resize(encodedWidth * encodedHeight * ENCODED_BITS_PER_PIXEL / BITS_PER_BYTE); vpx_image_t vpxImage; - vpx_img_wrap(&vpxImage, VPX_IMG_FMT_YV12, encodedWidth, encodedHeight, 1, - (unsigned char*)_encodedFace.data()); - uchar* yline = vpxImage.planes[0]; - uchar* vline = vpxImage.planes[1]; - uchar* uline = vpxImage.planes[2]; - const int Y_RED_WEIGHT = (int)(0.299 * 256); - const int Y_GREEN_WEIGHT = (int)(0.587 * 256); - const int Y_BLUE_WEIGHT = (int)(0.114 * 256); - const int V_RED_WEIGHT = (int)(0.713 * 256); - const int U_BLUE_WEIGHT = (int)(0.564 * 256); - int redIndex = 0; - int greenIndex = 1; - int blueIndex = 2; - if (format == GL_BGR) { - redIndex = 2; - blueIndex = 0; - } - for (int i = 0; i < encodedHeight; i += 2) { - uchar* ydest = yline; - uchar* vdest = vline; - uchar* udest = uline; - for (int j = 0; j < encodedWidth; j += 2) { - uchar* tl = _faceColor.ptr(i, j); - uchar* tr = _faceColor.ptr(i, j + 1); - uchar* bl = _faceColor.ptr(i + 1, j); - uchar* br = _faceColor.ptr(i + 1, j + 1); - - ydest[0] = (tl[redIndex] * Y_RED_WEIGHT + tl[1] * Y_GREEN_WEIGHT + tl[blueIndex] * Y_BLUE_WEIGHT) >> 8; - ydest[1] = (tr[redIndex] * Y_RED_WEIGHT + tr[1] * Y_GREEN_WEIGHT + tr[blueIndex] * Y_BLUE_WEIGHT) >> 8; - ydest[vpxImage.stride[0]] = (bl[redIndex] * Y_RED_WEIGHT + bl[greenIndex] * - Y_GREEN_WEIGHT + bl[blueIndex] * Y_BLUE_WEIGHT) >> 8; - ydest[vpxImage.stride[0] + 1] = (br[redIndex] * Y_RED_WEIGHT + br[greenIndex] * - Y_GREEN_WEIGHT + br[blueIndex] * Y_BLUE_WEIGHT) >> 8; - ydest += 2; - - int totalRed = tl[redIndex] + tr[redIndex] + bl[redIndex] + br[redIndex]; - int totalGreen = tl[greenIndex] + tr[greenIndex] + bl[greenIndex] + br[greenIndex]; - int totalBlue = tl[blueIndex] + tr[blueIndex] + bl[blueIndex] + br[blueIndex]; - int totalY = (totalRed * Y_RED_WEIGHT + totalGreen * Y_GREEN_WEIGHT + totalBlue * Y_BLUE_WEIGHT) >> 8; - - *vdest++ = (((totalRed - totalY) * V_RED_WEIGHT) >> 10) + 128; - *udest++ = (((totalBlue - totalY) * U_BLUE_WEIGHT) >> 10) + 128; + vpx_img_wrap(&vpxImage, VPX_IMG_FMT_YV12, encodedWidth, encodedHeight, 1, (unsigned char*)_encodedFace.data()); + + if (!_depthOnly || depth.empty()) { + if (_colorCodec.name == 0) { + // initialize encoder context + vpx_codec_enc_cfg_t codecConfig; + vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &codecConfig, 0); + codecConfig.rc_target_bitrate = ENCODED_FACE_WIDTH * ENCODED_FACE_HEIGHT * colorBitrateMultiplier * + codecConfig.rc_target_bitrate / codecConfig.g_w / codecConfig.g_h; + codecConfig.g_w = encodedWidth; + codecConfig.g_h = encodedHeight; + vpx_codec_enc_init(&_colorCodec, vpx_codec_vp8_cx(), &codecConfig, 0); } - yline += vpxImage.stride[0] * 2; - vline += vpxImage.stride[1]; - uline += vpxImage.stride[2]; - } - // encode the frame - vpx_codec_encode(&_colorCodec, &vpxImage, ++_frameCount, 1, 0, VPX_DL_REALTIME); + if (_videoSendMode == FACE_VIDEO) { + // resize/rotate face into encoding rectangle + _faceColor.create(encodedHeight, encodedWidth, CV_8UC3); + warpAffine(color, _faceColor, faceTransform, _faceColor.size()); - // start the payload off with the aspect ratio (zero for full frame) - payload.append((const char*)&aspectRatio, sizeof(float)); - - // extract the encoded frame - vpx_codec_iter_t iterator = 0; - const vpx_codec_cx_pkt_t* packet; - while ((packet = vpx_codec_get_cx_data(&_colorCodec, &iterator)) != 0) { - if (packet->kind == VPX_CODEC_CX_FRAME_PKT) { - // prepend the length, which will indicate whether there's a depth frame too - payload.append((const char*)&packet->data.frame.sz, sizeof(packet->data.frame.sz)); - payload.append((const char*)packet->data.frame.buf, packet->data.frame.sz); + } else { + _faceColor = color; } - } + // convert from RGB to YV12: see http://www.fourcc.org/yuv.php and + // http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor + uchar* yline = vpxImage.planes[0]; + uchar* vline = vpxImage.planes[1]; + uchar* uline = vpxImage.planes[2]; + const int Y_RED_WEIGHT = (int)(0.299 * 256); + const int Y_GREEN_WEIGHT = (int)(0.587 * 256); + const int Y_BLUE_WEIGHT = (int)(0.114 * 256); + const int V_RED_WEIGHT = (int)(0.713 * 256); + const int U_BLUE_WEIGHT = (int)(0.564 * 256); + int redIndex = 0; + int greenIndex = 1; + int blueIndex = 2; + if (format == GL_BGR) { + redIndex = 2; + blueIndex = 0; + } + for (int i = 0; i < encodedHeight; i += 2) { + uchar* ydest = yline; + uchar* vdest = vline; + uchar* udest = uline; + for (int j = 0; j < encodedWidth; j += 2) { + uchar* tl = _faceColor.ptr(i, j); + uchar* tr = _faceColor.ptr(i, j + 1); + uchar* bl = _faceColor.ptr(i + 1, j); + uchar* br = _faceColor.ptr(i + 1, j + 1); + + ydest[0] = (tl[redIndex] * Y_RED_WEIGHT + tl[1] * Y_GREEN_WEIGHT + tl[blueIndex] * Y_BLUE_WEIGHT) >> 8; + ydest[1] = (tr[redIndex] * Y_RED_WEIGHT + tr[1] * Y_GREEN_WEIGHT + tr[blueIndex] * Y_BLUE_WEIGHT) >> 8; + ydest[vpxImage.stride[0]] = (bl[redIndex] * Y_RED_WEIGHT + bl[greenIndex] * + Y_GREEN_WEIGHT + bl[blueIndex] * Y_BLUE_WEIGHT) >> 8; + ydest[vpxImage.stride[0] + 1] = (br[redIndex] * Y_RED_WEIGHT + br[greenIndex] * + Y_GREEN_WEIGHT + br[blueIndex] * Y_BLUE_WEIGHT) >> 8; + ydest += 2; + + int totalRed = tl[redIndex] + tr[redIndex] + bl[redIndex] + br[redIndex]; + int totalGreen = tl[greenIndex] + tr[greenIndex] + bl[greenIndex] + br[greenIndex]; + int totalBlue = tl[blueIndex] + tr[blueIndex] + bl[blueIndex] + br[blueIndex]; + int totalY = (totalRed * Y_RED_WEIGHT + totalGreen * Y_GREEN_WEIGHT + totalBlue * Y_BLUE_WEIGHT) >> 8; + + *vdest++ = (((totalRed - totalY) * V_RED_WEIGHT) >> 10) + 128; + *udest++ = (((totalBlue - totalY) * U_BLUE_WEIGHT) >> 10) + 128; + } + yline += vpxImage.stride[0] * 2; + vline += vpxImage.stride[1]; + uline += vpxImage.stride[2]; + } + + // encode the frame + vpx_codec_encode(&_colorCodec, &vpxImage, _frameCount, 1, 0, VPX_DL_REALTIME); + + // extract the encoded frame + vpx_codec_iter_t iterator = 0; + const vpx_codec_cx_pkt_t* packet; + while ((packet = vpx_codec_get_cx_data(&_colorCodec, &iterator)) != 0) { + if (packet->kind == VPX_CODEC_CX_FRAME_PKT) { + // prepend the length, which will indicate whether there's a depth frame too + payload.append((const char*)&packet->data.frame.sz, sizeof(packet->data.frame.sz)); + payload.append((const char*)packet->data.frame.buf, packet->data.frame.sz); + } + } + } else { + // zero length indicates no color info + const size_t ZERO_SIZE = 0; + payload.append((const char*)&ZERO_SIZE, sizeof(size_t)); + + // we can use more bits for depth + depthBitrateMultiplier *= 2.0f; + + // don't bother reporting the color + color = Mat(); + } + if (!depth.empty()) { + if (_depthCodec.name == 0) { + // initialize encoder context + vpx_codec_enc_cfg_t codecConfig; + vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &codecConfig, 0); + codecConfig.rc_target_bitrate = ENCODED_FACE_WIDTH * ENCODED_FACE_HEIGHT * depthBitrateMultiplier * + codecConfig.rc_target_bitrate / codecConfig.g_w / codecConfig.g_h; + codecConfig.g_w = encodedWidth; + codecConfig.g_h = encodedHeight; + vpx_codec_enc_init(&_depthCodec, vpx_codec_vp8_cx(), &codecConfig, 0); + } + // convert with mask uchar* yline = vpxImage.planes[0]; uchar* vline = vpxImage.planes[1]; diff --git a/interface/src/Webcam.h b/interface/src/Webcam.h index aee87e1bc7..16b9339eb0 100644 --- a/interface/src/Webcam.h +++ b/interface/src/Webcam.h @@ -112,6 +112,7 @@ public: public slots: void cycleVideoSendMode(); + void setDepthOnly(bool depthOnly); void reset(); void shutdown(); void grabFrame(); @@ -126,6 +127,7 @@ private: bool _initialized; VideoSendMode _videoSendMode; + bool _depthOnly; CvCapture* _capture; cv::CascadeClassifier _faceCascade; cv::Mat _hsvFrame; diff --git a/interface/src/avatar/Face.cpp b/interface/src/avatar/Face.cpp index 9573cd4e4b..22ce3c0727 100644 --- a/interface/src/avatar/Face.cpp +++ b/interface/src/avatar/Face.cpp @@ -112,18 +112,20 @@ int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) { return dataBytes; } - // the switch from full frame to not (or vice versa) requires us to reinit the codecs + // the switch between full frame or depth only modes requires us to reinit the codecs float aspectRatio = *(const float*)_arrivingFrame.constData(); + size_t colorSize = *(const size_t*)(_arrivingFrame.constData() + sizeof(float)); bool fullFrame = (aspectRatio == FULL_FRAME_ASPECT); - if (fullFrame != _lastFullFrame) { + bool depthOnly = (colorSize == 0); + if (fullFrame != _lastFullFrame || depthOnly != _lastDepthOnly) { destroyCodecs(); _lastFullFrame = fullFrame; + _lastDepthOnly = depthOnly; } // read the color data, if non-empty Mat color; const uint8_t* colorData = (const uint8_t*)(_arrivingFrame.constData() + sizeof(float) + sizeof(size_t)); - size_t colorSize = *(const size_t*)(_arrivingFrame.constData() + sizeof(float)); if (colorSize > 0) { if (_colorCodec.name == 0) { // initialize decoder context @@ -331,7 +333,7 @@ bool Face::render(float alpha) { ProgramObject* program = _videoProgram; Locations* locations = &_videoProgramLocations; - if (false && _colorTextureID != 0) { + if (_colorTextureID != 0) { glBindTexture(GL_TEXTURE_2D, _colorTextureID); } else { @@ -401,13 +403,14 @@ void Face::cycleRenderMode() { } void Face::setFrame(const cv::Mat& color, const cv::Mat& depth, float aspectRatio) { - Size2f textureSize; + Size2f textureSize = _textureSize; if (!color.empty()) { - if (_colorTextureID == 0) { + bool generate = (_colorTextureID == 0); + if (generate) { glGenTextures(1, &_colorTextureID); } glBindTexture(GL_TEXTURE_2D, _colorTextureID); - if (_textureSize.width != color.cols || _textureSize.height != color.rows) { + if (_textureSize.width != color.cols || _textureSize.height != color.rows || generate) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, color.cols, color.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, color.ptr()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); textureSize = color.size(); @@ -422,11 +425,12 @@ void Face::setFrame(const cv::Mat& color, const cv::Mat& depth, float aspectRati } if (!depth.empty()) { - if (_depthTextureID == 0) { + bool generate = (_depthTextureID == 0); + if (generate) { glGenTextures(1, &_depthTextureID); } glBindTexture(GL_TEXTURE_2D, _depthTextureID); - if (_textureSize.width != depth.cols || _textureSize.height != depth.rows) { + if (_textureSize.width != depth.cols || _textureSize.height != depth.rows || generate) { glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, depth.cols, depth.rows, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, depth.ptr()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/interface/src/avatar/Face.h b/interface/src/avatar/Face.h index 5e82148f8d..f3e681ff72 100644 --- a/interface/src/avatar/Face.h +++ b/interface/src/avatar/Face.h @@ -65,6 +65,7 @@ private: vpx_codec_ctx_t _colorCodec; vpx_codec_ctx_t _depthCodec; bool _lastFullFrame; + bool _lastDepthOnly; QByteArray _arrivingFrame; int _frameCount; From 23461c2e95a26fa12dacfb06d6e1fd016898f055 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 16:26:48 -0700 Subject: [PATCH 29/35] fixed crash --- libraries/shared/src/OctalCode.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index eeea3385e9..5513d362ac 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -118,17 +118,19 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber void voxelDetailsForCode(unsigned char * octalCode, VoxelPositionSize& voxelPositionSize) { float output[3]; memset(&output[0], 0, 3 * sizeof(float)); - float currentScale = 1.0; - - for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { - currentScale *= 0.5; - int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8); + + if (octalCode) { + for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { + currentScale *= 0.5; + int sectionIndex = sectionValue(octalCode + 1 + (BITS_IN_OCTAL * i / BITS_IN_BYTE), + (BITS_IN_OCTAL * i) % BITS_IN_BYTE); + + for (int j = 0; j < BITS_IN_OCTAL; j++) { + output[j] += currentScale * (int)oneAtBit(sectionIndex, (BITS_IN_BYTE - BITS_IN_OCTAL) + j); + } - for (int j = 0; j < 3; j++) { - output[j] += currentScale * (int)oneAtBit(sectionIndex, 5 + j); } - } voxelPositionSize.x = output[0]; voxelPositionSize.y = output[1]; From 378cb343aeb9874d34479683a4f6a50fe4d12385 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Tue, 6 Aug 2013 16:45:15 -0700 Subject: [PATCH 30/35] Rave tweaks per Ryan's request: Mood lighting for the avatars. This also sets us up to have light coming from the effects, if we want. --- interface/src/Application.cpp | 42 ++++++++++++++++++++------------- interface/src/Application.h | 1 + interface/src/avatar/Avatar.cpp | 18 +++++++++++++- interface/src/avatar/Avatar.h | 4 ++-- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 359975339d..01e2ebfb43 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2935,6 +2935,27 @@ void Application::displayOculus(Camera& whichCamera) { glPopMatrix(); } +void Application::setupWorldLight(Camera& whichCamera) { + + // Setup 3D lights (after the camera transform, so that they are positioned in world space) + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + + glm::vec3 relativeSunLoc = glm::normalize(_environment.getClosestData(whichCamera.getPosition()).getSunLocation() - + whichCamera.getPosition()); + GLfloat light_position0[] = { relativeSunLoc.x, relativeSunLoc.y, relativeSunLoc.z, 0.0 }; + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + GLfloat ambient_color[] = { 0.7, 0.7, 0.8 }; + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color); + GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 }; + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color); + GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0}; + glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color); + + glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); + glMateriali(GL_FRONT, GL_SHININESS, 96); +} + void Application::displaySide(Camera& whichCamera) { // transform by eye offset @@ -2964,22 +2985,7 @@ void Application::displaySide(Camera& whichCamera) { glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z); // Setup 3D lights (after the camera transform, so that they are positioned in world space) - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - - glm::vec3 relativeSunLoc = glm::normalize(_environment.getClosestData(whichCamera.getPosition()).getSunLocation() - - whichCamera.getPosition()); - GLfloat light_position0[] = { relativeSunLoc.x, relativeSunLoc.y, relativeSunLoc.z, 0.0 }; - glLightfv(GL_LIGHT0, GL_POSITION, light_position0); - GLfloat ambient_color[] = { 0.7, 0.7, 0.8 }; - glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color); - GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 }; - glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color); - GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0}; - glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color); - - glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); - glMateriali(GL_FRONT, GL_SHININESS, 96); + setupWorldLight(whichCamera); if (_renderStarsOn->isChecked()) { if (!_stars.getFileLoaded()) { @@ -3074,7 +3080,7 @@ void Application::displaySide(Camera& whichCamera) { glEnable(GL_LIGHTING); } - _myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS); + _myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS, whichCamera); if (_renderAvatarsOn->isChecked()) { // Render avatars of other nodes @@ -3110,6 +3116,8 @@ void Application::displaySide(Camera& whichCamera) { } } + _myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS, whichCamera); + if (_renderParticleSystemOn->isChecked()) { if (_particleSystemInitialized) { _particleSystem.render(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 249f6f082f..6cb8f0a620 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -118,6 +118,7 @@ public: GeometryCache* getGeometryCache() { return &_geometryCache; } void resetSongMixMenuItem(); + void setupWorldLight(Camera& whichCamera); virtual void nodeAdded(Node* node); virtual void nodeKilled(Node* node); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index d695cb4759..322f5adc64 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1220,11 +1220,27 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { } } -void Avatar::renderScreenTint(ScreenTintLayer layer) { +void Avatar::renderScreenTint(ScreenTintLayer layer, Camera& whichCamera) { if (layer == SCREEN_TINT_BEFORE_AVATARS) { if (_hand.isRaveGloveActive()) { _hand.renderRaveGloveStage(); + + // Set some mood lighting + GLfloat ambient_color[] = { 0.0, 0.0, 0.0 }; + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color); + GLfloat diffuse_color[] = { 0.4, 0.0, 0.0 }; + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color); + GLfloat specular_color[] = { 0.0, 0.0, 0.0, 0.0}; + glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color); + glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); + glMateriali(GL_FRONT, GL_SHININESS, 0); + } + } + else if (layer == SCREEN_TINT_BEFORE_AVATARS) { + if (_hand.isRaveGloveActive()) { + // Restore the world lighting + Application::getInstance()->setupWorldLight(whichCamera); } } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 91788cad32..ab122ee81b 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -117,7 +117,7 @@ enum ScreenTintLayer SCREEN_TINT_BEFORE_LANDSCAPE = 0, SCREEN_TINT_BEFORE_AVATARS, SCREEN_TINT_BEFORE_MY_AVATAR, - SCREEN_TINT_AFTER_MY_AVATAR, + SCREEN_TINT_AFTER_AVATARS, NUM_SCREEN_TINT_LAYERS }; @@ -136,7 +136,7 @@ public: void addBodyYaw(float bodyYaw) {_bodyYaw += bodyYaw;}; void addBodyYawDelta(float bodyYawDelta) {_bodyYawDelta += bodyYawDelta;} void render(bool lookingInMirror, bool renderAvatarBalls); - void renderScreenTint(ScreenTintLayer layer); + void renderScreenTint(ScreenTintLayer layer, Camera& whichCamera); //setters void setMousePressed (bool mousePressed ) { _mousePressed = mousePressed;} From 35465686db3246e06544d90f181575374707ff52 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Tue, 6 Aug 2013 17:39:56 -0700 Subject: [PATCH 31/35] Rave tweaks: Use separate light settings for avatars and particles --- interface/src/avatar/Avatar.cpp | 14 ++++---------- interface/src/avatar/Hand.cpp | 28 ++++++++++++++++++++++++++++ interface/src/avatar/Hand.h | 6 ++++++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 322f5adc64..1f1609d401 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1159,6 +1159,10 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { glPopMatrix(); } + if (Application::getInstance()->getAvatar()->getHand().isRaveGloveActive()) { + _hand.setRaveLights(RAVE_LIGHTS_AVATAR); + } + // render a simple round on the ground projected down from the avatar's position renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), _scale * 0.1f, 0.2f); @@ -1225,16 +1229,6 @@ void Avatar::renderScreenTint(ScreenTintLayer layer, Camera& whichCamera) { if (layer == SCREEN_TINT_BEFORE_AVATARS) { if (_hand.isRaveGloveActive()) { _hand.renderRaveGloveStage(); - - // Set some mood lighting - GLfloat ambient_color[] = { 0.0, 0.0, 0.0 }; - glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color); - GLfloat diffuse_color[] = { 0.4, 0.0, 0.0 }; - glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color); - GLfloat specular_color[] = { 0.0, 0.0, 0.0, 0.0}; - glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color); - glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); - glMateriali(GL_FRONT, GL_SHININESS, 0); } } else if (layer == SCREEN_TINT_BEFORE_AVATARS) { diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 484ce0de9a..e274e64e1a 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -145,6 +145,9 @@ void Hand::render(bool lookingInMirror) { if (_raveGloveInitialized) { updateRaveGloveEmitters(); // do this after calculateGeometry + + // Use normal lighting for the particles + setRaveLights(RAVE_LIGHTS_PARTICLES); _raveGloveParticleSystem.render(); } } @@ -161,6 +164,31 @@ void Hand::render(bool lookingInMirror) { } } +void Hand::setRaveLights(RaveLightsSetting setting) { + if (setting == RAVE_LIGHTS_AVATAR) { + // Set some mood lighting + GLfloat ambient_color[] = { 0.0, 0.0, 0.0 }; + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color); + GLfloat diffuse_color[] = { 0.4, 0.0, 0.0 }; + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color); + GLfloat specular_color[] = { 0.0, 0.0, 0.0, 0.0}; + glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color); + glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); + glMateriali(GL_FRONT, GL_SHININESS, 0); + } + else if (setting == RAVE_LIGHTS_PARTICLES) { + // particles use a brighter light setting + GLfloat ambient_color[] = { 0.7, 0.7, 0.8 }; + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color); + GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 }; + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color); + GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0}; + glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color); + glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); + glMateriali(GL_FRONT, GL_SHININESS, 96); + } +} + void Hand::renderRaveGloveStage() { if (_owningAvatar && _owningAvatar->isMyAvatar()) { Head& head = _owningAvatar->getHead(); diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 86995e2bdc..54a2b2e8a3 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -20,6 +20,11 @@ #include #include +enum RaveLightsSetting { + RAVE_LIGHTS_AVATAR = 0, + RAVE_LIGHTS_PARTICLES +}; + class Avatar; class ProgramObject; @@ -42,6 +47,7 @@ public: void simulate(float deltaTime, bool isMine); void render(bool lookingInMirror); void renderRaveGloveStage(); + void setRaveLights(RaveLightsSetting setting); void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; } void updateRaveGloveParticles(float deltaTime); From 24ec0b0ddc9a11b510d38399509fadb86d29e792 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 19:15:05 -0700 Subject: [PATCH 32/35] fixed packet header bug in createVoxelEditMessage() --- libraries/shared/src/SharedUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 93ea8a70ed..cf2374b84e 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -215,7 +215,6 @@ bool createVoxelEditMessage(unsigned char command, short int sequence, bool success = true; // assume the best int messageSize = MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE; // just a guess for now - int actualMessageSize = 3; unsigned char* messageBuffer = new unsigned char[messageSize]; int numBytesPacketHeader = populateTypeAndVersion(messageBuffer, command); @@ -223,6 +222,7 @@ bool createVoxelEditMessage(unsigned char command, short int sequence, *sequenceAt = sequence; unsigned char* copyAt = &messageBuffer[numBytesPacketHeader + sizeof(sequence)]; + int actualMessageSize = numBytesPacketHeader + sizeof(sequence); for (int i = 0; i < voxelCount && success; i++) { // get the coded voxel @@ -232,7 +232,7 @@ bool createVoxelEditMessage(unsigned char command, short int sequence, int lengthOfVoxelData = bytesRequiredForCodeLength(*voxelData)+SIZE_OF_COLOR_DATA; // make sure we have room to copy this voxel - if (actualMessageSize+lengthOfVoxelData > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) { + if (actualMessageSize + lengthOfVoxelData > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) { success = false; } else { // add it to our message From a5f472254d7758c3e342ae073ec94bad5ee0a989 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 19:15:26 -0700 Subject: [PATCH 33/35] removed ground plane grid, and changed start position --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 359975339d..821a21d604 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -77,7 +77,7 @@ static char STAR_CACHE_FILE[] = "cachedStars.txt"; static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored -const glm::vec3 START_LOCATION(4.f, 0.f, 5.f); // Where one's own node begins in the world +const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE); // Where one's own node begins in the world // (will be overwritten if avatar data file is found) const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff @@ -3045,7 +3045,7 @@ void Application::displaySide(Camera& whichCamera) { glDisable(GL_FOG); glDisable(GL_NORMALIZE); - renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude()); + //renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude()); } // Draw voxels if (_renderVoxels->isChecked()) { From ac693c703afa41cf578abae80fe542dff4497f07 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 19:19:04 -0700 Subject: [PATCH 34/35] added --domain option and --BuildStreet option --- animation-server/src/main.cpp | 77 +++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp index 4d0577b960..47cf94ff2e 100644 --- a/animation-server/src/main.cpp +++ b/animation-server/src/main.cpp @@ -31,11 +31,12 @@ #endif bool shouldShowPacketsPerSecond = false; // do we want to debug packets per second -bool includeBillboard = true; -bool includeBorderTracer = true; -bool includeMovingBug = true; +bool includeBillboard = false; +bool includeBorderTracer = false; +bool includeMovingBug = false; bool includeBlinkingVoxel = false; -bool includeDanceFloor = true; +bool includeDanceFloor = false; +bool buildStreet = false; const int ANIMATION_LISTEN_PORT = 40107; @@ -616,6 +617,62 @@ static void sendBillboard() { } } +bool roadInitialized = false; +const int ROAD_WIDTH_METERS = 3.0f; +const int BRICKS_ACROSS_ROAD = 32; +const float ROAD_BRICK_SIZE = 0.125f/TREE_SCALE; //(ROAD_WIDTH_METERS / TREE_SCALE) / BRICKS_ACROSS_ROAD; // in voxel units +const int ROAD_LENGTH = 1.0f / ROAD_BRICK_SIZE; // in bricks +const int ROAD_WIDTH = BRICKS_ACROSS_ROAD; // in bricks +glm::vec3 roadPosition(0.5f - (ROAD_BRICK_SIZE * BRICKS_ACROSS_ROAD), 0.0f, 0.0f); +//glm::vec3 roadPosition(0.0f, 0.0f, 0.0f); +const int BRICKS_PER_PACKET = 32; // guessing +const int PACKETS_PER_ROAD = VOXELS_PER_PACKET / (ROAD_LENGTH * ROAD_WIDTH); + +void doBuildStreet() { + if (roadInitialized) { + return; + } + + PACKET_TYPE message = PACKET_TYPE_SET_VOXEL_DESTRUCTIVE; // we're a bully! + static VoxelDetail details[BRICKS_PER_PACKET]; + unsigned char* bufferOut; + int sizeOut; + + for (int z = 0; z < ROAD_LENGTH; z++) { + for (int x = 0; x < ROAD_WIDTH; x++) { + + int nthVoxel = ((z * ROAD_WIDTH) + x); + int item = nthVoxel % BRICKS_PER_PACKET; + + glm::vec3 brick = roadPosition + glm::vec3(x * ROAD_BRICK_SIZE, 0, z * ROAD_BRICK_SIZE); + + details[item].s = ROAD_BRICK_SIZE; + details[item].x = brick.x; + details[item].y = brick.y; + details[item].z = brick.z; + + unsigned char randomTone = randIntInRange(118,138); + details[item].red = randomTone; + details[item].green = randomTone; + details[item].blue = randomTone; + + if (item == BRICKS_PER_PACKET - 1) { + if (createVoxelEditMessage(message, 0, BRICKS_PER_PACKET, (VoxelDetail*)&details, bufferOut, sizeOut)){ + ::packetsSent++; + ::bytesSent += sizeOut; + if (true || ::shouldShowPacketsPerSecond) { + printf("building road sending packet of size=%d\n", sizeOut); + } + NodeList::getInstance()->broadcastToNodes(bufferOut, sizeOut, &NODE_TYPE_VOXEL_SERVER, 1); + delete[] bufferOut; + } + } + } + } + roadInitialized = true; +} + + double start = 0; @@ -645,6 +702,10 @@ void* animateVoxels(void* args) { sendDanceFloor(); } + if (::buildStreet) { + doBuildStreet(); + } + uint64_t end = usecTimestampNow(); uint64_t elapsedSeconds = (end - ::start) / 1000000; if (::shouldShowPacketsPerSecond) { @@ -688,6 +749,9 @@ int main(int argc, const char * argv[]) const char* NO_DANCE_FLOOR = "--NoDanceFloor"; ::includeDanceFloor = !cmdOptionExists(argc, argv, NO_DANCE_FLOOR); + const char* BUILD_STREET = "--BuildStreet"; + ::buildStreet = cmdOptionExists(argc, argv, BUILD_STREET); + // Handle Local Domain testing with the --local command line const char* showPPS = "--showPPS"; ::shouldShowPacketsPerSecond = cmdOptionExists(argc, argv, showPPS); @@ -700,6 +764,11 @@ int main(int argc, const char * argv[]) nodeList->setDomainIPToLocalhost(); } + const char* domainIP = getCmdOption(argc, argv, "--domain"); + if (domainIP) { + NodeList::getInstance()->setDomainIP(domainIP); + } + nodeList->linkedDataCreateCallback = NULL; // do we need a callback? nodeList->startSilentNodeRemovalThread(); From 61560af28f6da61b316577456924980ee0653c4b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 6 Aug 2013 19:21:46 -0700 Subject: [PATCH 35/35] cleanup --- animation-server/src/main.cpp | 9 ++++----- interface/src/Application.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp index 47cf94ff2e..dec8f2ea5d 100644 --- a/animation-server/src/main.cpp +++ b/animation-server/src/main.cpp @@ -31,11 +31,11 @@ #endif bool shouldShowPacketsPerSecond = false; // do we want to debug packets per second -bool includeBillboard = false; -bool includeBorderTracer = false; -bool includeMovingBug = false; +bool includeBillboard = true; +bool includeBorderTracer = true; +bool includeMovingBug = true; bool includeBlinkingVoxel = false; -bool includeDanceFloor = false; +bool includeDanceFloor = true; bool buildStreet = false; @@ -624,7 +624,6 @@ const float ROAD_BRICK_SIZE = 0.125f/TREE_SCALE; //(ROAD_WIDTH_METERS / TREE_SCA const int ROAD_LENGTH = 1.0f / ROAD_BRICK_SIZE; // in bricks const int ROAD_WIDTH = BRICKS_ACROSS_ROAD; // in bricks glm::vec3 roadPosition(0.5f - (ROAD_BRICK_SIZE * BRICKS_ACROSS_ROAD), 0.0f, 0.0f); -//glm::vec3 roadPosition(0.0f, 0.0f, 0.0f); const int BRICKS_PER_PACKET = 32; // guessing const int PACKETS_PER_ROAD = VOXELS_PER_PACKET / (ROAD_LENGTH * ROAD_WIDTH); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 821a21d604..19b889a918 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -77,8 +77,10 @@ static char STAR_CACHE_FILE[] = "cachedStars.txt"; static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored -const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE); // Where one's own node begins in the world - // (will be overwritten if avatar data file is found) +// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found) +// this is basically in the center of the ground plane. Slightly adjusted. This was asked for by +// Grayson as he's building a street around here for demo dinner 2 +const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE); const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff // in the idle loop? (60 FPS is default)