From cb6f542b9f36f6ae765b48a260a30896295cf19b Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Wed, 17 Jul 2013 17:00:23 -0700 Subject: [PATCH 01/50] First-pass finger motion trails --- interface/src/Hand.cpp | 31 ++++++++++++++ interface/src/Hand.h | 1 + libraries/avatars/src/HandData.cpp | 65 ++++++++++++++++++++++++++++++ libraries/avatars/src/HandData.h | 11 +++++ 4 files changed, 108 insertions(+) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index bbfd58c5b1..6e9cf1ca7f 100755 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -95,6 +95,7 @@ void Hand::render(bool lookingInMirror) { glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); + renderFingerTrails(); renderHandSpheres(); } @@ -173,6 +174,35 @@ void Hand::renderHandSpheres() { glPopMatrix(); } +void Hand::renderFingerTrails() { + // Draw the finger root cones + for (size_t i = 0; i < getNumPalms(); ++i) { + PalmData& palm = getPalms()[i]; + if (palm.isActive()) { + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + int numPositions = finger.getTrailNumPositions(); + if (numPositions > 0) { + glBegin(GL_TRIANGLE_STRIP); + for (int t = 0; t < numPositions; ++t) + { + const glm::vec3& center = finger.getTrailPosition(t); + const float halfWidth = 0.001f; + const glm::vec3 edgeDirection(1.0f, 0.0f, 0.0f); + glm::vec3 edge0 = center + edgeDirection * halfWidth; + glm::vec3 edge1 = center - edgeDirection * halfWidth; + float alpha = 1.0f - ((float)t / (float)(numPositions - 1)); + glColor4f(1.0f, 0.0f, 0.0f, alpha); + glVertex3fv((float*)&edge0); + glVertex3fv((float*)&edge1); + } + glEnd(); + } + } + } + } +} + void Hand::setLeapFingers(const std::vector& fingerTips, const std::vector& fingerRoots) { // TODO: add id-checking here to increase finger stability @@ -193,6 +223,7 @@ void Hand::setLeapFingers(const std::vector& fingerTips, } } } + updateFingerTrails(); } void Hand::setLeapHands(const std::vector& handPositions, diff --git a/interface/src/Hand.h b/interface/src/Hand.h index fb6b863458..aed406dea5 100755 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -74,6 +74,7 @@ private: // private methods void renderRaveGloveStage(); void renderHandSpheres(); + void renderFingerTrails(); void calculateGeometry(); }; diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 32e83b352d..ffe5615823 100755 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -16,6 +16,8 @@ HandData::HandData(AvatarData* owningAvatar) : for (int i = 0; i < 2; ++i) { _palms.push_back(PalmData(this)); } + const int standardTrailLength = 30; + setFingerTrailLength(standardTrailLength); } PalmData::PalmData(HandData* owningHandData) : @@ -80,3 +82,66 @@ void HandData::decodeRemoteData(const std::vector& fingerVectors) { } } +void HandData::setFingerTrailLength(unsigned int length) { + for (size_t i = 0; i < getNumPalms(); ++i) { + PalmData& palm = getPalms()[i]; + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.setTrailLength(length); + } + } +} + +void HandData::updateFingerTrails() { + for (size_t i = 0; i < getNumPalms(); ++i) { + PalmData& palm = getPalms()[i]; + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.updateTrail(); + } + } +} + +void FingerData::setTrailLength(unsigned int length) { + _tipTrailPositions.resize(length); + _tipTrailCurrentStartIndex = 0; + _tipTrailCurrentValidLength = 0; +} + +void FingerData::updateTrail() { + if (_tipTrailPositions.size() == 0) + return; + + if (_isActive) { + // Add the next point in the trail. + _tipTrailCurrentStartIndex--; + if (_tipTrailCurrentStartIndex < 0) + _tipTrailCurrentStartIndex = _tipTrailPositions.size() - 1; + + _tipTrailPositions[_tipTrailCurrentStartIndex] = getTipPosition(); + + if (_tipTrailCurrentValidLength < _tipTrailPositions.size()) + _tipTrailCurrentValidLength++; + } + else { + // It's not active, so just shorten the trail. + if (_tipTrailCurrentValidLength > 0) + _tipTrailCurrentValidLength--; + } +} + +int FingerData::getTrailNumPositions() { + return _tipTrailCurrentValidLength; +} + +const glm::vec3& FingerData::getTrailPosition(int index) { + if (index >= _tipTrailCurrentValidLength) { + static glm::vec3 zero(0,0,0); + return zero; + } + int posIndex = (index + _tipTrailCurrentStartIndex) % _tipTrailCurrentValidLength; + return _tipTrailPositions[posIndex]; +} + + + diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 65b32ff5c6..f52171b403 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -40,6 +40,9 @@ public: std::vector& getPalms() { return _palms; } size_t getNumPalms() { return _palms.size(); } + void setFingerTrailLength(unsigned int length); + void updateFingerTrails(); + // Use these for sending and receiving hand data void encodeRemoteData(std::vector& fingerVectors); void decodeRemoteData(const std::vector& fingerVectors); @@ -69,11 +72,19 @@ public: void setActive(bool active) { _isActive = active; } void setRawTipPosition(const glm::vec3& pos) { _tipRawPosition = pos; } void setRawRootPosition(const glm::vec3& pos) { _rootRawPosition = pos; } + void setTrailLength(unsigned int length); + void updateTrail(); + int getTrailNumPositions(); + const glm::vec3& getTrailPosition(int index); + private: glm::vec3 _tipRawPosition; glm::vec3 _rootRawPosition; bool _isActive; // This has current valid data + std::vector _tipTrailPositions; + int _tipTrailCurrentStartIndex; + int _tipTrailCurrentValidLength; PalmData* _owningPalmData; HandData* _owningHandData; }; From 40f87817bf2f2db9267536b55772857877949f8a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Jul 2013 11:03:46 -0700 Subject: [PATCH 02/50] first cut at scene stats --- libraries/voxels/src/VoxelSceneStats.cpp | 76 ++++++++++++++++++++++++ libraries/voxels/src/VoxelSceneStats.h | 51 ++++++++++++++++ voxel-server/src/VoxelNodeData.h | 3 + voxel-server/src/main.cpp | 6 +- 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 libraries/voxels/src/VoxelSceneStats.cpp create mode 100644 libraries/voxels/src/VoxelSceneStats.h diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp new file mode 100644 index 0000000000..37422e471d --- /dev/null +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -0,0 +1,76 @@ +// +// VoxelSceneStats.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 7/18/13. +// +// + +#include "VoxelSceneStats.h" + +VoxelSceneStats::VoxelSceneStats() : + start(0), + end(0), + elapsed(0), + total(0), + traversed(0), + internal(0), + internalOutOfView(0), + internalOccluded(0), + internalDirty(0), + leaves(0), + leavesOutOfView(0), + leavesOccluded(0), + leavesDirty(0), + packets(0), + bytes(0), + passes(0), + elapsedUsecsToSend(0), + wasFinished(false), + wasMoving(false), + hadDeltaView(false), + hadOcclusionCulling(false) +{ +} + +VoxelSceneStats::~VoxelSceneStats() { +} + +void VoxelSceneStats::sceneStarted() { + start = usecTimestampNow(); +} + +void VoxelSceneStats::sceneCompleted() { + end = usecTimestampNow(); + elapsed = end - start; +} + +void VoxelSceneStats::reset() { + start = 0; + end= 0; + elapsed= 0; + + + total = 0; + traversed = 0; + internal = 0; + internalOutOfView = 0; + internalOccluded = 0; + internalDirty = 0; + leaves = 0; + leavesOutOfView = 0; + leavesOccluded = 0; + leavesDirty = 0; + packets = 0; + bytes = 0; + passes = 0; + wasFinished = false; + wasMoving = false; + hadDeltaView = false; + hadOcclusionCulling = false; +} + + +void VoxelSceneStats::printDebugDetails() { + qDebug("VoxelSceneStats: start: %llu, end: %llu, elapsed: %llu \n", start, end, elapsed); +} diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h new file mode 100644 index 0000000000..c91e757236 --- /dev/null +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -0,0 +1,51 @@ +// +// VoxelSceneStats.h +// hifi +// +// Created by Brad Hefta-Gaub on 7/18/13. +// +// + +#ifndef __hifi__VoxelSceneStats__ +#define __hifi__VoxelSceneStats__ + + +class VoxelSceneStats { +public: + VoxelSceneStats(); + ~VoxelSceneStats(); + void reset(); + void sceneStarted(); + void sceneCompleted(); + void printDebugDetails(); + + // scene timing data in usecs + uint64_t start; + uint64_t end; + uint64_t elapsed; + + // scene voxel related data + unsigned long total; + unsigned long traversed; + unsigned long internal; + unsigned long internalOutOfView; + unsigned long internalOccluded; + unsigned long internalDirty; + unsigned long leaves; + unsigned long leavesOutOfView; + unsigned long leavesOccluded; + unsigned long leavesDirty; + + // scene network related data + unsigned int packets; + unsigned int bytes; + unsigned int passes; + + // features related items + bool wasFinished; + bool wasMoving; + bool hadDeltaView; + bool hadOcclusionCulling; +}; + +#endif /* defined(__hifi__VoxelSceneStats__) */ diff --git a/voxel-server/src/VoxelNodeData.h b/voxel-server/src/VoxelNodeData.h index 96b61db963..988fcb5330 100644 --- a/voxel-server/src/VoxelNodeData.h +++ b/voxel-server/src/VoxelNodeData.h @@ -58,6 +58,9 @@ public: void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; }; bool getCurrentPacketIsColor() const { return _currentPacketIsColor; }; + + VoxelSceneStats stats; + private: VoxelNodeData(const VoxelNodeData &); VoxelNodeData& operator= (const VoxelNodeData&); diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 5b1ad57861..65b3f5c5c4 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -204,9 +204,13 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, printf("ENTIRE SCENE SENT! nodeData->setLastTimeBagEmpty(now=[%lld])\n", now); } } - + + nodeData->stats.sceneCompleted(); + nodeData->stats.printDebugDetails(); + // This is the start of "resending" the scene. nodeData->nodeBag.insert(serverTree.rootNode); + nodeData->stats.sceneStarted(); } // If we have something in our nodeBag, then turn them into packets and send them out... From b90fc9cc0d5567e14f97ac65750c25c8d4d798e8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Jul 2013 11:21:14 -0700 Subject: [PATCH 03/50] more --- libraries/voxels/src/VoxelSceneStats.cpp | 3 ++- libraries/voxels/src/VoxelSceneStats.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 37422e471d..26ec66c32b 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -6,6 +6,8 @@ // // +#include + #include "VoxelSceneStats.h" VoxelSceneStats::VoxelSceneStats() : @@ -25,7 +27,6 @@ VoxelSceneStats::VoxelSceneStats() : packets(0), bytes(0), passes(0), - elapsedUsecsToSend(0), wasFinished(false), wasMoving(false), hadDeltaView(false), diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index c91e757236..a90de6e7a9 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -9,6 +9,8 @@ #ifndef __hifi__VoxelSceneStats__ #define __hifi__VoxelSceneStats__ +#include + class VoxelSceneStats { public: From d5812c8f3477630cf7a6f92ac402977b2e1f2bbc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Jul 2013 11:21:23 -0700 Subject: [PATCH 04/50] more --- voxel-server/src/VoxelNodeData.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/voxel-server/src/VoxelNodeData.h b/voxel-server/src/VoxelNodeData.h index 988fcb5330..746db6da93 100644 --- a/voxel-server/src/VoxelNodeData.h +++ b/voxel-server/src/VoxelNodeData.h @@ -12,9 +12,11 @@ #include #include #include -#include "VoxelNodeBag.h" -#include "VoxelConstants.h" -#include "CoverageMap.h" + +#include +#include +#include +#include class VoxelNodeData : public AvatarData { public: From 3aa6af21b1f2fb385702816b71d8345f459b4943 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Jul 2013 14:13:45 -0700 Subject: [PATCH 05/50] more voxel scene stats --- libraries/voxels/src/VoxelSceneStats.cpp | 203 +++++++++++++++++------ libraries/voxels/src/VoxelSceneStats.h | 70 ++++++-- libraries/voxels/src/VoxelTree.cpp | 84 +++++++++- libraries/voxels/src/VoxelTree.h | 16 +- voxel-server/src/main.cpp | 16 +- 5 files changed, 312 insertions(+), 77 deletions(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 26ec66c32b..44c10e2bf9 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -8,70 +8,179 @@ #include +#include "VoxelNode.h" #include "VoxelSceneStats.h" -VoxelSceneStats::VoxelSceneStats() : - start(0), - end(0), - elapsed(0), - total(0), - traversed(0), - internal(0), - internalOutOfView(0), - internalOccluded(0), - internalDirty(0), - leaves(0), - leavesOutOfView(0), - leavesOccluded(0), - leavesDirty(0), - packets(0), - bytes(0), - passes(0), - wasFinished(false), - wasMoving(false), - hadDeltaView(false), - hadOcclusionCulling(false) -{ +VoxelSceneStats::VoxelSceneStats() { + reset(); } VoxelSceneStats::~VoxelSceneStats() { } -void VoxelSceneStats::sceneStarted() { - start = usecTimestampNow(); +void VoxelSceneStats::sceneStarted(bool fullScene, bool moving) { + _start = usecTimestampNow(); + reset(); // resets packet and voxel stats + _fullSceneDraw = fullScene; + _moving = moving; } void VoxelSceneStats::sceneCompleted() { - end = usecTimestampNow(); - elapsed = end - start; + _end = usecTimestampNow(); + _elapsed = _end - _start; } void VoxelSceneStats::reset() { - start = 0; - end= 0; - elapsed= 0; + _packets = 0; + _bytes = 0; + _passes = 0; + _traversed = 0; + _internal = 0; + _leaves = 0; + + _skippedDistance = 0; + _internalSkippedDistance = 0; + _leavesSkippedDistance = 0; + + _skippedOutOfView = 0; + _internalSkippedOutOfView = 0; + _leavesSkippedOutOfView = 0; + + _skippedWasInView = 0; + _internalSkippedWasInView = 0; + _leavesSkippedWasInView = 0; + + _skippedNoChange = 0; + _internalSkippedNoChange = 0; + _leavesSkippedNoChange = 0; + + _skippedOccluded = 0; + _internalSkippedOccluded = 0; + _leavesSkippedOccluded = 0; + + _colorSent = 0; + _internalColorSent = 0; + _leavesColorSent = 0; + + _didntFit = 0; + _internalDidntFit = 0; + _leavesDidntFit = 0; - total = 0; - traversed = 0; - internal = 0; - internalOutOfView = 0; - internalOccluded = 0; - internalDirty = 0; - leaves = 0; - leavesOutOfView = 0; - leavesOccluded = 0; - leavesDirty = 0; - packets = 0; - bytes = 0; - passes = 0; - wasFinished = false; - wasMoving = false; - hadDeltaView = false; - hadOcclusionCulling = false; } +void VoxelSceneStats::packetSent(int bytes) { + _packets++; + _bytes += bytes; +} + +void VoxelSceneStats::traversed(const VoxelNode* node) { + _traversed++; + if (node->isLeaf()) { + _leaves++; + } else { + _internal++; + } +} + +void VoxelSceneStats::skippedDistance(const VoxelNode* node) { + _skippedDistance++; + if (node->isLeaf()) { + _leavesSkippedDistance++; + } else { + _internalSkippedDistance++; + } +} + +void VoxelSceneStats::skippedOutOfView(const VoxelNode* node) { + _skippedOutOfView++; + if (node->isLeaf()) { + _leavesSkippedOutOfView++; + } else { + _internalSkippedOutOfView++; + } +} + +void VoxelSceneStats::skippedWasInView(const VoxelNode* node) { + _skippedWasInView++; + if (node->isLeaf()) { + _leavesSkippedWasInView++; + } else { + _internalSkippedWasInView++; + } +} + +void VoxelSceneStats::skippedNoChange(const VoxelNode* node) { + _skippedNoChange++; + if (node->isLeaf()) { + _leavesSkippedNoChange++; + } else { + _internalSkippedNoChange++; + } +} + +void VoxelSceneStats::skippedOccluded(const VoxelNode* node) { + _skippedOccluded++; + if (node->isLeaf()) { + _leavesSkippedOccluded++; + } else { + _internalSkippedOccluded++; + } +} + +void VoxelSceneStats::colorSent(const VoxelNode* node) { + _colorSent++; + if (node->isLeaf()) { + _leavesColorSent++; + } else { + _internalColorSent++; + } +} + +void VoxelSceneStats::didntFit(const VoxelNode* node) { + _didntFit++; + if (node->isLeaf()) { + _leavesDidntFit++; + } else { + _internalDidntFit++; + } +} void VoxelSceneStats::printDebugDetails() { - qDebug("VoxelSceneStats: start: %llu, end: %llu, elapsed: %llu \n", start, end, elapsed); + qDebug("\n------------------------------\n"); + qDebug("VoxelSceneStats:\n"); + qDebug(" start : %llu \n", _start); + qDebug(" end : %llu \n", _end); + qDebug(" elapsed: %llu \n", _elapsed); + qDebug("\n"); + qDebug(" full scene: %s\n", debug::valueOf(_fullSceneDraw)); + qDebug(" moving: %s\n", debug::valueOf(_moving)); + qDebug("\n"); + qDebug(" packets: %d\n", _packets); + qDebug(" bytes : %d\n", _bytes); + qDebug("\n"); + qDebug(" traversed : %lu\n", _traversed ); + qDebug(" internal : %lu\n", _internal ); + qDebug(" leaves : %lu\n", _leaves ); + qDebug(" skipped distance : %lu\n", _skippedDistance ); + qDebug(" internal : %lu\n", _internalSkippedDistance ); + qDebug(" leaves : %lu\n", _leavesSkippedDistance ); + qDebug(" skipped out of view : %lu\n", _skippedOutOfView ); + qDebug(" internal : %lu\n", _internalSkippedOutOfView ); + qDebug(" leaves : %lu\n", _leavesSkippedOutOfView ); + qDebug(" skipped was in view : %lu\n", _skippedWasInView ); + qDebug(" internal : %lu\n", _internalSkippedWasInView ); + qDebug(" leaves : %lu\n", _leavesSkippedWasInView ); + qDebug(" skipped no change : %lu\n", _skippedNoChange ); + qDebug(" internal : %lu\n", _internalSkippedNoChange ); + qDebug(" leaves : %lu\n", _leavesSkippedNoChange ); + qDebug(" skipped occluded : %lu\n", _skippedOccluded ); + qDebug(" internal : %lu\n", _internalSkippedOccluded ); + qDebug(" leaves : %lu\n", _leavesSkippedOccluded ); + qDebug(" color sent : %lu\n", _colorSent ); + qDebug(" internal : %lu\n", _internalColorSent ); + qDebug(" leaves : %lu\n", _leavesColorSent ); + qDebug(" Didn't Fit : %lu\n", _didntFit ); + qDebug(" internal : %lu\n", _internalDidntFit ); + qDebug(" leaves : %lu\n", _leavesDidntFit ); } diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index a90de6e7a9..d41091ae80 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -11,43 +11,85 @@ #include +class VoxelNode; class VoxelSceneStats { public: VoxelSceneStats(); ~VoxelSceneStats(); void reset(); - void sceneStarted(); + void sceneStarted(bool fullScene, bool moving); void sceneCompleted(); void printDebugDetails(); + void packetSent(int bytes); + void traversed(const VoxelNode* node); + void skippedDistance(const VoxelNode* node); + void skippedOutOfView(const VoxelNode* node); + void skippedWasInView(const VoxelNode* node); + void skippedNoChange(const VoxelNode* node); + void skippedOccluded(const VoxelNode* node); + void colorSent(const VoxelNode* node); + void didntFit(const VoxelNode* node); + void colorBitsWritten(const VoxelNode* node); + void existsBitsWritten(const VoxelNode* node); + void existsInPacketBitsWritten(const VoxelNode* node); + +private: // scene timing data in usecs - uint64_t start; - uint64_t end; - uint64_t elapsed; + uint64_t _start; + uint64_t _end; + uint64_t _elapsed; // scene voxel related data + unsigned long _traversed; + unsigned long _internal; + unsigned long _leaves; + + unsigned long _skippedDistance; + unsigned long _internalSkippedDistance; + unsigned long _leavesSkippedDistance; + + unsigned long _skippedOutOfView; + unsigned long _internalSkippedOutOfView; + unsigned long _leavesSkippedOutOfView; + + unsigned long _skippedWasInView; + unsigned long _internalSkippedWasInView; + unsigned long _leavesSkippedWasInView; + + unsigned long _skippedNoChange; + unsigned long _internalSkippedNoChange; + unsigned long _leavesSkippedNoChange; + + unsigned long _skippedOccluded; + unsigned long _internalSkippedOccluded; + unsigned long _leavesSkippedOccluded; + + unsigned long _colorSent; + unsigned long _internalColorSent; + unsigned long _leavesColorSent; + + unsigned long _didntFit; + unsigned long _internalDidntFit; + unsigned long _leavesDidntFit; + unsigned long total; - unsigned long traversed; - unsigned long internal; unsigned long internalOutOfView; unsigned long internalOccluded; unsigned long internalDirty; - unsigned long leaves; unsigned long leavesOutOfView; unsigned long leavesOccluded; unsigned long leavesDirty; // scene network related data - unsigned int packets; - unsigned int bytes; - unsigned int passes; + unsigned int _packets; + unsigned int _bytes; + unsigned int _passes; // features related items - bool wasFinished; - bool wasMoving; - bool hadDeltaView; - bool hadOcclusionCulling; + bool _moving; + bool _fullSceneDraw; }; #endif /* defined(__hifi__VoxelSceneStats__) */ diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 9cb6a85f93..13e55bea0f 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1037,6 +1037,13 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node, unsigned char* outputBuffer, availableBytes -= codeLength; // keep track or remaining space int currentEncodeLevel = 0; + + // record some stats, this is the one node that we won't record below in the recursion function, so we need to + // track it here + if (params.stats) { + params.stats->traversed(node); + } + int childBytesWritten = encodeTreeBitstreamRecursion(node, outputBuffer, availableBytes, bag, params, currentEncodeLevel); // if childBytesWritten == 1 then something went wrong... that's not possible @@ -1081,6 +1088,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // If we're too far away for our render level, then just return if (distance >= boundaryDistance) { + if (params.stats) { + params.stats->skippedDistance(node); + } return bytesAtThisLevel; } @@ -1088,6 +1098,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if // we're out of view if (!node->isInView(*params.viewFrustum)) { + if (params.stats) { + params.stats->skippedOutOfView(node); + } return bytesAtThisLevel; } @@ -1110,6 +1123,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // if we're in deltaViewFrustum mode, and this node has changed since it was last sent, then we do // need to send it. if (wasInView && !(params.deltaViewFrustum && node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) { + if (params.stats) { + params.stats->skippedWasInView(node); + } return bytesAtThisLevel; } @@ -1117,6 +1133,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // then we can also bail early and save bits if (!params.forceSendScene && !params.deltaViewFrustum && !node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) { + if (params.stats) { + params.stats->skippedNoChange(node); + } return bytesAtThisLevel; } @@ -1136,6 +1155,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, false); delete voxelPolygon; // cleanup if (result == OCCLUDED) { + if (params.stats) { + params.stats->skippedOccluded(node); + } return bytesAtThisLevel; } } else { @@ -1201,6 +1223,12 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp distancesToChildren[i] = 0.0f; currentCount++; } + + // track stats + if (params.stats && childNode) { + params.stats->traversed(childNode); + } + } // for each child node in Distance sorted order..., check to see if they exist, are colored, and in view, and if so @@ -1211,13 +1239,21 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp bool childIsInView = (childNode && (!params.viewFrustum || childNode->isInView(*params.viewFrustum))); - if (childIsInView) { + if (!childIsInView) { + if (params.stats) { + params.stats->skippedOutOfView(childNode); + } + } else { // Before we determine consider this further, let's see if it's in our LOD scope... float distance = distancesToChildren[i]; // params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0; float boundaryDistance = !params.viewFrustum ? 1 : boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust); - if (distance < boundaryDistance) { + if (!(distance < boundaryDistance)) { + if (params.stats) { + params.stats->skippedDistance(childNode); + } + } else { inViewCount++; // track children in view as existing and not a leaf, if they're a leaf, @@ -1261,7 +1297,18 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp } // wants occlusion culling & isLeaf() - bool shouldRender = !params.viewFrustum ? true : childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust); + bool shouldRender = !params.viewFrustum ? true : + childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust); + + // track some stats + if (params.stats) { + if (!shouldRender) { + params.stats->skippedDistance(childNode); + } + if (childIsOccluded) { + params.stats->skippedOccluded(childNode); + } + } // track children with actual color, only if the child wasn't previously in view! if (shouldRender && !childIsOccluded) { @@ -1288,7 +1335,14 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp inViewWithColorCount++; } else { // otherwise just track stats of the items we discarded - params.childWasInViewDiscarded++; + if (params.stats) { + if (childWasInView) { + params.stats->skippedWasInView(childNode); + } else { + params.stats->skippedNoChange(childNode); + } + } + } } } @@ -1297,14 +1351,23 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp *writeToThisLevelBuffer = childrenColoredBits; writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count + if (params.stats) { + params.stats->colorBitsWritten(node); + } // write the color data... if (params.includeColor) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { if (oneAtBit(childrenColoredBits, i)) { - memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR); + VoxelNode* childNode = node->getChildAtIndex(i); + memcpy(writeToThisLevelBuffer, &childNode->getColor(), BYTES_PER_COLOR); writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color + + if (params.stats) { + params.stats->colorSent(childNode); + } + } } } @@ -1315,12 +1378,18 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp *writeToThisLevelBuffer = childrenExistInTreeBits; writeToThisLevelBuffer += sizeof(childrenExistInTreeBits); // move the pointer bytesAtThisLevel += sizeof(childrenExistInTreeBits); // keep track of byte count + if (params.stats) { + params.stats->existsBitsWritten(node); + } } // write the child exist bits *writeToThisLevelBuffer = childrenExistInPacketBits; writeToThisLevelBuffer += sizeof(childrenExistInPacketBits); // move the pointer bytesAtThisLevel += sizeof(childrenExistInPacketBits); // keep track of byte count + if (params.stats) { + params.stats->existsInPacketBitsWritten(node); + } // We only need to keep digging, if there is at least one child that is inView, and not a leaf. keepDiggingDeeper = (inViewNotLeafCount > 0); @@ -1333,6 +1402,11 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp availableBytes -= bytesAtThisLevel; } else { bag.insert(node); + + if (params.stats) { + params.stats->didntFit(node); + } + return 0; } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index e5db6526e9..199942605e 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -9,12 +9,14 @@ #ifndef __hifi__VoxelTree__ #define __hifi__VoxelTree__ -#include "SimpleMovingAverage.h" +#include +#include + +#include "CoverageMap.h" #include "ViewFrustum.h" #include "VoxelNode.h" #include "VoxelNodeBag.h" -#include "CoverageMap.h" -#include "PointerStack.h" +#include "VoxelSceneStats.h" // Callback function, for recuseTreeWithOperation typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData); @@ -36,6 +38,7 @@ typedef enum {GRADIENT, RANDOM, NATURAL} creationMode; #define NO_BOUNDARY_ADJUST 0 #define LOW_RES_MOVING_ADJUST 1 #define IGNORE_LAST_SENT 0 +#define IGNORE_SCENE_STATS NULL class EncodeBitstreamParams { public: @@ -48,10 +51,10 @@ public: bool deltaViewFrustum; const ViewFrustum* lastViewFrustum; bool wantOcclusionCulling; - long childWasInViewDiscarded; int boundaryLevelAdjust; uint64_t lastViewFrustumSent; bool forceSendScene; + VoxelSceneStats* stats; CoverageMap* map; EncodeBitstreamParams( @@ -66,7 +69,8 @@ public: CoverageMap* map = IGNORE_COVERAGE_MAP, int boundaryLevelAdjust = NO_BOUNDARY_ADJUST, uint64_t lastViewFrustumSent = IGNORE_LAST_SENT, - bool forceSendScene = true) : + bool forceSendScene = true, + VoxelSceneStats* stats = IGNORE_SCENE_STATS) : maxEncodeLevel (maxEncodeLevel), maxLevelReached (0), viewFrustum (viewFrustum), @@ -76,10 +80,10 @@ public: deltaViewFrustum (deltaViewFrustum), lastViewFrustum (lastViewFrustum), wantOcclusionCulling (wantOcclusionCulling), - childWasInViewDiscarded (0), boundaryLevelAdjust (boundaryLevelAdjust), lastViewFrustumSent (lastViewFrustumSent), forceSendScene (forceSendScene), + stats (stats), map (map) {} }; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 65b3f5c5c4..0c13d6620a 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -200,9 +200,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, // only set our last sent time if we weren't resetting due to frustum change uint64_t now = usecTimestampNow(); nodeData->setLastTimeBagEmpty(now); - if (::debugVoxelSending) { - printf("ENTIRE SCENE SENT! nodeData->setLastTimeBagEmpty(now=[%lld])\n", now); - } } nodeData->stats.sceneCompleted(); @@ -210,7 +207,10 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, // This is the start of "resending" the scene. nodeData->nodeBag.insert(serverTree.rootNode); - nodeData->stats.sceneStarted(); + + // start tracking our stats + bool fullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging(); + nodeData->stats.sceneStarted(fullScene, viewFrustumChanged); } // If we have something in our nodeBag, then turn them into packets and send them out... @@ -243,12 +243,15 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP; int boundaryLevelAdjust = viewFrustumChanged && nodeData->getWantLowResMoving() ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST; + + bool fullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && + nodeData->getViewFrustumJustStoppedChanging(); EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, wantOcclusionCulling, coverageMap, boundaryLevelAdjust, nodeData->getLastTimeBagEmpty(), - nodeData->getViewFrustumJustStoppedChanging()); + fullScene, &nodeData->stats); bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeData->nodeBag, params); @@ -258,6 +261,8 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, } else { nodeList->getNodeSocket()->send(node->getActiveSocket(), nodeData->getPacket(), nodeData->getPacketLength()); + + nodeData->stats.packetSent(nodeData->getPacketLength()); trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; packetsSentThisInterval++; @@ -268,6 +273,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, if (nodeData->isPacketWaiting()) { nodeList->getNodeSocket()->send(node->getActiveSocket(), nodeData->getPacket(), nodeData->getPacketLength()); + nodeData->stats.packetSent(nodeData->getPacketLength()); trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; nodeData->resetVoxelPacket(); From 4d1ae4308546214abbd5be295a2cc002fab91d44 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Jul 2013 15:13:55 -0700 Subject: [PATCH 06/50] adjust server sleep time to allow 60fps --- voxel-server/src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 0c13d6620a..770a22bd23 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -44,9 +44,9 @@ const int MIN_BRIGHTNESS = 64; const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05f; -const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000; -int PACKETS_PER_CLIENT_PER_INTERVAL = 30; -const int SENDING_TIME_TO_SPARE = 20 * 1000; // usec of sending interval to spare for calculating voxels +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 MAX_VOXEL_TREE_DEPTH_LEVELS = 4; From 11eabf3c5137b3a52274708e51bfb8a584934694 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Jul 2013 15:14:11 -0700 Subject: [PATCH 07/50] more stats --- libraries/voxels/src/VoxelSceneStats.cpp | 52 ++++++++++++++++++++++++ libraries/voxels/src/VoxelSceneStats.h | 12 ++++++ 2 files changed, 64 insertions(+) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 44c10e2bf9..254f099e3f 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -67,6 +67,18 @@ void VoxelSceneStats::reset() { _internalDidntFit = 0; _leavesDidntFit = 0; + _colorBitsWritten = 0; + _internalColorBitsWritten = 0; + _leavesColorBitsWritten = 0; + + _existsBitsWritten = 0; + _internalExistsBitsWritten = 0; + _leavesExistsBitsWritten = 0; + + _existsInPacketBitsWritten = 0; + _internalExistsInPacketBitsWritten = 0; + _leavesExistsInPacketBitsWritten = 0; + } void VoxelSceneStats::packetSent(int bytes) { @@ -146,6 +158,35 @@ void VoxelSceneStats::didntFit(const VoxelNode* node) { } } +void VoxelSceneStats::colorBitsWritten(const VoxelNode* node) { + _colorBitsWritten++; + if (node->isLeaf()) { + _leavesColorBitsWritten++; + } else { + _internalColorBitsWritten++; + } +} + +void VoxelSceneStats::existsBitsWritten(const VoxelNode* node) { + _existsBitsWritten++; + if (node->isLeaf()) { + _leavesExistsBitsWritten++; + } else { + _internalExistsBitsWritten++; + } +} + +void VoxelSceneStats::existsInPacketBitsWritten(const VoxelNode* node) { + _existsInPacketBitsWritten++; + if (node->isLeaf()) { + _leavesExistsInPacketBitsWritten++; + } else { + _internalExistsInPacketBitsWritten++; + } +} + + + void VoxelSceneStats::printDebugDetails() { qDebug("\n------------------------------\n"); qDebug("VoxelSceneStats:\n"); @@ -177,10 +218,21 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" skipped occluded : %lu\n", _skippedOccluded ); qDebug(" internal : %lu\n", _internalSkippedOccluded ); qDebug(" leaves : %lu\n", _leavesSkippedOccluded ); + + qDebug("\n"); qDebug(" color sent : %lu\n", _colorSent ); qDebug(" internal : %lu\n", _internalColorSent ); qDebug(" leaves : %lu\n", _leavesColorSent ); qDebug(" Didn't Fit : %lu\n", _didntFit ); qDebug(" internal : %lu\n", _internalDidntFit ); qDebug(" leaves : %lu\n", _leavesDidntFit ); + qDebug(" color bits : %lu\n", _colorBitsWritten ); + qDebug(" internal : %lu\n", _internalColorBitsWritten ); + qDebug(" leaves : %lu\n", _leavesColorBitsWritten ); + qDebug(" exists bits : %lu\n", _existsBitsWritten ); + qDebug(" internal : %lu\n", _internalExistsBitsWritten); + qDebug(" leaves : %lu\n", _leavesExistsBitsWritten ); + qDebug(" in packet bit : %lu\n", _existsInPacketBitsWritten ); + qDebug(" internal : %lu\n", _internalExistsInPacketBitsWritten); + qDebug(" leaves : %lu\n", _leavesExistsInPacketBitsWritten ); } diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index d41091ae80..29461996b3 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -74,6 +74,18 @@ private: unsigned long _internalDidntFit; unsigned long _leavesDidntFit; + unsigned long _colorBitsWritten; + unsigned long _internalColorBitsWritten; + unsigned long _leavesColorBitsWritten; + + unsigned long _existsBitsWritten; + unsigned long _internalExistsBitsWritten; + unsigned long _leavesExistsBitsWritten; + + unsigned long _existsInPacketBitsWritten; + unsigned long _internalExistsInPacketBitsWritten; + unsigned long _leavesExistsInPacketBitsWritten; + unsigned long total; unsigned long internalOutOfView; unsigned long internalOccluded; From 262851346c496f272d7c425f1cd2b5ccdc9fb2d6 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Fri, 19 Jul 2013 09:31:45 -0700 Subject: [PATCH 08/50] Rave Glove Demo: Leap Rework (simplification and elimination of redundant data passing) This version matches fingers based on Leap serialized ID's, avoiding finger-replacement-crosstalk. --- interface/src/Application.cpp | 4 +- interface/src/Hand.cpp | 39 ---- interface/src/Hand.h | 4 - interface/src/LeapManager.cpp | 291 ++++++++++++++++++----------- interface/src/LeapManager.h | 3 +- libraries/avatars/src/HandData.cpp | 2 + libraries/avatars/src/HandData.h | 10 +- 7 files changed, 198 insertions(+), 155 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c5c18c9fdb..0b053e59d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2046,10 +2046,8 @@ void Application::update(float deltaTime) { // Leap finger-sensing device LeapManager::enableFakeFingers(_simulateLeapHand->isChecked() || _testRaveGlove->isChecked()); - LeapManager::nextFrame(); _myAvatar.getHand().setRaveGloveActive(_testRaveGlove->isChecked()); - _myAvatar.getHand().setLeapFingers(LeapManager::getFingerTips(), LeapManager::getFingerRoots()); - _myAvatar.getHand().setLeapHands(LeapManager::getHandPositions(), LeapManager::getHandNormals()); + LeapManager::nextFrame(_myAvatar); // Read serial port interface devices if (_serialHeadSensor.isActive()) { diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 1117044b67..97594d0f50 100755 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -203,45 +203,6 @@ void Hand::renderFingerTrails() { } } -void Hand::setLeapFingers(const std::vector& fingerTips, - const std::vector& fingerRoots) { - // TODO: add id-checking here to increase finger stability - - size_t fingerIndex = 0; - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; - for (size_t f = 0; f < palm.getNumFingers(); ++f) { - FingerData& finger = palm.getFingers()[f]; - if (fingerIndex < fingerTips.size()) { - finger.setActive(true); - finger.setRawTipPosition(fingerTips[fingerIndex]); - finger.setRawRootPosition(fingerRoots[fingerIndex]); - fingerIndex++; - } - else { - finger.setActive(false); - } - } - } - updateFingerTrails(); -} - -void Hand::setLeapHands(const std::vector& handPositions, - const std::vector& handNormals) { - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; - if (i < handPositions.size()) { - palm.setActive(true); - palm.setRawPosition(handPositions[i]); - palm.setRawNormal(handNormals[i]); - } - else { - palm.setActive(false); - } - } -} - - void Hand::updateFingerParticles(float deltaTime) { if (!_particleSystemInitialized) { diff --git a/interface/src/Hand.h b/interface/src/Hand.h index aed406dea5..f37046ed3a 100755 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -42,10 +42,6 @@ public: void render(bool lookingInMirror); void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; } - void setLeapFingers (const std::vector& fingerTips, - const std::vector& fingerRoots); - void setLeapHands (const std::vector& handPositions, - const std::vector& handNormals); void updateFingerParticles(float deltaTime); void setRaveGloveActive(bool active) { _isRaveGloveActive = active; } diff --git a/interface/src/LeapManager.cpp b/interface/src/LeapManager.cpp index fe47e527fa..36be287e01 100755 --- a/interface/src/LeapManager.cpp +++ b/interface/src/LeapManager.cpp @@ -7,6 +7,7 @@ // #include "LeapManager.h" +#include "Avatar.h" #include #include // needed for RTLD_LAZY #include @@ -16,48 +17,15 @@ bool LeapManager::_doFakeFingers = false; Leap::Controller* LeapManager::_controller = NULL; HifiLeapListener* LeapManager::_listener = NULL; -namespace { -glm::vec3 fakeHandOffset(0.0f, 50.0f, 50.0f); -} // end anonymous namespace - class HifiLeapListener : public Leap::Listener { public: HifiLeapListener() {} virtual ~HifiLeapListener() {} Leap::Frame lastFrame; - std::vector fingerTips; - std::vector fingerRoots; - std::vector handPositions; - std::vector handNormals; - virtual void onFrame(const Leap::Controller& controller) { #ifndef LEAP_STUBS - Leap::Frame frame = controller.frame(); - int numFingers = frame.fingers().count(); - fingerTips.resize(numFingers); - fingerRoots.resize(numFingers); - for (int i = 0; i < numFingers; ++i) { - const Leap::Finger& thisFinger = frame.fingers()[i]; - const Leap::Vector pos = thisFinger.stabilizedTipPosition(); - fingerTips[i] = glm::vec3(pos.x, pos.y, pos.z); - - const Leap::Vector root = pos - thisFinger.direction() * thisFinger.length(); - fingerRoots[i] = glm::vec3(root.x, root.y, root.z); - } - - int numHands = frame.hands().count(); - handPositions.resize(numHands); - handNormals.resize(numHands); - for (int i = 0; i < numHands; ++i) { - const Leap::Hand& thisHand = frame.hands()[i]; - const Leap::Vector pos = thisHand.palmPosition(); - handPositions[i] = glm::vec3(pos.x, pos.y, pos.z); - - const Leap::Vector norm = thisHand.palmNormal(); - handNormals[i] = glm::vec3(norm.x, norm.y, norm.z); - } - lastFrame = frame; + lastFrame = controller.frame(); #endif } @@ -80,10 +48,192 @@ void LeapManager::terminate() { _controller = NULL; } -void LeapManager::nextFrame() { +void LeapManager::nextFrame(Avatar& avatar) { + // Apply the frame data directly to the avatar. + Hand& hand = avatar.getHand(); + + // If we actually get valid Leap data, this will be set to true; + bool gotRealData = false; + // First, deactivate everything. + for (size_t i = 0; i < hand.getNumPalms(); ++i) { + PalmData& palm = hand.getPalms()[i]; + palm.setActive(false); + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.setActive(false); + } + } + if (controllersExist()) { _listener->onFrame(*_controller); } + +#ifndef LEAP_STUBS + if (controllersExist()) { + // Performance note: + // This is a first pass. + // Once all of this is stable, perfoamance may be improved ysing std::map or another + // associative container to match serialized Leap ID's with available fingers. + // That will make this code shorter and more efficient. + + // First, see which palms and fingers are still valid. + Leap::Frame& frame = _listener->lastFrame; + + // Note that this is O(n^2) at worst, but n is very small. + + size_t numLeapHands = frame.hands().count(); + std::vector palmAssignment(numLeapHands); + // Look for matches + for (size_t index = 0; index < numLeapHands; ++index) { + palmAssignment[index] = NULL; + Leap::Hand leapHand = frame.hands()[index]; + int id = leapHand.id(); + if (leapHand.isValid()) { + for (size_t i = 0; i < hand.getNumPalms(); ++i) { + PalmData& palm = hand.getPalms()[i]; + if (palm.getLeapID() == id) { + // Found hand with the same ID. We're set! + palmAssignment[index] = &palm; + palm.setActive(true); + } + } + } + } + // Fill empty slots + for (size_t index = 0; index < numLeapHands; ++index) { + if (palmAssignment[index] == NULL) { + Leap::Hand leapHand = frame.hands()[index]; + if (leapHand.isValid()) { + for (size_t i = 0; i < hand.getNumPalms() && palmAssignment[index] == NULL; ++i) { + PalmData& palm = hand.getPalms()[i]; + if (!palm.isActive()) { + // Found a free hand to use. + palmAssignment[index] = &palm; + palm.setActive(true); + palm.setLeapID(leapHand.id()); + } + } + } + } + } + // Apply the assignments + for (size_t index = 0; index < numLeapHands; ++index) { + if (palmAssignment[index]) { + Leap::Hand leapHand = frame.hands()[index]; + PalmData& palm = *(palmAssignment[index]); + const Leap::Vector pos = leapHand.palmPosition(); + const Leap::Vector normal = leapHand.palmNormal(); + palm.setRawPosition(glm::vec3(pos.x, pos.y, pos.z)); + palm.setRawNormal(glm::vec3(normal.x, normal.y, normal.z)); + } + } + + size_t numLeapFingers = frame.fingers().count(); + std::vector fingerAssignment(numLeapFingers); + // Look for matches + for (size_t index = 0; index < numLeapFingers; ++index) { + fingerAssignment[index] = NULL; + Leap::Finger leapFinger = frame.fingers()[index]; + int id = leapFinger.id(); + if (leapFinger.isValid()) { + for (size_t i = 0; i < hand.getNumPalms(); ++i) { + PalmData& palm = hand.getPalms()[i]; + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + if (finger.getLeapID() == id) { + // Found finger with the same ID. We're set! + fingerAssignment[index] = &finger; + finger.setActive(true); + } + } + } + } + } + // Fill empty slots + for (size_t index = 0; index < numLeapFingers; ++index) { + if (fingerAssignment[index] == NULL) { + Leap::Finger leapFinger = frame.fingers()[index]; + if (leapFinger.isValid()) { + for (size_t i = 0; i < hand.getNumPalms() && fingerAssignment[index] == NULL; ++i) { + PalmData& palm = hand.getPalms()[i]; + for (size_t f = 0; f < palm.getNumFingers() && fingerAssignment[index] == NULL; ++f) { + FingerData& finger = palm.getFingers()[f]; + if (!finger.isActive()) { + // Found a free finger to use. + fingerAssignment[index] = &finger; + finger.setActive(true); + finger.setLeapID(leapFinger.id()); + } + } + } + } + } + } + // Apply the assignments + for (size_t index = 0; index < numLeapFingers; ++index) { + if (fingerAssignment[index]) { + Leap::Finger leapFinger = frame.fingers()[index]; + FingerData& finger = *(fingerAssignment[index]); + const Leap::Vector tip = leapFinger.stabilizedTipPosition(); + const Leap::Vector root = tip - leapFinger.direction() * leapFinger.length(); + finger.setRawTipPosition(glm::vec3(tip.x, tip.y, tip.z)); + finger.setRawRootPosition(glm::vec3(root.x, root.y, root.z)); + } + } + gotRealData = true; + } +#endif + if (!gotRealData) { + if (_doFakeFingers) { + // There's no real Leap data and we need to fake it. + for (size_t i = 0; i < hand.getNumPalms(); ++i) { + static const glm::vec3 fakeHandOffsets[] = { + glm::vec3( -500.0f, 50.0f, 50.0f), + glm::vec3( 0.0f, 50.0f, 50.0f) + }; + static const glm::vec3 fakeHandFingerMirrors[] = { + glm::vec3( -1.0f, 1.0f, 1.0f), + glm::vec3( 1.0f, 1.0f, 1.0f) + }; + static const glm::vec3 fakeFingerPositions[] = { + glm::vec3( -60.0f, 0.0f, -40.0f), + glm::vec3( -20.0f, 0.0f, -60.0f), + glm::vec3( 20.0f, 0.0f, -60.0f), + glm::vec3( 60.0f, 0.0f, -40.0f), + glm::vec3( -50.0f, 0.0f, 30.0f) + }; + + PalmData& palm = hand.getPalms()[i]; + palm.setActive(true); + // Simulated data + + palm.setRawPosition(glm::vec3( 0.0f, 0.0f, 0.0f) + fakeHandOffsets[i]); + palm.setRawNormal(glm::vec3(0.0f, 1.0f, 0.0f)); + + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.setActive(true); + const float tipScale = 1.5f; + const float rootScale = 0.75f; + glm::vec3 fingerPos = fakeFingerPositions[f] * fakeHandFingerMirrors[i]; + finger.setRawTipPosition(fingerPos * tipScale + fakeHandOffsets[i]); + finger.setRawRootPosition(fingerPos * rootScale + fakeHandOffsets[i]); + } + } + } + else { + // Just deactivate everything. + for (size_t i = 0; i < hand.getNumPalms(); ++i) { + PalmData& palm = hand.getPalms()[i]; + palm.setActive(false); + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.setActive(false); + } + } + } + } + hand.updateFingerTrails(); } void LeapManager::enableFakeFingers(bool enable) { @@ -98,77 +248,6 @@ bool LeapManager::controllersExist() { #endif } -const std::vector& LeapManager::getFingerTips() { - if (controllersExist()) { - return _listener->fingerTips; - } - else { - static std::vector stubData; - stubData.clear(); - if (_doFakeFingers) { - // Simulated data - float scale = 1.5f; - stubData.push_back(glm::vec3( -60.0f, 0.0f, -40.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( -20.0f, 0.0f, -60.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( 20.0f, 0.0f, -60.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( 60.0f, 0.0f, -40.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( -50.0f, 0.0f, 30.0f) * scale + fakeHandOffset); - } - return stubData; - } -} - -const std::vector& LeapManager::getFingerRoots() { - if (controllersExist()) { - return _listener->fingerRoots; - } - else { - static std::vector stubData; - stubData.clear(); - if (_doFakeFingers) { - // Simulated data - float scale = 0.75f; - stubData.push_back(glm::vec3( -60.0f, 0.0f, -40.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( -20.0f, 0.0f, -60.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( 20.0f, 0.0f, -60.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( 60.0f, 0.0f, -40.0f) * scale + fakeHandOffset); - stubData.push_back(glm::vec3( -50.0f, 0.0f, 30.0f) * scale + fakeHandOffset); - } - return stubData; - } -} - -const std::vector& LeapManager::getHandPositions() { - if (controllersExist()) { - return _listener->handPositions; - } - else { - static std::vector stubData; - stubData.clear(); - if (_doFakeFingers) { - // Simulated data - glm::vec3 handOffset(0.0f, 50.0f, 50.0f); - stubData.push_back(glm::vec3( 0.0f, 0.0f, 0.0f) + fakeHandOffset); - } - return stubData; - } -} - -const std::vector& LeapManager::getHandNormals() { - if (controllersExist()) { - return _listener->handNormals; - } - else { - static std::vector stubData; - stubData.clear(); - if (_doFakeFingers) { - // Simulated data - stubData.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); - } - return stubData; - } -} - std::string LeapManager::statusString() { std::stringstream leapString; #ifndef LEAP_STUBS diff --git a/interface/src/LeapManager.h b/interface/src/LeapManager.h index e6ac304677..11dbefe849 100755 --- a/interface/src/LeapManager.h +++ b/interface/src/LeapManager.h @@ -13,6 +13,7 @@ #include #include +class Avatar; class HifiLeapListener; namespace Leap { class Controller; @@ -20,7 +21,7 @@ namespace Leap { class LeapManager { public: - static void nextFrame(); // called once per frame to get new Leap data + static void nextFrame(Avatar& avatar); // called once per frame to get new Leap data static bool controllersExist(); // Returns true if there's at least one active Leap plugged in static void enableFakeFingers(bool enable); // put fake data in if there's no Leap plugged in static const std::vector& getFingerTips(); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index ffe5615823..982b53b288 100755 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -24,6 +24,7 @@ PalmData::PalmData(HandData* owningHandData) : _rawPosition(0, 0, 0), _rawNormal(0, 1, 0), _isActive(false), +_leapID(-1), _owningHandData(owningHandData) { for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) { @@ -35,6 +36,7 @@ FingerData::FingerData(PalmData* owningPalmData, HandData* owningHandData) : _tipRawPosition(0, 0, 0), _rootRawPosition(0, 0, 0), _isActive(false), +_leapID(-1), _owningPalmData(owningPalmData), _owningHandData(owningHandData) { diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index f52171b403..61512d8ece 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -68,8 +68,10 @@ public: const glm::vec3& getTipRawPosition() const { return _tipRawPosition; } const glm::vec3& getRootRawPosition() const { return _rootRawPosition; } bool isActive() const { return _isActive; } + int getLeapID() const { return _leapID; } void setActive(bool active) { _isActive = active; } + void setLeapID(int id) { _leapID = id; } void setRawTipPosition(const glm::vec3& pos) { _tipRawPosition = pos; } void setRawRootPosition(const glm::vec3& pos) { _rootRawPosition = pos; } void setTrailLength(unsigned int length); @@ -81,7 +83,8 @@ public: private: glm::vec3 _tipRawPosition; glm::vec3 _rootRawPosition; - bool _isActive; // This has current valid data + bool _isActive; // This has current valid data + int _leapID; // the Leap's serial id for this tracked object std::vector _tipTrailPositions; int _tipTrailCurrentStartIndex; int _tipTrailCurrentValidLength; @@ -97,11 +100,13 @@ public: const glm::vec3& getRawPosition() const { return _rawPosition; } const glm::vec3& getRawNormal() const { return _rawNormal; } bool isActive() const { return _isActive; } + int getLeapID() const { return _leapID; } std::vector& getFingers() { return _fingers; } size_t getNumFingers() { return _fingers.size(); } void setActive(bool active) { _isActive = active; } + void setLeapID(int id) { _leapID = id; } void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; } @@ -109,7 +114,8 @@ private: std::vector _fingers; glm::vec3 _rawPosition; glm::vec3 _rawNormal; - bool _isActive; // This has current valid data + bool _isActive; // This has current valid data + int _leapID; // the Leap's serial id for this tracked object HandData* _owningHandData; }; From c2ab5c4d9827d4e6fadf860bd459e667d8515c65 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 11:42:37 -0700 Subject: [PATCH 09/50] more work on voxel stats --- libraries/voxels/src/VoxelSceneStats.cpp | 47 +++++++----------------- libraries/voxels/src/VoxelSceneStats.h | 32 +++++++--------- libraries/voxels/src/VoxelTree.cpp | 20 +++++++--- voxel-server/src/main.cpp | 2 +- 4 files changed, 43 insertions(+), 58 deletions(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 254f099e3f..7d91a363c5 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -68,17 +68,8 @@ void VoxelSceneStats::reset() { _leavesDidntFit = 0; _colorBitsWritten = 0; - _internalColorBitsWritten = 0; - _leavesColorBitsWritten = 0; - _existsBitsWritten = 0; - _internalExistsBitsWritten = 0; - _leavesExistsBitsWritten = 0; - _existsInPacketBitsWritten = 0; - _internalExistsInPacketBitsWritten = 0; - _leavesExistsInPacketBitsWritten = 0; - } void VoxelSceneStats::packetSent(int bytes) { @@ -158,33 +149,27 @@ void VoxelSceneStats::didntFit(const VoxelNode* node) { } } -void VoxelSceneStats::colorBitsWritten(const VoxelNode* node) { +void VoxelSceneStats::colorBitsWritten() { _colorBitsWritten++; - if (node->isLeaf()) { - _leavesColorBitsWritten++; - } else { - _internalColorBitsWritten++; - } } -void VoxelSceneStats::existsBitsWritten(const VoxelNode* node) { +void VoxelSceneStats::existsBitsWritten() { _existsBitsWritten++; - if (node->isLeaf()) { - _leavesExistsBitsWritten++; - } else { - _internalExistsBitsWritten++; - } } -void VoxelSceneStats::existsInPacketBitsWritten(const VoxelNode* node) { +void VoxelSceneStats::existsInPacketBitsWritten() { _existsInPacketBitsWritten++; - if (node->isLeaf()) { - _leavesExistsInPacketBitsWritten++; - } else { - _internalExistsInPacketBitsWritten++; - } } +void VoxelSceneStats::childBitsRemoved(bool includesExistsBits, bool includesColors) { + _existsInPacketBitsWritten--; + if (includesExistsBits) { + _existsBitsWritten--; + } + if (includesColors) { + _colorBitsWritten--; + } +} void VoxelSceneStats::printDebugDetails() { @@ -227,12 +212,6 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" internal : %lu\n", _internalDidntFit ); qDebug(" leaves : %lu\n", _leavesDidntFit ); qDebug(" color bits : %lu\n", _colorBitsWritten ); - qDebug(" internal : %lu\n", _internalColorBitsWritten ); - qDebug(" leaves : %lu\n", _leavesColorBitsWritten ); qDebug(" exists bits : %lu\n", _existsBitsWritten ); - qDebug(" internal : %lu\n", _internalExistsBitsWritten); - qDebug(" leaves : %lu\n", _leavesExistsBitsWritten ); - qDebug(" in packet bit : %lu\n", _existsInPacketBitsWritten ); - qDebug(" internal : %lu\n", _internalExistsInPacketBitsWritten); - qDebug(" leaves : %lu\n", _leavesExistsInPacketBitsWritten ); + qDebug(" in packet bit : %lu\n", _existsInPacketBitsWritten); } diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index 29461996b3..526d7f38a6 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -31,9 +31,10 @@ public: void skippedOccluded(const VoxelNode* node); void colorSent(const VoxelNode* node); void didntFit(const VoxelNode* node); - void colorBitsWritten(const VoxelNode* node); - void existsBitsWritten(const VoxelNode* node); - void existsInPacketBitsWritten(const VoxelNode* node); + void colorBitsWritten(); + void existsBitsWritten(); + void existsInPacketBitsWritten(); + void childBitsRemoved(bool includesExistsBits, bool includesColors); private: // scene timing data in usecs @@ -75,24 +76,19 @@ private: unsigned long _leavesDidntFit; unsigned long _colorBitsWritten; - unsigned long _internalColorBitsWritten; - unsigned long _leavesColorBitsWritten; - unsigned long _existsBitsWritten; - unsigned long _internalExistsBitsWritten; - unsigned long _leavesExistsBitsWritten; - unsigned long _existsInPacketBitsWritten; - unsigned long _internalExistsInPacketBitsWritten; - unsigned long _leavesExistsInPacketBitsWritten; - unsigned long total; - unsigned long internalOutOfView; - unsigned long internalOccluded; - unsigned long internalDirty; - unsigned long leavesOutOfView; - unsigned long leavesOccluded; - unsigned long leavesDirty; + // Accounting Notes: + // + // 1) number of voxels sent can be calculated as _colorSent + _colorBitsWritten. This works because each internal + // node in a packet will have a _colorBitsWritten included for it and each "leaf" in the packet will have a + // _colorSent written for it. Note that these "leaf" nodes in the packets may not be actual leaves in the full + // tree, because LOD may cause us to send an average color for an internal node instead of recursing deeper to + // the leaves. + // + // 2) the stats balance if: _traversed = all skipped + all sent + // // scene network related data unsigned int _packets; diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 13e55bea0f..2939cd3258 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1302,7 +1302,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // track some stats if (params.stats) { - if (!shouldRender) { + if (!shouldRender && childNode->isLeaf()) { params.stats->skippedDistance(childNode); } if (childIsOccluded) { @@ -1352,7 +1352,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count if (params.stats) { - params.stats->colorBitsWritten(node); + params.stats->colorBitsWritten(); } // write the color data... @@ -1379,7 +1379,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp writeToThisLevelBuffer += sizeof(childrenExistInTreeBits); // move the pointer bytesAtThisLevel += sizeof(childrenExistInTreeBits); // keep track of byte count if (params.stats) { - params.stats->existsBitsWritten(node); + params.stats->existsBitsWritten(); } } @@ -1388,7 +1388,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp writeToThisLevelBuffer += sizeof(childrenExistInPacketBits); // move the pointer bytesAtThisLevel += sizeof(childrenExistInPacketBits); // keep track of byte count if (params.stats) { - params.stats->existsInPacketBitsWritten(node); + params.stats->existsInPacketBitsWritten(); } // We only need to keep digging, if there is at least one child that is inView, and not a leaf. @@ -1467,7 +1467,12 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // so, if the child returns 2 bytes out, we can actually consider that an empty tree also!! // // we can make this act like no bytes out, by just resetting the bytes out in this case - if (params.includeColor && childTreeBytesOut == 2) { + if (params.includeColor && !params.includeExistsBits && childTreeBytesOut == 2) { + childTreeBytesOut = 0; // this is the degenerate case of a tree with no colors and no child trees + } + // If we've asked for existBits, this is also true, except that the tree will output 3 bytes + // NOTE: does this introduce a problem with detecting deletion?? + if (params.includeColor && params.includeExistsBits && childTreeBytesOut == 3) { childTreeBytesOut = 0; // this is the degenerate case of a tree with no colors and no child trees } @@ -1482,6 +1487,11 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp childrenExistInPacketBits -= (1 << (7 - originalIndex)); // repair the child exists mask *childExistsPlaceHolder = childrenExistInPacketBits; + + if (params.stats) { + params.stats->childBitsRemoved(params.includeExistsBits, params.includeColor); + } + // Note: no need to move the pointer, cause we already stored this } // end if (childTreeBytesOut == 0) } // end if (oneAtBit(childrenExistInPacketBits, originalIndex)) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 770a22bd23..92c835d776 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -143,6 +143,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, } nodeList->getNodeSocket()->send(node->getActiveSocket(), nodeData->getPacket(), nodeData->getPacketLength()); + nodeData->stats.packetSent(nodeData->getPacketLength()); trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; nodeData->resetVoxelPacket(); @@ -261,7 +262,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, } else { nodeList->getNodeSocket()->send(node->getActiveSocket(), nodeData->getPacket(), nodeData->getPacketLength()); - nodeData->stats.packetSent(nodeData->getPacketLength()); trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; From 92f7f06af9eb1513b077275b8583649c118dc528 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 12:00:51 -0700 Subject: [PATCH 10/50] more stats --- libraries/voxels/src/VoxelSceneStats.cpp | 3 +++ libraries/voxels/src/VoxelSceneStats.h | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 7d91a363c5..c5586ef957 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -70,6 +70,7 @@ void VoxelSceneStats::reset() { _colorBitsWritten = 0; _existsBitsWritten = 0; _existsInPacketBitsWritten = 0; + _treesRemoved = 0; } void VoxelSceneStats::packetSent(int bytes) { @@ -169,6 +170,7 @@ void VoxelSceneStats::childBitsRemoved(bool includesExistsBits, bool includesCol if (includesColors) { _colorBitsWritten--; } + _treesRemoved++; } @@ -214,4 +216,5 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" color bits : %lu\n", _colorBitsWritten ); qDebug(" exists bits : %lu\n", _existsBitsWritten ); qDebug(" in packet bit : %lu\n", _existsInPacketBitsWritten); + qDebug(" trees removed : %lu\n", _treesRemoved ); } diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index 526d7f38a6..e31b53a8ae 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -78,6 +78,7 @@ private: unsigned long _colorBitsWritten; unsigned long _existsBitsWritten; unsigned long _existsInPacketBitsWritten; + unsigned long _treesRemoved; // Accounting Notes: // @@ -87,7 +88,11 @@ private: // tree, because LOD may cause us to send an average color for an internal node instead of recursing deeper to // the leaves. // - // 2) the stats balance if: _traversed = all skipped + all sent + // 2) the stats balance if: (working assumption) + // if _colorSent > 0 + / _traversed = all skipped + _colorSent + _colorBitsWritten + // else + // _traversed = all skipped + _colorSent + _colorBitsWritten + _treesRemoved // // scene network related data From 787c448856a5bf9fdc423cbb5339931186fd24d3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 12:29:54 -0700 Subject: [PATCH 11/50] include elapsed encoding time in voxel stats, fixed issue with subtree removal stats --- libraries/voxels/src/VoxelSceneStats.cpp | 19 ++++++++++++++++--- libraries/voxels/src/VoxelSceneStats.h | 8 +++++++- libraries/voxels/src/VoxelTree.cpp | 3 ++- voxel-server/src/main.cpp | 4 +++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index c5586ef957..bf3d59a3db 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -29,8 +29,20 @@ void VoxelSceneStats::sceneCompleted() { _end = usecTimestampNow(); _elapsed = _end - _start; } + +void VoxelSceneStats::encodeStarted() { + _encodeStart = usecTimestampNow(); +} + +void VoxelSceneStats::encodeStopped() { + _totalEncodeTime += (usecTimestampNow() - _encodeStart); +} + void VoxelSceneStats::reset() { + _totalEncodeTime = 0; + _encodeStart = 0; + _packets = 0; _bytes = 0; _passes = 0; @@ -177,9 +189,10 @@ void VoxelSceneStats::childBitsRemoved(bool includesExistsBits, bool includesCol void VoxelSceneStats::printDebugDetails() { qDebug("\n------------------------------\n"); qDebug("VoxelSceneStats:\n"); - qDebug(" start : %llu \n", _start); - qDebug(" end : %llu \n", _end); - qDebug(" elapsed: %llu \n", _elapsed); + qDebug(" start : %llu \n", _start); + qDebug(" end : %llu \n", _end); + qDebug(" elapsed : %llu \n", _elapsed); + qDebug(" encoding : %llu \n", _totalEncodeTime); qDebug("\n"); qDebug(" full scene: %s\n", debug::valueOf(_fullSceneDraw)); qDebug(" moving: %s\n", debug::valueOf(_moving)); diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index e31b53a8ae..2310e5e199 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -22,6 +22,9 @@ public: void sceneCompleted(); void printDebugDetails(); void packetSent(int bytes); + + void encodeStarted(); + void encodeStopped(); void traversed(const VoxelNode* node); void skippedDistance(const VoxelNode* node); @@ -41,6 +44,9 @@ private: uint64_t _start; uint64_t _end; uint64_t _elapsed; + + uint64_t _totalEncodeTime; + uint64_t _encodeStart; // scene voxel related data unsigned long _traversed; @@ -90,7 +96,7 @@ private: // // 2) the stats balance if: (working assumption) // if _colorSent > 0 - / _traversed = all skipped + _colorSent + _colorBitsWritten + // _traversed = all skipped + _colorSent + _colorBitsWritten // else // _traversed = all skipped + _colorSent + _colorBitsWritten + _treesRemoved // diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 2939cd3258..11297313f8 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1488,7 +1488,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // repair the child exists mask *childExistsPlaceHolder = childrenExistInPacketBits; - if (params.stats) { + // If this is the last of the child exists bits, then we're actually be rolling out the entire tree + if (params.stats && childrenExistInPacketBits == 0) { params.stats->childBitsRemoved(params.includeExistsBits, params.includeColor); } diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 92c835d776..69abbcdcce 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -253,9 +253,11 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, wantOcclusionCulling, coverageMap, boundaryLevelAdjust, nodeData->getLastTimeBagEmpty(), fullScene, &nodeData->stats); - + + nodeData->stats.encodeStarted(); bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeData->nodeBag, params); + nodeData->stats.encodeStopped(); if (nodeData->getAvailable() >= bytesWritten) { nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten); From b97ef2a2c63131c0a34a11fe1dd049964678e44f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 13:54:20 -0700 Subject: [PATCH 12/50] made voxel stats a command line option --- voxel-server/src/main.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 69abbcdcce..502563a9ef 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -60,6 +60,7 @@ bool wantLocalDomain = false; bool wantColorRandomizer = false; bool debugVoxelSending = false; bool shouldShowAnimationDebug = false; +bool displayVoxelStats = false; EnvironmentData environmentData[3]; @@ -204,7 +205,10 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, } nodeData->stats.sceneCompleted(); - nodeData->stats.printDebugDetails(); + + if (::displayVoxelStats) { + nodeData->stats.printDebugDetails(); + } // This is the start of "resending" the scene. nodeData->nodeBag.insert(serverTree.rootNode); @@ -380,7 +384,9 @@ void *distributeVoxelsToListeners(void *args) { if (usecToSleep > 0) { usleep(usecToSleep); } else { - std::cout << "Last send took too much time, not sleeping!\n"; + if (::debugVoxelSending) { + std::cout << "Last send took too much time, not sleeping!\n"; + } } } @@ -413,6 +419,10 @@ int main(int argc, const char * argv[]) { nodeList->startSilentNodeRemovalThread(); srand((unsigned)time(0)); + + const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; + ::displayVoxelStats = cmdOptionExists(argc, argv, DISPLAY_VOXEL_STATS); + printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); From d9c8a59929ec4d87e9574b63504f5c4f1fc162d6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 15:09:38 -0700 Subject: [PATCH 13/50] send voxel scene stats from server to client --- interface/src/Application.cpp | 8 ++ libraries/shared/src/PacketHeaders.h | 1 + libraries/voxels/src/VoxelSceneStats.cpp | 151 +++++++++++++++++++++++ libraries/voxels/src/VoxelSceneStats.h | 3 + voxel-server/src/main.cpp | 5 + 5 files changed, 168 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index adb88147e9..524b5ccd09 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -56,6 +56,8 @@ #include #include +#include + #include "Application.h" #include "InterfaceConfig.h" #include "LogDisplay.h" @@ -3337,6 +3339,12 @@ void* Application::networkReceive(void* args) { if (packetVersionMatch(app->_incomingPacket)) { // only process this packet if we have a match on the packet version switch (app->_incomingPacket[0]) { + case PACKET_TYPE_VOXEL_STATS:{ + VoxelSceneStats stats; + int statsMessageLength = stats.unpackFromMessage(app->_incomingPacket, bytesReceived); + stats.printDebugDetails(); + break; + } case PACKET_TYPE_TRANSMITTER_DATA_V2: // V2 = IOS transmitter app app->_myTransmitter.processIncomingData(app->_incomingPacket, bytesReceived); diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 041303f2b5..16cda5ce1e 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -33,6 +33,7 @@ const PACKET_TYPE PACKET_TYPE_TRANSMITTER_DATA_V2 = 'T'; const PACKET_TYPE PACKET_TYPE_ENVIRONMENT_DATA = 'e'; const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L'; const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C'; +const PACKET_TYPE PACKET_TYPE_VOXEL_STATS = '#'; typedef char PACKET_VERSION; diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index bf3d59a3db..0368c530ec 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -6,6 +6,7 @@ // // +#include #include #include "VoxelNode.h" @@ -185,6 +186,156 @@ void VoxelSceneStats::childBitsRemoved(bool includesExistsBits, bool includesCol _treesRemoved++; } +int VoxelSceneStats::packIntoMessage(unsigned char* destinationBuffer, int availableBytes) { + unsigned char* bufferStart = destinationBuffer; + + int headerLength = populateTypeAndVersion(destinationBuffer, PACKET_TYPE_VOXEL_STATS); + destinationBuffer += headerLength; + + memcpy(destinationBuffer, &_start, sizeof(_start)); + destinationBuffer += sizeof(_start); + memcpy(destinationBuffer, &_end, sizeof(_end)); + destinationBuffer += sizeof(_end); + memcpy(destinationBuffer, &_elapsed, sizeof(_elapsed)); + destinationBuffer += sizeof(_elapsed); + memcpy(destinationBuffer, &_totalEncodeTime, sizeof(_totalEncodeTime)); + destinationBuffer += sizeof(_totalEncodeTime); + memcpy(destinationBuffer, &_fullSceneDraw, sizeof(_fullSceneDraw)); + destinationBuffer += sizeof(_fullSceneDraw); + memcpy(destinationBuffer, &_moving, sizeof(_moving)); + destinationBuffer += sizeof(_moving); + memcpy(destinationBuffer, &_packets, sizeof(_packets)); + destinationBuffer += sizeof(_packets); + memcpy(destinationBuffer, &_bytes, sizeof(_bytes)); + destinationBuffer += sizeof(_bytes); + + memcpy(destinationBuffer, &_internal, sizeof(_internal)); + destinationBuffer += sizeof(_internal); + memcpy(destinationBuffer, &_leaves, sizeof(_leaves)); + destinationBuffer += sizeof(_leaves); + memcpy(destinationBuffer, &_internalSkippedDistance, sizeof(_internalSkippedDistance)); + destinationBuffer += sizeof(_internalSkippedDistance); + memcpy(destinationBuffer, &_leavesSkippedDistance, sizeof(_leavesSkippedDistance)); + destinationBuffer += sizeof(_leavesSkippedDistance); + memcpy(destinationBuffer, &_internalSkippedOutOfView, sizeof(_internalSkippedOutOfView)); + destinationBuffer += sizeof(_internalSkippedOutOfView); + memcpy(destinationBuffer, &_leavesSkippedOutOfView, sizeof(_leavesSkippedOutOfView)); + destinationBuffer += sizeof(_leavesSkippedOutOfView); + memcpy(destinationBuffer, &_internalSkippedWasInView, sizeof(_internalSkippedWasInView)); + destinationBuffer += sizeof(_internalSkippedWasInView); + memcpy(destinationBuffer, &_leavesSkippedWasInView, sizeof(_leavesSkippedWasInView)); + destinationBuffer += sizeof(_leavesSkippedWasInView); + memcpy(destinationBuffer, &_internalSkippedNoChange, sizeof(_internalSkippedNoChange)); + destinationBuffer += sizeof(_internalSkippedNoChange); + memcpy(destinationBuffer, &_leavesSkippedNoChange, sizeof(_leavesSkippedNoChange)); + destinationBuffer += sizeof(_leavesSkippedNoChange); + memcpy(destinationBuffer, &_internalSkippedOccluded, sizeof(_internalSkippedOccluded)); + destinationBuffer += sizeof(_internalSkippedOccluded); + memcpy(destinationBuffer, &_leavesSkippedOccluded, sizeof(_leavesSkippedOccluded)); + destinationBuffer += sizeof(_leavesSkippedOccluded); + memcpy(destinationBuffer, &_internalColorSent, sizeof(_internalColorSent)); + destinationBuffer += sizeof(_internalColorSent); + memcpy(destinationBuffer, &_leavesColorSent, sizeof(_leavesColorSent)); + destinationBuffer += sizeof(_leavesColorSent); + memcpy(destinationBuffer, &_internalDidntFit, sizeof(_internalDidntFit)); + destinationBuffer += sizeof(_internalDidntFit); + memcpy(destinationBuffer, &_leavesDidntFit, sizeof(_leavesDidntFit)); + destinationBuffer += sizeof(_leavesDidntFit); + memcpy(destinationBuffer, &_colorBitsWritten, sizeof(_colorBitsWritten)); + destinationBuffer += sizeof(_colorBitsWritten); + memcpy(destinationBuffer, &_existsBitsWritten, sizeof(_existsBitsWritten)); + destinationBuffer += sizeof(_existsBitsWritten); + memcpy(destinationBuffer, &_existsInPacketBitsWritten, sizeof(_existsInPacketBitsWritten)); + destinationBuffer += sizeof(_existsInPacketBitsWritten); + memcpy(destinationBuffer, &_treesRemoved, sizeof(_treesRemoved)); + destinationBuffer += sizeof(_treesRemoved); + + return destinationBuffer - bufferStart; // includes header! +} + +int VoxelSceneStats::unpackFromMessage(unsigned char* sourceBuffer, int availableBytes) { + unsigned char* startPosition = sourceBuffer; + + // increment to push past the packet header + int numBytesPacketHeader = numBytesForPacketHeader(sourceBuffer); + sourceBuffer += numBytesPacketHeader; + + memcpy(&_start, sourceBuffer, sizeof(_start)); + sourceBuffer += sizeof(_start); + memcpy(&_end, sourceBuffer, sizeof(_end)); + sourceBuffer += sizeof(_end); + memcpy(&_elapsed, sourceBuffer, sizeof(_elapsed)); + sourceBuffer += sizeof(_elapsed); + memcpy(&_totalEncodeTime, sourceBuffer, sizeof(_totalEncodeTime)); + sourceBuffer += sizeof(_totalEncodeTime); + memcpy(&_fullSceneDraw, sourceBuffer, sizeof(_fullSceneDraw)); + sourceBuffer += sizeof(_fullSceneDraw); + memcpy(&_moving, sourceBuffer, sizeof(_moving)); + sourceBuffer += sizeof(_moving); + memcpy(&_packets, sourceBuffer, sizeof(_packets)); + sourceBuffer += sizeof(_packets); + memcpy(&_bytes, sourceBuffer, sizeof(_bytes)); + sourceBuffer += sizeof(_bytes); + memcpy(&_internal, sourceBuffer, sizeof(_internal)); + sourceBuffer += sizeof(_internal); + memcpy(&_leaves, sourceBuffer, sizeof(_leaves)); + sourceBuffer += sizeof(_leaves); + _traversed = _internal + _leaves; + + memcpy(&_internalSkippedDistance, sourceBuffer, sizeof(_internalSkippedDistance)); + sourceBuffer += sizeof(_internalSkippedDistance); + memcpy(&_leavesSkippedDistance, sourceBuffer, sizeof(_leavesSkippedDistance)); + sourceBuffer += sizeof(_leavesSkippedDistance); + _skippedDistance = _internalSkippedDistance + _leavesSkippedDistance; + + memcpy(&_internalSkippedOutOfView, sourceBuffer, sizeof(_internalSkippedOutOfView)); + sourceBuffer += sizeof(_internalSkippedOutOfView); + memcpy(&_leavesSkippedOutOfView, sourceBuffer, sizeof(_leavesSkippedOutOfView)); + sourceBuffer += sizeof(_leavesSkippedOutOfView); + _skippedOutOfView = _internalSkippedOutOfView + _leavesSkippedOutOfView; + + memcpy(&_internalSkippedWasInView, sourceBuffer, sizeof(_internalSkippedWasInView)); + sourceBuffer += sizeof(_internalSkippedWasInView); + memcpy(&_leavesSkippedWasInView, sourceBuffer, sizeof(_leavesSkippedWasInView)); + sourceBuffer += sizeof(_leavesSkippedWasInView); + _skippedWasInView = _internalSkippedWasInView + _leavesSkippedWasInView; + + memcpy(&_internalSkippedNoChange, sourceBuffer, sizeof(_internalSkippedNoChange)); + sourceBuffer += sizeof(_internalSkippedNoChange); + memcpy(&_leavesSkippedNoChange, sourceBuffer, sizeof(_leavesSkippedNoChange)); + sourceBuffer += sizeof(_leavesSkippedNoChange); + _skippedNoChange = _internalSkippedNoChange + _leavesSkippedNoChange; + + memcpy(&_internalSkippedOccluded, sourceBuffer, sizeof(_internalSkippedOccluded)); + sourceBuffer += sizeof(_internalSkippedOccluded); + memcpy(&_leavesSkippedOccluded, sourceBuffer, sizeof(_leavesSkippedOccluded)); + sourceBuffer += sizeof(_leavesSkippedOccluded); + _skippedOccluded = _internalSkippedOccluded + _leavesSkippedOccluded; + + memcpy(&_internalColorSent, sourceBuffer, sizeof(_internalColorSent)); + sourceBuffer += sizeof(_internalColorSent); + memcpy(&_leavesColorSent, sourceBuffer, sizeof(_leavesColorSent)); + sourceBuffer += sizeof(_leavesColorSent); + _colorSent = _internalColorSent + _leavesColorSent; + + memcpy(&_internalDidntFit, sourceBuffer, sizeof(_internalDidntFit)); + sourceBuffer += sizeof(_internalDidntFit); + memcpy(&_leavesDidntFit, sourceBuffer, sizeof(_leavesDidntFit)); + sourceBuffer += sizeof(_leavesDidntFit); + _didntFit = _internalDidntFit + _leavesDidntFit; + + memcpy(&_colorBitsWritten, sourceBuffer, sizeof(_colorBitsWritten)); + sourceBuffer += sizeof(_colorBitsWritten); + memcpy(&_existsBitsWritten, sourceBuffer, sizeof(_existsBitsWritten)); + sourceBuffer += sizeof(_existsBitsWritten); + memcpy(&_existsInPacketBitsWritten, sourceBuffer, sizeof(_existsInPacketBitsWritten)); + sourceBuffer += sizeof(_existsInPacketBitsWritten); + memcpy(&_treesRemoved, sourceBuffer, sizeof(_treesRemoved)); + sourceBuffer += sizeof(_treesRemoved); + + return sourceBuffer - startPosition; // includes header! +} + void VoxelSceneStats::printDebugDetails() { qDebug("\n------------------------------\n"); diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index 2310e5e199..93146ffa88 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -38,6 +38,9 @@ public: void existsBitsWritten(); void existsInPacketBitsWritten(); void childBitsRemoved(bool includesExistsBits, bool includesColors); + + int packIntoMessage(unsigned char* destinationBuffer, int availableBytes); + int unpackFromMessage(unsigned char* sourceBuffer, int availableBytes); private: // scene timing data in usecs diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 502563a9ef..5ae2874a34 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -209,6 +209,11 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, if (::displayVoxelStats) { nodeData->stats.printDebugDetails(); } + + // Send the stats message to the client + unsigned char statsMessage[MAX_PACKET_SIZE]; + int statsMessageLength = nodeData->stats.packIntoMessage(statsMessage, sizeof(statsMessage)); + nodeList->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength); // This is the start of "resending" the scene. nodeData->nodeBag.insert(serverTree.rootNode); From 2cc42f67738313e9a63b0bcccd1f6bd23fc4c4ac Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 15:59:47 -0700 Subject: [PATCH 14/50] support piggybacking voxel and voxel stats messages into single packet --- interface/src/Application.cpp | 35 +++++++++---- libraries/voxels/src/VoxelSceneStats.cpp | 4 ++ libraries/voxels/src/VoxelSceneStats.h | 12 +++++ voxel-server/src/main.cpp | 64 ++++++++++++++++-------- 4 files changed, 85 insertions(+), 30 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 524b5ccd09..345ede0274 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3339,12 +3339,6 @@ void* Application::networkReceive(void* args) { if (packetVersionMatch(app->_incomingPacket)) { // only process this packet if we have a match on the packet version switch (app->_incomingPacket[0]) { - case PACKET_TYPE_VOXEL_STATS:{ - VoxelSceneStats stats; - int statsMessageLength = stats.unpackFromMessage(app->_incomingPacket, bytesReceived); - stats.printDebugDetails(); - break; - } case PACKET_TYPE_TRANSMITTER_DATA_V2: // V2 = IOS transmitter app app->_myTransmitter.processIncomingData(app->_incomingPacket, bytesReceived); @@ -3357,16 +3351,39 @@ void* Application::networkReceive(void* args) { case PACKET_TYPE_VOXEL_DATA_MONOCHROME: case PACKET_TYPE_Z_COMMAND: case PACKET_TYPE_ERASE_VOXEL: + case PACKET_TYPE_VOXEL_STATS: case PACKET_TYPE_ENVIRONMENT_DATA: { + + unsigned char* messageData = app->_incomingPacket; + ssize_t messageLength = bytesReceived; + + // note: PACKET_TYPE_VOXEL_STATS can have PACKET_TYPE_VOXEL_DATA or PACKET_TYPE_VOXEL_DATA_MONOCHROME + // 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) { + VoxelSceneStats stats; + int statsMessageLength = stats.unpackFromMessage(messageData, messageLength); + stats.printDebugDetails(); + if (messageLength > statsMessageLength) { + messageData += statsMessageLength; + messageLength -= statsMessageLength; + if (!packetVersionMatch(messageData)) { + break; // bail since piggyback data doesn't match our versioning + } + } else { + break; // bail since no piggyback data + } + } // fall through to piggyback message + if (app->_renderVoxels->isChecked()) { Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER); if (voxelServer) { voxelServer->lock(); - if (app->_incomingPacket[0] == PACKET_TYPE_ENVIRONMENT_DATA) { - app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived); + if (messageData[0] == PACKET_TYPE_ENVIRONMENT_DATA) { + app->_environment.parseData(&senderAddress, messageData, messageLength); } else { - app->_voxels.parseData(app->_incomingPacket, bytesReceived); + app->_voxels.parseData(messageData, messageLength); } voxelServer->unlock(); diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 0368c530ec..ab25b725bb 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -14,6 +14,7 @@ VoxelSceneStats::VoxelSceneStats() { reset(); + _readyToSend = false; } VoxelSceneStats::~VoxelSceneStats() { @@ -29,6 +30,9 @@ void VoxelSceneStats::sceneStarted(bool fullScene, bool moving) { void VoxelSceneStats::sceneCompleted() { _end = usecTimestampNow(); _elapsed = _end - _start; + + _statsMessageLength = packIntoMessage(_statsMessage, sizeof(_statsMessage)); + _readyToSend = true; } void VoxelSceneStats::encodeStarted() { diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index 93146ffa88..05545f3320 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -10,6 +10,7 @@ #define __hifi__VoxelSceneStats__ #include +#include class VoxelNode; @@ -20,6 +21,7 @@ public: void reset(); void sceneStarted(bool fullScene, bool moving); void sceneCompleted(); + void printDebugDetails(); void packetSent(int bytes); @@ -41,8 +43,18 @@ public: int packIntoMessage(unsigned char* destinationBuffer, int availableBytes); int unpackFromMessage(unsigned char* sourceBuffer, int availableBytes); + + bool readyToSend() const { return _readyToSend; } + void markAsSent() { _readyToSend = false; } + unsigned char* getStatsMessage() { return &_statsMessage[0]; } + int getStatsMessageLength() const { return _statsMessageLength; } + private: + bool _readyToSend; + unsigned char _statsMessage[MAX_PACKET_SIZE]; + int _statsMessageLength; + // scene timing data in usecs uint64_t _start; uint64_t _end; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 5ae2874a34..6244ee190d 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -112,6 +112,44 @@ void eraseVoxelTreeAndCleanupNodeVisitData() { pthread_mutex_t treeLock; +void handlePacketSend(NodeList* nodeList, + NodeList::iterator& node, + VoxelNodeData* nodeData, + int& trueBytesSent, int& truePacketsSent) { + // If we've got a stats message ready to send, then see if we can piggyback them together + if (nodeData->stats.readyToSend()) { + // Send the stats message to the client + unsigned char* statsMessage = nodeData->stats.getStatsMessage(); + int statsMessageLength = nodeData->stats.getStatsMessageLength(); + + // If the size of the stats message and the voxel message will fit in a packet, then piggyback them + if (nodeData->getPacketLength() + statsMessageLength < MAX_PACKET_SIZE) { + + // copy voxel message to back of stats message + memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); + statsMessageLength += nodeData->getPacketLength(); + + // actually send it + nodeList->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength); + } else { + // not enough room in the packet, send two packets + nodeList->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength); + nodeList->getNodeSocket()->send(node->getActiveSocket(), + nodeData->getPacket(), nodeData->getPacketLength()); + } + } else { + // just send the voxel packet + nodeList->getNodeSocket()->send(node->getActiveSocket(), + nodeData->getPacket(), nodeData->getPacketLength()); + } + // remember to track our stats + nodeData->stats.packetSent(nodeData->getPacketLength()); + trueBytesSent += nodeData->getPacketLength(); + truePacketsSent++; + nodeData->resetVoxelPacket(); +} + + // Version of voxel distributor that sends the deepest LOD level at once void deepestLevelVoxelDistributor(NodeList* nodeList, NodeList::iterator& node, @@ -142,12 +180,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, printf("wantColor=%s --- SENDING PARTIAL PACKET! nodeData->getCurrentPacketIsColor()=%s\n", debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor())); } - nodeList->getNodeSocket()->send(node->getActiveSocket(), - nodeData->getPacket(), nodeData->getPacketLength()); - nodeData->stats.packetSent(nodeData->getPacketLength()); - trueBytesSent += nodeData->getPacketLength(); - truePacketsSent++; - nodeData->resetVoxelPacket(); + + handlePacketSend(nodeList, node, nodeData, trueBytesSent, truePacketsSent); + } else { if (::debugVoxelSending) { printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n", @@ -209,11 +244,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, if (::displayVoxelStats) { nodeData->stats.printDebugDetails(); } - - // Send the stats message to the client - unsigned char statsMessage[MAX_PACKET_SIZE]; - int statsMessageLength = nodeData->stats.packIntoMessage(statsMessage, sizeof(statsMessage)); - nodeList->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength); // This is the start of "resending" the scene. nodeData->nodeBag.insert(serverTree.rootNode); @@ -271,22 +301,14 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, if (nodeData->getAvailable() >= bytesWritten) { nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten); } else { - nodeList->getNodeSocket()->send(node->getActiveSocket(), - nodeData->getPacket(), nodeData->getPacketLength()); - nodeData->stats.packetSent(nodeData->getPacketLength()); - trueBytesSent += nodeData->getPacketLength(); - truePacketsSent++; + handlePacketSend(nodeList, node, nodeData, trueBytesSent, truePacketsSent); packetsSentThisInterval++; nodeData->resetVoxelPacket(); nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten); } } else { if (nodeData->isPacketWaiting()) { - nodeList->getNodeSocket()->send(node->getActiveSocket(), - nodeData->getPacket(), nodeData->getPacketLength()); - nodeData->stats.packetSent(nodeData->getPacketLength()); - trueBytesSent += nodeData->getPacketLength(); - truePacketsSent++; + handlePacketSend(nodeList, node, nodeData, trueBytesSent, truePacketsSent); nodeData->resetVoxelPacket(); } packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left From 83290bc8b7ac0a769c43b4df216ea2f289c12fe7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 17:28:37 -0700 Subject: [PATCH 15/50] first cut at real voxel stats dialog box --- interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 25 +++++++- interface/src/Application.h | 7 +++ interface/src/ui/VoxelStatsDialog.cpp | 74 ++++++++++++++++++++++++ interface/src/ui/VoxelStatsDialog.h | 45 ++++++++++++++ libraries/voxels/src/VoxelSceneStats.cpp | 27 +++++++++ libraries/voxels/src/VoxelSceneStats.h | 21 +++++++ 7 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 interface/src/ui/VoxelStatsDialog.cpp create mode 100644 interface/src/ui/VoxelStatsDialog.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 829ccbff06..9625c1b78d 100755 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -75,7 +75,7 @@ add_subdirectory(external/fervor/) include_directories(external/fervor/) # run qt moc on qt-enabled headers -qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/AvatarVoxelSystem.h src/Webcam.h src/ui/BandwidthDialog.h) +qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/AvatarVoxelSystem.h src/Webcam.h src/ui/BandwidthDialog.h src/ui/VoxelStatsDialog.h) # create the executable, make it a bundle on OS X add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS}) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 345ede0274..fddfdfef07 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -176,6 +176,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _window(new QMainWindow(desktop())), _glWidget(new GLCanvas()), _bandwidthDialog(NULL), + _voxelStatsDialog(NULL), _displayLevels(false), _frameCount(0), _fps(120.0f), @@ -1097,6 +1098,21 @@ void Application::bandwidthDetailsClosed() { delete dlg; } +void Application::voxelStatsDetails() { + if (!_voxelStatsDialog) { + _voxelStatsDialog = new VoxelStatsDialog(_glWidget, &_voxelSceneStats); + connect(_voxelStatsDialog, SIGNAL(closed()), SLOT(voxelStatsDetailsClosed())); + _voxelStatsDialog->show(); + } + _voxelStatsDialog->raise(); +} + +void Application::voxelStatsDetailsClosed() { + QDialog* dlg = _voxelStatsDialog; + _voxelStatsDialog = NULL; + delete dlg; +} + void Application::editPreferences() { QDialog dialog(_glWidget); dialog.setWindowTitle("Interface Preferences"); @@ -1695,6 +1711,7 @@ void Application::initMenu() { (_bandwidthDisplayOn = toolsMenu->addAction("Bandwidth Display"))->setCheckable(true); _bandwidthDisplayOn->setChecked(true); toolsMenu->addAction("Bandwidth Details", this, SLOT(bandwidthDetails())); + toolsMenu->addAction("Voxel Stats Details", this, SLOT(voxelStatsDetails())); QMenu* voxelMenu = menuBar->addMenu("Voxels"); @@ -2128,6 +2145,9 @@ void Application::update(float deltaTime) { if (_bandwidthDialog) { _bandwidthDialog->update(); } + if (_voxelStatsDialog) { + _voxelStatsDialog->update(); + } // Update audio stats for procedural sounds #ifndef _WIN32 @@ -3361,9 +3381,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) { - VoxelSceneStats stats; - int statsMessageLength = stats.unpackFromMessage(messageData, messageLength); - stats.printDebugDetails(); + int statsMessageLength = app->_voxelSceneStats.unpackFromMessage(messageData, messageLength); + app->_voxelSceneStats.printDebugDetails(); if (messageLength > statsMessageLength) { messageData += statsMessageLength; messageLength -= statsMessageLength; diff --git a/interface/src/Application.h b/interface/src/Application.h index 9333808a27..05df195a3e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -39,6 +39,7 @@ #include "ToolsPalette.h" #include "ui/ChatEntry.h" #include "ui/BandwidthDialog.h" +#include "ui/VoxelStatsDialog.h" #include "ViewFrustum.h" #include "VoxelSystem.h" #include "Webcam.h" @@ -116,6 +117,9 @@ private slots: void bandwidthDetails(); void editPreferences(); void bandwidthDetailsClosed(); + + void voxelStatsDetails(); + void voxelStatsDetailsClosed(); void pair(); @@ -277,6 +281,7 @@ private: BandwidthMeter _bandwidthMeter; BandwidthDialog* _bandwidthDialog; + VoxelStatsDialog* _voxelStatsDialog; SerialInterface _serialHeadSensor; QNetworkAccessManager* _networkAccessManager; @@ -406,6 +411,8 @@ private: ToolsPalette _palette; Swatch _swatch; + + VoxelSceneStats _voxelSceneStats; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp new file mode 100644 index 0000000000..455ea0cfb0 --- /dev/null +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -0,0 +1,74 @@ +// +// VoxelStatsDialog.cpp +// interface +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include +#include + +#include +#include + +#include + +#include "ui/VoxelStatsDialog.h" + + +VoxelStatsDialog::VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model) : + QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint), + _model(model) { + + char strBuf[64]; + + this->setWindowTitle("Voxel Statistics"); + + // Create layouter + QFormLayout* form = new QFormLayout(); + this->QDialog::setLayout(form); + + // Setup labels + for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; ++i) { + VoxelSceneStats::ItemInfo& itemInfo = _model->getItemInfo(i); + QLabel* label = _labels[i] = new QLabel(); + label->setAlignment(Qt::AlignRight); + + // Set foreground color to 62.5% brightness of the meter (otherwise will be hard to read on the bright background) + QPalette palette = label->palette(); + unsigned rgb = itemInfo.colorRGBA >> 8; + rgb = ((rgb & 0xfefefeu) >> 1) + ((rgb & 0xf8f8f8) >> 3); + palette.setColor(QPalette::WindowText, QColor::fromRgb(rgb)); + label->setPalette(palette); + + snprintf(strBuf, sizeof(strBuf), " %s:", itemInfo.caption); + form->addRow(strBuf, label); + } +} + +void VoxelStatsDialog::paintEvent(QPaintEvent* event) { + + // Update labels + char strBuf[64]; + for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; ++i) { + QLabel* label = _labels[i]; + snprintf(strBuf, sizeof(strBuf), "%s", _model->getItemValue(i)); + label->setText(strBuf); + } + + this->QDialog::paintEvent(event); + this->setFixedSize(this->width(), this->height()); +} + +void VoxelStatsDialog::reject() { + // Just regularly close upon ESC + this->QDialog::close(); +} + +void VoxelStatsDialog::closeEvent(QCloseEvent* event) { + this->QDialog::closeEvent(event); + emit closed(); +} + + diff --git a/interface/src/ui/VoxelStatsDialog.h b/interface/src/ui/VoxelStatsDialog.h new file mode 100644 index 0000000000..1d30ec8881 --- /dev/null +++ b/interface/src/ui/VoxelStatsDialog.h @@ -0,0 +1,45 @@ +// +// VoxelStatsDialog.h +// interface +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__VoxelStatsDialog__ +#define __hifi__VoxelStatsDialog__ + +#include +#include + +#include + +class VoxelStatsDialog : public QDialog { + Q_OBJECT +public: + + // Sets up the UI + VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model); + +signals: + void closed(); + +public slots: + + void reject(); + +protected: + + // State <- data model held by BandwidthMeter + void paintEvent(QPaintEvent*); + + // Emits a 'closed' signal when this dialog is closed. + void closeEvent(QCloseEvent*); + +private: + QLabel* _labels[VoxelSceneStats::ITEM_COUNT]; + VoxelSceneStats* _model; +}; + +#endif /* defined(__interface__VoxelStatsDialog__) */ + diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index ab25b725bb..02ee47c6c1 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -12,6 +12,7 @@ #include "VoxelNode.h" #include "VoxelSceneStats.h" + VoxelSceneStats::VoxelSceneStats() { reset(); _readyToSend = false; @@ -386,3 +387,29 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" in packet bit : %lu\n", _existsInPacketBitsWritten); qDebug(" trees removed : %lu\n", _treesRemoved ); } + + +VoxelSceneStats::ItemInfo VoxelSceneStats::_ITEMS[] = { + { "Elapsed" , "usecs", 0x40ff40d0 }, + { "Encode" , "usecs", 0xffef40c0 }, + { "Packets" , "" , 0xd0d0d0a0 } +}; + +char* VoxelSceneStats::getItemValue(int item) { + switch(item) { + case ITEM_ELAPSED: + sprintf(_itemValueBuffer, "%llu", _elapsed); + break; + case ITEM_ENCODE: + sprintf(_itemValueBuffer, "%llu", _totalEncodeTime); + break; + case ITEM_PACKETS: + sprintf(_itemValueBuffer, "%d", _packets); + break; + default: + sprintf(_itemValueBuffer, ""); + break; + } + return _itemValueBuffer; +} + diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index 05545f3320..99880c591d 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -49,6 +49,22 @@ public: unsigned char* getStatsMessage() { return &_statsMessage[0]; } int getStatsMessageLength() const { return _statsMessageLength; } + enum { + ITEM_ELAPSED, + ITEM_ENCODE, + ITEM_PACKETS, + ITEM_COUNT + }; + + // Meta information about each stats item + struct ItemInfo { + char const* const caption; + char const* unitCaption; + unsigned colorRGBA; + }; + + ItemInfo& getItemInfo(int item) { return _ITEMS[item]; }; + char* getItemValue(int item); private: bool _readyToSend; @@ -124,6 +140,11 @@ private: // features related items bool _moving; bool _fullSceneDraw; + + + static ItemInfo _ITEMS[]; + static int const MAX_ITEM_VALUE_LENGTH = 40; + char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH]; }; #endif /* defined(__hifi__VoxelSceneStats__) */ From 4e8ce1b193600cea126be7d95f9b6d0c118a10df Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Jul 2013 18:15:06 -0700 Subject: [PATCH 16/50] tweaks to stats dialog --- interface/src/ui/VoxelStatsDialog.cpp | 3 ++- libraries/voxels/src/VoxelSceneStats.cpp | 24 ++++++++++++++++-------- libraries/voxels/src/VoxelSceneStats.h | 5 ++--- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index 455ea0cfb0..d365990dcf 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -41,6 +41,7 @@ VoxelStatsDialog::VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model) : rgb = ((rgb & 0xfefefeu) >> 1) + ((rgb & 0xf8f8f8) >> 3); palette.setColor(QPalette::WindowText, QColor::fromRgb(rgb)); label->setPalette(palette); + label->setText(" "); snprintf(strBuf, sizeof(strBuf), " %s:", itemInfo.caption); form->addRow(strBuf, label); @@ -50,7 +51,7 @@ VoxelStatsDialog::VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model) : void VoxelStatsDialog::paintEvent(QPaintEvent* event) { // Update labels - char strBuf[64]; + char strBuf[256]; for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; ++i) { QLabel* label = _labels[i]; snprintf(strBuf, sizeof(strBuf), "%s", _model->getItemValue(i)); diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 02ee47c6c1..3251c607f1 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -354,7 +354,7 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" moving: %s\n", debug::valueOf(_moving)); qDebug("\n"); qDebug(" packets: %d\n", _packets); - qDebug(" bytes : %d\n", _bytes); + qDebug(" bytes : %ld\n", _bytes); qDebug("\n"); qDebug(" traversed : %lu\n", _traversed ); qDebug(" internal : %lu\n", _internal ); @@ -390,22 +390,30 @@ void VoxelSceneStats::printDebugDetails() { VoxelSceneStats::ItemInfo VoxelSceneStats::_ITEMS[] = { - { "Elapsed" , "usecs", 0x40ff40d0 }, - { "Encode" , "usecs", 0xffef40c0 }, - { "Packets" , "" , 0xd0d0d0a0 } + { "Elapsed" , 0x40ff40d0 }, + { "Encode" , 0xffef40c0 }, + { "Network" , 0xd0d0d0a0 } }; char* VoxelSceneStats::getItemValue(int item) { + const uint64_t USECS_PER_SECOND = 1000 * 1000; + int calcFPS; + int calculatedKBPS; switch(item) { case ITEM_ELAPSED: - sprintf(_itemValueBuffer, "%llu", _elapsed); + calcFPS = (float)USECS_PER_SECOND / (float)_elapsed; + sprintf(_itemValueBuffer, "%llu usecs (%d fps)", _elapsed, calcFPS); break; case ITEM_ENCODE: - sprintf(_itemValueBuffer, "%llu", _totalEncodeTime); + calcFPS = (float)USECS_PER_SECOND / (float)_totalEncodeTime; + sprintf(_itemValueBuffer, "%llu usecs (%d fps)", _totalEncodeTime, calcFPS); break; - case ITEM_PACKETS: - sprintf(_itemValueBuffer, "%d", _packets); + case ITEM_PACKETS: { + float elapsedSecs = ((float)_elapsed / (float)USECS_PER_SECOND); + calculatedKBPS = elapsedSecs == 0 ? 0 : ((_bytes * 8) / elapsedSecs) / 1000; + sprintf(_itemValueBuffer, "%d packets %lu bytes (%d kbps)", _packets, _bytes, calculatedKBPS); break; + } default: sprintf(_itemValueBuffer, ""); break; diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index 99880c591d..d58d21d0e0 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -59,7 +59,6 @@ public: // Meta information about each stats item struct ItemInfo { char const* const caption; - char const* unitCaption; unsigned colorRGBA; }; @@ -134,7 +133,7 @@ private: // scene network related data unsigned int _packets; - unsigned int _bytes; + unsigned long _bytes; unsigned int _passes; // features related items @@ -143,7 +142,7 @@ private: static ItemInfo _ITEMS[]; - static int const MAX_ITEM_VALUE_LENGTH = 40; + static int const MAX_ITEM_VALUE_LENGTH = 128; char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH]; }; From b8cf4a9775057c218f3999c861dff59004717241 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Fri, 19 Jul 2013 19:47:07 -0700 Subject: [PATCH 17/50] Rave glove: stabilization of Leap hands --- interface/src/LeapManager.cpp | 165 +++++++++++++++-------------- libraries/avatars/src/HandData.cpp | 18 ++-- libraries/avatars/src/HandData.h | 14 ++- 3 files changed, 108 insertions(+), 89 deletions(-) diff --git a/interface/src/LeapManager.cpp b/interface/src/LeapManager.cpp index 36be287e01..31bd15eb68 100755 --- a/interface/src/LeapManager.cpp +++ b/interface/src/LeapManager.cpp @@ -54,15 +54,6 @@ void LeapManager::nextFrame(Avatar& avatar) { // If we actually get valid Leap data, this will be set to true; bool gotRealData = false; - // First, deactivate everything. - for (size_t i = 0; i < hand.getNumPalms(); ++i) { - PalmData& palm = hand.getPalms()[i]; - palm.setActive(false); - for (size_t f = 0; f < palm.getNumFingers(); ++f) { - FingerData& finger = palm.getFingers()[f]; - finger.setActive(false); - } - } if (controllersExist()) { _listener->onFrame(*_controller); @@ -70,57 +61,70 @@ void LeapManager::nextFrame(Avatar& avatar) { #ifndef LEAP_STUBS if (controllersExist()) { - // Performance note: - // This is a first pass. - // Once all of this is stable, perfoamance may be improved ysing std::map or another - // associative container to match serialized Leap ID's with available fingers. - // That will make this code shorter and more efficient. - + gotRealData = true; // First, see which palms and fingers are still valid. Leap::Frame& frame = _listener->lastFrame; // Note that this is O(n^2) at worst, but n is very small. + // After this many frames of no data, assume the digit is lost. + const int assumeLostAfterFrameCount = 10; + + // Increment our frame data counters + for (size_t i = 0; i < hand.getNumPalms(); ++i) { + PalmData& palm = hand.getPalms()[i]; + palm.incrementFramesWithoutData(); + if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) { + palm.setActive(false); + } + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.incrementFramesWithoutData(); + if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) { + finger.setActive(false); + } + } + } + size_t numLeapHands = frame.hands().count(); std::vector palmAssignment(numLeapHands); + // Look for matches for (size_t index = 0; index < numLeapHands; ++index) { + PalmData* takeoverCandidate = NULL; palmAssignment[index] = NULL; Leap::Hand leapHand = frame.hands()[index]; int id = leapHand.id(); if (leapHand.isValid()) { - for (size_t i = 0; i < hand.getNumPalms(); ++i) { + for (size_t i = 0; i < hand.getNumPalms() && palmAssignment[index] == NULL; ++i) { PalmData& palm = hand.getPalms()[i]; if (palm.getLeapID() == id) { // Found hand with the same ID. We're set! palmAssignment[index] = &palm; - palm.setActive(true); - } - } - } - } - // Fill empty slots - for (size_t index = 0; index < numLeapHands; ++index) { - if (palmAssignment[index] == NULL) { - Leap::Hand leapHand = frame.hands()[index]; - if (leapHand.isValid()) { - for (size_t i = 0; i < hand.getNumPalms() && palmAssignment[index] == NULL; ++i) { - PalmData& palm = hand.getPalms()[i]; - if (!palm.isActive()) { - // Found a free hand to use. - palmAssignment[index] = &palm; - palm.setActive(true); - palm.setLeapID(leapHand.id()); - } + palm.resetFramesWithoutData(); } + else if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) { + takeoverCandidate = &palm; + } + } + if (palmAssignment[index] == NULL) { + palmAssignment[index] = takeoverCandidate; + } + if (palmAssignment[index] == NULL) { + palmAssignment[index] = &hand.addNewPalm(); } } } + // Apply the assignments for (size_t index = 0; index < numLeapHands; ++index) { if (palmAssignment[index]) { Leap::Hand leapHand = frame.hands()[index]; PalmData& palm = *(palmAssignment[index]); + + palm.resetFramesWithoutData(); + palm.setLeapID(leapHand.id()); + palm.setActive(true); const Leap::Vector pos = leapHand.palmPosition(); const Leap::Vector normal = leapHand.palmNormal(); palm.setRawPosition(glm::vec3(pos.x, pos.y, pos.z)); @@ -128,59 +132,58 @@ void LeapManager::nextFrame(Avatar& avatar) { } } - size_t numLeapFingers = frame.fingers().count(); - std::vector fingerAssignment(numLeapFingers); - // Look for matches - for (size_t index = 0; index < numLeapFingers; ++index) { - fingerAssignment[index] = NULL; - Leap::Finger leapFinger = frame.fingers()[index]; - int id = leapFinger.id(); - if (leapFinger.isValid()) { - for (size_t i = 0; i < hand.getNumPalms(); ++i) { - PalmData& palm = hand.getPalms()[i]; - for (size_t f = 0; f < palm.getNumFingers(); ++f) { - FingerData& finger = palm.getFingers()[f]; - if (finger.getLeapID() == id) { - // Found finger with the same ID. We're set! - fingerAssignment[index] = &finger; - finger.setActive(true); - } - } - } - } - } - // Fill empty slots - for (size_t index = 0; index < numLeapFingers; ++index) { - if (fingerAssignment[index] == NULL) { - Leap::Finger leapFinger = frame.fingers()[index]; - if (leapFinger.isValid()) { - for (size_t i = 0; i < hand.getNumPalms() && fingerAssignment[index] == NULL; ++i) { - PalmData& palm = hand.getPalms()[i]; - for (size_t f = 0; f < palm.getNumFingers() && fingerAssignment[index] == NULL; ++f) { - FingerData& finger = palm.getFingers()[f]; - if (!finger.isActive()) { - // Found a free finger to use. - fingerAssignment[index] = &finger; - finger.setActive(true); - finger.setLeapID(leapFinger.id()); + // Look for fingers per palm + for (size_t i = 0; i < hand.getNumPalms(); ++i) { + PalmData& palm = hand.getPalms()[i]; + if (palm.isActive()) { + Leap::Hand leapHand = frame.hand(palm.getLeapID()); + if (leapHand.isValid()) { + int numLeapFingers = leapHand.fingers().count(); + std::vector fingerAssignment(numLeapFingers); + + + // Look for matches + for (size_t index = 0; index < numLeapFingers; ++index) { + FingerData* takeoverCandidate = NULL; + fingerAssignment[index] = NULL; + Leap::Finger leapFinger = leapHand.fingers()[index]; + int id = leapFinger.id(); + if (leapFinger.isValid()) { + for (size_t f = 0; f < palm.getNumFingers() && fingerAssignment[index] == NULL; ++f) { + FingerData& finger = palm.getFingers()[f]; + if (finger.getLeapID() == id) { + // Found hand with the same ID. We're set! + fingerAssignment[index] = &finger; + } + else if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) { + takeoverCandidate = &finger; + } + } + // If we didn't find a match, but we found an unused finger, us it. + if (fingerAssignment[index] == NULL) { + fingerAssignment[index] = takeoverCandidate; } } } + + // Apply the assignments + for (size_t index = 0; index < numLeapFingers; ++index) { + if (fingerAssignment[index]) { + Leap::Finger leapFinger = leapHand.fingers()[index]; + FingerData& finger = *(fingerAssignment[index]); + + finger.resetFramesWithoutData(); + finger.setLeapID(leapFinger.id()); + finger.setActive(true); + const Leap::Vector tip = leapFinger.stabilizedTipPosition(); + const Leap::Vector root = tip - leapFinger.direction() * leapFinger.length(); + finger.setRawTipPosition(glm::vec3(tip.x, tip.y, tip.z)); + finger.setRawRootPosition(glm::vec3(root.x, root.y, root.z)); + } + } } } } - // Apply the assignments - for (size_t index = 0; index < numLeapFingers; ++index) { - if (fingerAssignment[index]) { - Leap::Finger leapFinger = frame.fingers()[index]; - FingerData& finger = *(fingerAssignment[index]); - const Leap::Vector tip = leapFinger.stabilizedTipPosition(); - const Leap::Vector root = tip - leapFinger.direction() * leapFinger.length(); - finger.setRawTipPosition(glm::vec3(tip.x, tip.y, tip.z)); - finger.setRawRootPosition(glm::vec3(root.x, root.y, root.z)); - } - } - gotRealData = true; } #endif if (!gotRealData) { diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 982b53b288..785aaa45de 100755 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -13,18 +13,19 @@ HandData::HandData(AvatarData* owningAvatar) : _baseOrientation(0.0f, 0.0f, 0.0f, 1.0f), _owningAvatarData(owningAvatar) { - for (int i = 0; i < 2; ++i) { - _palms.push_back(PalmData(this)); - } - const int standardTrailLength = 30; - setFingerTrailLength(standardTrailLength); +} + +PalmData& HandData::addNewPalm() { + _palms.push_back(PalmData(this)); + return _palms.back(); } PalmData::PalmData(HandData* owningHandData) : _rawPosition(0, 0, 0), _rawNormal(0, 1, 0), _isActive(false), -_leapID(-1), +_leapID(LEAPID_INVALID), +_numFramesWithoutData(0), _owningHandData(owningHandData) { for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) { @@ -36,10 +37,13 @@ FingerData::FingerData(PalmData* owningPalmData, HandData* owningHandData) : _tipRawPosition(0, 0, 0), _rootRawPosition(0, 0, 0), _isActive(false), -_leapID(-1), +_leapID(LEAPID_INVALID), +_numFramesWithoutData(0), _owningPalmData(owningPalmData), _owningHandData(owningHandData) { + const int standardTrailLength = 30; + setTrailLength(standardTrailLength); } void HandData::encodeRemoteData(std::vector& fingerVectors) { diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 61512d8ece..d2b5cae90d 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -20,6 +20,7 @@ class FingerData; class PalmData; const int NUM_FINGERS_PER_HAND = 5; +const int LEAPID_INVALID = -1; class HandData { public: @@ -39,6 +40,7 @@ public: std::vector& getPalms() { return _palms; } size_t getNumPalms() { return _palms.size(); } + PalmData& addNewPalm(); void setFingerTrailLength(unsigned int length); void updateFingerTrails(); @@ -79,12 +81,17 @@ public: int getTrailNumPositions(); const glm::vec3& getTrailPosition(int index); - + + void incrementFramesWithoutData() { _numFramesWithoutData++; } + void resetFramesWithoutData() { _numFramesWithoutData = 0; } + int getFramesWithoutData() const { return _numFramesWithoutData; } + private: glm::vec3 _tipRawPosition; glm::vec3 _rootRawPosition; bool _isActive; // This has current valid data int _leapID; // the Leap's serial id for this tracked object + int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost. std::vector _tipTrailPositions; int _tipTrailCurrentStartIndex; int _tipTrailCurrentValidLength; @@ -110,12 +117,17 @@ public: void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; } + void incrementFramesWithoutData() { _numFramesWithoutData++; } + void resetFramesWithoutData() { _numFramesWithoutData = 0; } + int getFramesWithoutData() const { return _numFramesWithoutData; } + private: std::vector _fingers; glm::vec3 _rawPosition; glm::vec3 _rawNormal; bool _isActive; // This has current valid data int _leapID; // the Leap's serial id for this tracked object + int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost. HandData* _owningHandData; }; From d10ffd4f2d1c0bc248c9192dbc652b328eaf5d20 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Fri, 19 Jul 2013 19:53:30 -0700 Subject: [PATCH 18/50] Small .h fix after testing without Leap libs --- interface/src/LeapManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/LeapManager.cpp b/interface/src/LeapManager.cpp index 31bd15eb68..a941d0a221 100755 --- a/interface/src/LeapManager.cpp +++ b/interface/src/LeapManager.cpp @@ -7,7 +7,7 @@ // #include "LeapManager.h" -#include "Avatar.h" +#include "avatar/Avatar.h" #include #include // needed for RTLD_LAZY #include From 6ceb48127a4104c0290cc6d668e591db7079faab Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Fri, 19 Jul 2013 19:56:05 -0700 Subject: [PATCH 19/50] Small fix when no Leap connected. --- libraries/avatars/src/HandData.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 785aaa45de..7bb6eebdc0 100755 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -13,6 +13,9 @@ HandData::HandData(AvatarData* owningAvatar) : _baseOrientation(0.0f, 0.0f, 0.0f, 1.0f), _owningAvatarData(owningAvatar) { + // Start with two palms + addNewPalm(); + addNewPalm(); } PalmData& HandData::addNewPalm() { From e0f115298dc533a61841d78a05d90028348c6604 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 20 Jul 2013 11:28:12 -0700 Subject: [PATCH 20/50] additional stats items --- interface/src/Application.cpp | 1 - interface/src/ui/VoxelStatsDialog.cpp | 4 +- libraries/voxels/src/VoxelSceneStats.cpp | 89 +++++++++++++++++++++++- libraries/voxels/src/VoxelSceneStats.h | 12 ++++ 4 files changed, 101 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fddfdfef07..8126567ff5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3382,7 +3382,6 @@ void* Application::networkReceive(void* args) { // 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); - app->_voxelSceneStats.printDebugDetails(); if (messageLength > statsMessageLength) { messageData += statsMessageLength; messageLength -= statsMessageLength; diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index d365990dcf..8ab7df3ddd 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -41,7 +41,9 @@ VoxelStatsDialog::VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model) : rgb = ((rgb & 0xfefefeu) >> 1) + ((rgb & 0xf8f8f8) >> 3); palette.setColor(QPalette::WindowText, QColor::fromRgb(rgb)); label->setPalette(palette); - label->setText(" "); + + // This is my hackery attempt at making QDialog auto-size to a width that will hold our info. It kinda works. + label->setText("123456789012345678901234567890123456789012345678901234567890"); snprintf(strBuf, sizeof(strBuf), " %s:", itemInfo.caption); form->addRow(strBuf, label); diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 3251c607f1..199068101e 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -390,9 +390,21 @@ void VoxelSceneStats::printDebugDetails() { VoxelSceneStats::ItemInfo VoxelSceneStats::_ITEMS[] = { - { "Elapsed" , 0x40ff40d0 }, - { "Encode" , 0xffef40c0 }, - { "Network" , 0xd0d0d0a0 } + { "Elapsed" , 0x40ff40d0 }, + { "Encode" , 0xffef40c0 }, + { "Network" , 0xd0d0d0a0 }, + { "Voxels Sent" , 0x40ff40d0 }, + { "Colors Sent" , 0xffef40c0 }, + { "Bitmasks Sent" , 0xd0d0d0a0 }, + { "Traversed" , 0x40ff40d0 }, + { "Skipped - Total" , 0xffef40c0 }, + { "Skipped - Distance" , 0xd0d0d0a0 }, + { "Skipped - Out of View", 0x40ff40d0 }, + { "Skipped - Was in View", 0xffef40c0 }, + { "Skipped - No Change" , 0xd0d0d0a0 }, + { "Skipped - Occluded" , 0x40ff40d0 }, + { "Didn't fit in packet" , 0xffef40c0 }, + { "Mode" , 0xd0d0d0a0 }, }; char* VoxelSceneStats::getItemValue(int item) { @@ -414,6 +426,77 @@ char* VoxelSceneStats::getItemValue(int item) { sprintf(_itemValueBuffer, "%d packets %lu bytes (%d kbps)", _packets, _bytes, calculatedKBPS); break; } + case ITEM_VOXELS: { + unsigned long total = _existsInPacketBitsWritten + _colorSent; + float calculatedBPV = total == 0 ? 0 : (_bytes * 8) / total; + sprintf(_itemValueBuffer, "%lu total (%.2f bits/voxel) %lu internal %lu leaves", + total, calculatedBPV, _existsInPacketBitsWritten, _colorSent); + break; + } + case ITEM_TRAVERSED: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _traversed, _internal, _leaves); + break; + } + case ITEM_SKIPPED: { + unsigned long total = _skippedDistance + _skippedOutOfView + + _skippedWasInView + _skippedNoChange + _skippedOccluded; + + unsigned long internal = _internalSkippedDistance + _internalSkippedOutOfView + + _internalSkippedWasInView + _internalSkippedNoChange + _internalSkippedOccluded; + + unsigned long leaves = _leavesSkippedDistance + _leavesSkippedOutOfView + + _leavesSkippedWasInView + _leavesSkippedNoChange + _leavesSkippedOccluded; + + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + total, internal, leaves); + break; + } + case ITEM_SKIPPED_DISTANCE: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _skippedDistance, _internalSkippedDistance, _leavesSkippedDistance); + break; + } + case ITEM_SKIPPED_OUT_OF_VIEW: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _skippedOutOfView, _internalSkippedOutOfView, _leavesSkippedOutOfView); + break; + } + case ITEM_SKIPPED_WAS_IN_VIEW: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _skippedWasInView, _internalSkippedWasInView, _leavesSkippedWasInView); + break; + } + case ITEM_SKIPPED_NO_CHANGE: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _skippedNoChange, _internalSkippedNoChange, _leavesSkippedNoChange); + break; + } + case ITEM_SKIPPED_OCCLUDED: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _skippedOccluded, _internalSkippedOccluded, _leavesSkippedOccluded); + break; + } + case ITEM_COLORS: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _colorSent, _internalColorSent, _leavesColorSent); + break; + } + case ITEM_DIDNT_FIT: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves (removed: %lu)", + _didntFit, _internalDidntFit, _leavesDidntFit, _treesRemoved); + break; + } + case ITEM_BITS: { + sprintf(_itemValueBuffer, "colors: %lu, exists: %lu, in packets: %lu", + _colorBitsWritten, _existsBitsWritten, _existsInPacketBitsWritten); + break; + } + case ITEM_MODE: { + sprintf(_itemValueBuffer, "%s - %s", (_fullSceneDraw ? "Full Scene" : "Partial Scene"), + (_moving ? "Moving" : "Stationary")); + break; + } default: sprintf(_itemValueBuffer, ""); break; diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index d58d21d0e0..fb7931e6e7 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -53,6 +53,18 @@ public: ITEM_ELAPSED, ITEM_ENCODE, ITEM_PACKETS, + ITEM_VOXELS, + ITEM_COLORS, + ITEM_BITS, + ITEM_TRAVERSED, + ITEM_SKIPPED, + ITEM_SKIPPED_DISTANCE, + ITEM_SKIPPED_OUT_OF_VIEW, + ITEM_SKIPPED_WAS_IN_VIEW, + ITEM_SKIPPED_NO_CHANGE, + ITEM_SKIPPED_OCCLUDED, + ITEM_DIDNT_FIT, + ITEM_MODE, ITEM_COUNT }; From de7cd4db03c7b805e9f043c889f6812af6b6d3aa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 20 Jul 2013 15:49:04 -0700 Subject: [PATCH 21/50] added total voxel count to stats --- libraries/voxels/src/VoxelNode.cpp | 20 ++++++++ libraries/voxels/src/VoxelNode.h | 8 ++++ libraries/voxels/src/VoxelSceneStats.cpp | 60 +++++++++++++++++------- libraries/voxels/src/VoxelSceneStats.h | 7 ++- libraries/voxels/src/VoxelTree.cpp | 3 ++ voxel-server/src/main.cpp | 8 ++-- 6 files changed, 86 insertions(+), 20 deletions(-) diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 1268449ac6..34eb2b2261 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -44,6 +44,8 @@ void VoxelNode::init(unsigned char * octalCode) { _children[i] = NULL; } _childCount = 0; + _subtreeNodeCount = 1; // that's me + _subtreeLeafNodeCount = 0; // that's me _glBufferIndex = GLBUFFER_INDEX_UNKNOWN; _isDirty = true; @@ -79,6 +81,24 @@ void VoxelNode::handleSubtreeChanged(VoxelTree* myTree) { if (myTree->getShouldReaverage()) { setColorFromAverageOfChildren(); } + + recalculateSubTreeNodeCount(); +} + +void VoxelNode::recalculateSubTreeNodeCount() { + // Assuming the tree below me as changed, I need to recalculate my node count + _subtreeNodeCount = 1; // that's me + if (isLeaf()) { + _subtreeLeafNodeCount = 1; + } else { + _subtreeLeafNodeCount = 0; + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + if (_children[i]) { + _subtreeNodeCount += _children[i]->_subtreeNodeCount; + _subtreeLeafNodeCount += _children[i]->_subtreeLeafNodeCount; + } + } + } } diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 431592c2f9..c84ce3c7d6 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -107,6 +107,12 @@ public: static int addDeleteHook(VoxelNodeDeleteHook hook, void* extraData = NULL); static void removeDeleteHook(int hookID); + + void recalculateSubTreeNodeCount(); + unsigned long getSubTreeNodeCount() const { return _subtreeNodeCount; }; + unsigned long getSubTreeInternalNodeCount() const { return _subtreeNodeCount - _subtreeLeafNodeCount; }; + unsigned long getSubTreeLeafNodeCount() const { return _subtreeLeafNodeCount; }; + private: void calculateAABox(); void init(unsigned char * octalCode); @@ -126,6 +132,8 @@ private: unsigned char* _octalCode; VoxelNode* _children[8]; int _childCount; + unsigned long _subtreeNodeCount; + unsigned long _subtreeLeafNodeCount; float _density; // If leaf: density = 1, if internal node: 0-1 density of voxels inside static VoxelNodeDeleteHook _hooks[VOXEL_NODE_MAX_DELETE_HOOKS]; diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 199068101e..d00f746009 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -21,9 +21,13 @@ VoxelSceneStats::VoxelSceneStats() { VoxelSceneStats::~VoxelSceneStats() { } -void VoxelSceneStats::sceneStarted(bool fullScene, bool moving) { - _start = usecTimestampNow(); +void VoxelSceneStats::sceneStarted(bool fullScene, bool moving, VoxelNode* root) { reset(); // resets packet and voxel stats + _start = usecTimestampNow(); + _totalVoxels = root->getSubTreeNodeCount(); + _totalInternal = root->getSubTreeInternalNodeCount(); + _totalLeaves = root->getSubTreeLeafNodeCount(); + _fullSceneDraw = fullScene; _moving = moving; } @@ -53,6 +57,10 @@ void VoxelSceneStats::reset() { _bytes = 0; _passes = 0; + _totalVoxels = 0; + _totalInternal = 0; + _totalLeaves = 0; + _traversed = 0; _internal = 0; _leaves = 0; @@ -214,6 +222,10 @@ int VoxelSceneStats::packIntoMessage(unsigned char* destinationBuffer, int avail memcpy(destinationBuffer, &_bytes, sizeof(_bytes)); destinationBuffer += sizeof(_bytes); + memcpy(destinationBuffer, &_totalInternal, sizeof(_totalInternal)); + destinationBuffer += sizeof(_totalInternal); + memcpy(destinationBuffer, &_totalLeaves, sizeof(_totalLeaves)); + destinationBuffer += sizeof(_totalLeaves); memcpy(destinationBuffer, &_internal, sizeof(_internal)); destinationBuffer += sizeof(_internal); memcpy(destinationBuffer, &_leaves, sizeof(_leaves)); @@ -281,12 +293,19 @@ int VoxelSceneStats::unpackFromMessage(unsigned char* sourceBuffer, int availabl sourceBuffer += sizeof(_packets); memcpy(&_bytes, sourceBuffer, sizeof(_bytes)); sourceBuffer += sizeof(_bytes); + + memcpy(&_totalInternal, sourceBuffer, sizeof(_totalInternal)); + sourceBuffer += sizeof(_totalInternal); + memcpy(&_totalLeaves, sourceBuffer, sizeof(_totalLeaves)); + sourceBuffer += sizeof(_totalLeaves); + _totalVoxels = _totalInternal + _totalLeaves; + memcpy(&_internal, sourceBuffer, sizeof(_internal)); sourceBuffer += sizeof(_internal); memcpy(&_leaves, sourceBuffer, sizeof(_leaves)); sourceBuffer += sizeof(_leaves); _traversed = _internal + _leaves; - + memcpy(&_internalSkippedDistance, sourceBuffer, sizeof(_internalSkippedDistance)); sourceBuffer += sizeof(_internalSkippedDistance); memcpy(&_leavesSkippedDistance, sourceBuffer, sizeof(_leavesSkippedDistance)); @@ -356,6 +375,9 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" packets: %d\n", _packets); qDebug(" bytes : %ld\n", _bytes); qDebug("\n"); + qDebug(" total voxels : %lu\n", _totalVoxels ); + qDebug(" internal : %lu\n", _totalInternal ); + qDebug(" leaves : %lu\n", _totalLeaves ); qDebug(" traversed : %lu\n", _traversed ); qDebug(" internal : %lu\n", _internal ); qDebug(" leaves : %lu\n", _leaves ); @@ -393,18 +415,19 @@ VoxelSceneStats::ItemInfo VoxelSceneStats::_ITEMS[] = { { "Elapsed" , 0x40ff40d0 }, { "Encode" , 0xffef40c0 }, { "Network" , 0xd0d0d0a0 }, - { "Voxels Sent" , 0x40ff40d0 }, - { "Colors Sent" , 0xffef40c0 }, - { "Bitmasks Sent" , 0xd0d0d0a0 }, - { "Traversed" , 0x40ff40d0 }, - { "Skipped - Total" , 0xffef40c0 }, - { "Skipped - Distance" , 0xd0d0d0a0 }, - { "Skipped - Out of View", 0x40ff40d0 }, - { "Skipped - Was in View", 0xffef40c0 }, - { "Skipped - No Change" , 0xd0d0d0a0 }, - { "Skipped - Occluded" , 0x40ff40d0 }, - { "Didn't fit in packet" , 0xffef40c0 }, - { "Mode" , 0xd0d0d0a0 }, + { "Voxels on Server" , 0x40ff40d0 }, + { "Voxels Sent" , 0xffef40c0 }, + { "Colors Sent" , 0xd0d0d0a0 }, + { "Bitmasks Sent" , 0x40ff40d0 }, + { "Traversed" , 0xffef40c0 }, + { "Skipped - Total" , 0xd0d0d0a0 }, + { "Skipped - Distance" , 0x40ff40d0 }, + { "Skipped - Out of View", 0xffef40c0 }, + { "Skipped - Was in View", 0xd0d0d0a0 }, + { "Skipped - No Change" , 0x40ff40d0 }, + { "Skipped - Occluded" , 0xffef40c0 }, + { "Didn't fit in packet" , 0xd0d0d0a0 }, + { "Mode" , 0x40ff40d0 }, }; char* VoxelSceneStats::getItemValue(int item) { @@ -426,10 +449,15 @@ char* VoxelSceneStats::getItemValue(int item) { sprintf(_itemValueBuffer, "%d packets %lu bytes (%d kbps)", _packets, _bytes, calculatedKBPS); break; } + case ITEM_VOXELS_SERVER: { + sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves", + _totalVoxels, _totalInternal, _totalLeaves); + break; + } case ITEM_VOXELS: { unsigned long total = _existsInPacketBitsWritten + _colorSent; float calculatedBPV = total == 0 ? 0 : (_bytes * 8) / total; - sprintf(_itemValueBuffer, "%lu total (%.2f bits/voxel) %lu internal %lu leaves", + sprintf(_itemValueBuffer, "%lu (%.2f bits/voxel) %lu internal %lu leaves", total, calculatedBPV, _existsInPacketBitsWritten, _colorSent); break; } diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index fb7931e6e7..dbf60d3d67 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -19,7 +19,7 @@ public: VoxelSceneStats(); ~VoxelSceneStats(); void reset(); - void sceneStarted(bool fullScene, bool moving); + void sceneStarted(bool fullScene, bool moving, VoxelNode* root); void sceneCompleted(); void printDebugDetails(); @@ -53,6 +53,7 @@ public: ITEM_ELAPSED, ITEM_ENCODE, ITEM_PACKETS, + ITEM_VOXELS_SERVER, ITEM_VOXELS, ITEM_COLORS, ITEM_BITS, @@ -91,6 +92,10 @@ private: uint64_t _encodeStart; // scene voxel related data + unsigned long _totalVoxels; + unsigned long _totalInternal; + unsigned long _totalLeaves; + unsigned long _traversed; unsigned long _internal; unsigned long _leaves; diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 11297313f8..362df3b3f7 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -673,6 +673,9 @@ void VoxelTree::reaverageVoxelColors(VoxelNode *startNode) { if (hasChildren && !startNode->collapseIdenticalLeaves()) { startNode->setColorFromAverageOfChildren(); } + + // this is also a good time to recalculateSubTreeNodeCount() + startNode->recalculateSubTreeNodeCount(); } } diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 6244ee190d..e995012bef 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -250,7 +250,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, // start tracking our stats bool fullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging(); - nodeData->stats.sceneStarted(fullScene, viewFrustumChanged); + nodeData->stats.sceneStarted(fullScene, viewFrustumChanged, ::serverTree.rootNode); } // If we have something in our nodeBag, then turn them into packets and send them out... @@ -486,8 +486,10 @@ int main(int argc, const char * argv[]) { ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); - unsigned long nodeCount = ::serverTree.getVoxelCount(); - printf("Nodes after loading scene %ld nodes\n", nodeCount); + unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); + unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); + unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); + printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); } // Check to see if the user passed in a command line option for loading an old style local From c3fa37019eff9156c29d9b9105ab3bbe4f89eee5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 21 Jul 2013 05:18:35 -0700 Subject: [PATCH 22/50] replaced old voxel stats with new voxel stats --- interface/src/Application.cpp | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 784954710b..0c7820d673 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2865,27 +2865,19 @@ void Application::displayStats() { drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); - voxelStats << "Voxels Created: " << _voxels.getVoxelsCreated() / 1000.f << "K (" << _voxels.getVoxelsCreatedPerSecondAverage() / 1000.f - << "Kps) "; + char* voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_VOXELS); + voxelStats << "Voxels Sent from Server: " << voxelDetails; drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - - voxelStats.str(""); - voxelStats << "Voxels Colored: " << _voxels.getVoxelsColored() / 1000.f << "K (" << _voxels.getVoxelsColoredPerSecondAverage() / 1000.f - << "Kps) "; - drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - - voxelStats.str(""); - voxelStats << "Voxel Bits Read: " << _voxels.getVoxelsBytesRead() * 8.f / 1000000.f - << "M (" << _voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)"; - drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); - float voxelsBytesPerColored = _voxels.getVoxelsColored() - ? ((float) _voxels.getVoxelsBytesRead() / _voxels.getVoxelsColored()) - : 0; - - voxelStats << "Voxels Bits per Colored: " << voxelsBytesPerColored * 8; - drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ELAPSED); + voxelStats << "Scene Send Time from Server: " << voxelDetails; + drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ENCODE); + voxelStats << "Encode Time on Server: " << voxelDetails; + drawtext(10, statsVerticalOffset + 290, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); Node *avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); char avatarMixerStats[200]; From 70c6ed040cbaf04f0601c7bd0f674a16df7d357b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 21 Jul 2013 07:21:23 -0700 Subject: [PATCH 23/50] added averages for bits per voxel and elapsed time --- libraries/voxels/src/VoxelSceneStats.cpp | 40 +++++++++++++++++------- libraries/voxels/src/VoxelSceneStats.h | 4 +++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index d00f746009..c38057ec89 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -13,9 +13,10 @@ #include "VoxelSceneStats.h" -VoxelSceneStats::VoxelSceneStats() { +VoxelSceneStats::VoxelSceneStats() : _elapsedAverage(100), _bitsPerVoxelAverage(100) { reset(); _readyToSend = false; + _started = false; } VoxelSceneStats::~VoxelSceneStats() { @@ -23,6 +24,7 @@ VoxelSceneStats::~VoxelSceneStats() { void VoxelSceneStats::sceneStarted(bool fullScene, bool moving, VoxelNode* root) { reset(); // resets packet and voxel stats + _started = true; _start = usecTimestampNow(); _totalVoxels = root->getSubTreeNodeCount(); _totalInternal = root->getSubTreeInternalNodeCount(); @@ -33,11 +35,15 @@ void VoxelSceneStats::sceneStarted(bool fullScene, bool moving, VoxelNode* root) } void VoxelSceneStats::sceneCompleted() { - _end = usecTimestampNow(); - _elapsed = _end - _start; + if (_started) { + _end = usecTimestampNow(); + _elapsed = _end - _start; + _elapsedAverage.updateAverage((float)_elapsed); - _statsMessageLength = packIntoMessage(_statsMessage, sizeof(_statsMessage)); - _readyToSend = true; + _statsMessageLength = packIntoMessage(_statsMessage, sizeof(_statsMessage)); + _readyToSend = true; + _started = false; + } } void VoxelSceneStats::encodeStarted() { @@ -356,6 +362,13 @@ int VoxelSceneStats::unpackFromMessage(unsigned char* sourceBuffer, int availabl sourceBuffer += sizeof(_existsInPacketBitsWritten); memcpy(&_treesRemoved, sourceBuffer, sizeof(_treesRemoved)); sourceBuffer += sizeof(_treesRemoved); + + // running averages + _elapsedAverage.updateAverage((float)_elapsed); + unsigned long total = _existsInPacketBitsWritten + _colorSent; + float calculatedBPV = total == 0 ? 0 : (_bytes * 8) / total; + _bitsPerVoxelAverage.updateAverage(calculatedBPV); + return sourceBuffer - startPosition; // includes header! } @@ -432,13 +445,17 @@ VoxelSceneStats::ItemInfo VoxelSceneStats::_ITEMS[] = { char* VoxelSceneStats::getItemValue(int item) { const uint64_t USECS_PER_SECOND = 1000 * 1000; - int calcFPS; - int calculatedKBPS; + int calcFPS, calcAverageFPS, calculatedKBPS; switch(item) { - case ITEM_ELAPSED: + case ITEM_ELAPSED: { calcFPS = (float)USECS_PER_SECOND / (float)_elapsed; - sprintf(_itemValueBuffer, "%llu usecs (%d fps)", _elapsed, calcFPS); + float elapsedAverage = _elapsedAverage.getAverage(); + calcAverageFPS = (float)USECS_PER_SECOND / (float)elapsedAverage; + + sprintf(_itemValueBuffer, "%llu usecs (%d fps) Average: %.0f usecs (%d fps)", + _elapsed, calcFPS, elapsedAverage, calcAverageFPS); break; + } case ITEM_ENCODE: calcFPS = (float)USECS_PER_SECOND / (float)_totalEncodeTime; sprintf(_itemValueBuffer, "%llu usecs (%d fps)", _totalEncodeTime, calcFPS); @@ -457,8 +474,9 @@ char* VoxelSceneStats::getItemValue(int item) { case ITEM_VOXELS: { unsigned long total = _existsInPacketBitsWritten + _colorSent; float calculatedBPV = total == 0 ? 0 : (_bytes * 8) / total; - sprintf(_itemValueBuffer, "%lu (%.2f bits/voxel) %lu internal %lu leaves", - total, calculatedBPV, _existsInPacketBitsWritten, _colorSent); + float averageBPV = _bitsPerVoxelAverage.getAverage(); + sprintf(_itemValueBuffer, "%lu (%.2f bits/voxel Average: %.2f bits/voxel) %lu internal %lu leaves", + total, calculatedBPV, averageBPV, _existsInPacketBitsWritten, _colorSent); break; } case ITEM_TRAVERSED: { diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index dbf60d3d67..bf7b38f988 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -84,9 +84,13 @@ private: int _statsMessageLength; // scene timing data in usecs + bool _started; uint64_t _start; uint64_t _end; uint64_t _elapsed; + + SimpleMovingAverage _elapsedAverage; + SimpleMovingAverage _bitsPerVoxelAverage; uint64_t _totalEncodeTime; uint64_t _encodeStart; From 76952a9d13508441c6064d6401384e5e40556eff Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 21 Jul 2013 16:24:23 -0700 Subject: [PATCH 24/50] testing --- libraries/shared/src/PacketHeaders.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 041303f2b5..00c19e657a 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -34,6 +34,8 @@ const PACKET_TYPE PACKET_TYPE_ENVIRONMENT_DATA = 'e'; const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L'; const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C'; +// this is a test... + typedef char PACKET_VERSION; PACKET_VERSION versionForPacketType(PACKET_TYPE type); From 9ab8fecff5101f2e06d07210b045f39fd890f17c Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Mon, 22 Jul 2013 07:19:25 -0700 Subject: [PATCH 25/50] Minor tweaks to Rave Glove mode, per Ryan's testing 1. Improve response by using unfiltered data from Leap library 2. Reduce distracting arm-flail by only attaching the arm to che glove when we're not in rave mode. --- interface/src/LeapManager.cpp | 7 +++++++ interface/src/avatar/Avatar.cpp | 11 ++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/interface/src/LeapManager.cpp b/interface/src/LeapManager.cpp index a941d0a221..883a9c1037 100755 --- a/interface/src/LeapManager.cpp +++ b/interface/src/LeapManager.cpp @@ -12,6 +12,9 @@ #include // needed for RTLD_LAZY #include +// Uncomment the next line to use Leap-smoothed stabilized (slower) data. +//#define USE_STABILIZED_DATA + bool LeapManager::_libraryExists = false; bool LeapManager::_doFakeFingers = false; Leap::Controller* LeapManager::_controller = NULL; @@ -175,7 +178,11 @@ void LeapManager::nextFrame(Avatar& avatar) { finger.resetFramesWithoutData(); finger.setLeapID(leapFinger.id()); finger.setActive(true); +#ifdef USE_STABILIZED_DATA const Leap::Vector tip = leapFinger.stabilizedTipPosition(); +#else + const Leap::Vector tip = leapFinger.tipPosition(); +#endif const Leap::Vector root = tip - leapFinger.direction() * leapFinger.length(); finger.setRawTipPosition(glm::vec3(tip.x, tip.y, tip.z)); finger.setRawRootPosition(glm::vec3(root.x, root.y, root.z)); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ddb78f595b..c2a2d5aadd 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -830,13 +830,14 @@ void Avatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovem } // If there's a leap-interaction hand visible, use that as the endpoint - for (size_t i = 0; i < getHand().getPalms().size(); ++i) { - PalmData& palm = getHand().getPalms()[i]; - if (palm.isActive()) { - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = palm.getPosition(); + if (!getHand().isRaveGloveActive()) { + for (size_t i = 0; i < getHand().getPalms().size(); ++i) { + PalmData& palm = getHand().getPalms()[i]; + if (palm.isActive()) { + _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = palm.getPosition(); + } } } - }//if (_isMine) //constrain right arm length and re-adjust elbow position as it bends From c301b799c5bb215d1195e5d8cd90b8bae7bf3a94 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 13:54:47 -0700 Subject: [PATCH 26/50] first cut at selecting audio sources --- audio-mixer/src/PositionalAudioRingBuffer.cpp | 49 +++++++++++- audio-mixer/src/PositionalAudioRingBuffer.h | 10 +++ interface/src/Application.cpp | 12 ++- interface/src/Audio.cpp | 76 ++++++++++++++++++- interface/src/Audio.h | 13 ++++ libraries/audio/src/AudioRingBuffer.h | 8 ++ libraries/shared/src/PacketHeaders.cpp | 6 ++ libraries/shared/src/PacketHeaders.h | 2 - 8 files changed, 171 insertions(+), 5 deletions(-) diff --git a/audio-mixer/src/PositionalAudioRingBuffer.cpp b/audio-mixer/src/PositionalAudioRingBuffer.cpp index 60ec9a425e..936b71fb79 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.cpp +++ b/audio-mixer/src/PositionalAudioRingBuffer.cpp @@ -16,19 +16,66 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer() : AudioRingBuffer(false), _position(0.0f, 0.0f, 0.0f), _orientation(0.0f, 0.0f, 0.0f, 0.0f), - _willBeAddedToMix(false) + _willBeAddedToMix(false), + _sourceID(-1), + _listenMode(AudioRingBuffer::NORMAL), + _listenRadius(0.0f), + _listenSourceCount(0), + _listenSources(NULL) { } +PositionalAudioRingBuffer::~PositionalAudioRingBuffer() { + if (_listenSources) { + delete[] _listenSources; + } +} + int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer); + currentBuffer += parseSourceData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); + currentBuffer += parseListenModeData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parseAudioSamples(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); return currentBuffer - sourceBuffer; } +int PositionalAudioRingBuffer::parseSourceData(unsigned char* sourceBuffer, int numBytes) { + unsigned char* currentBuffer = sourceBuffer; + + memcpy(&_sourceID, currentBuffer, sizeof(_sourceID)); + currentBuffer += sizeof(_sourceID); + + return currentBuffer - sourceBuffer; +} + +int PositionalAudioRingBuffer::parseListenModeData(unsigned char* sourceBuffer, int numBytes) { + unsigned char* currentBuffer = sourceBuffer; + + memcpy(&_listenMode, currentBuffer, sizeof(_listenMode)); + currentBuffer += sizeof(_listenMode); + + if (_listenMode == AudioRingBuffer::OMNI_DIRECTIONAL_POINT) { + memcpy(&_listenRadius, currentBuffer, sizeof(_listenRadius)); + currentBuffer += sizeof(_listenRadius); + } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { + memcpy(&_listenSourceCount, currentBuffer, sizeof(_listenSourceCount)); + currentBuffer += sizeof(_listenSourceCount); + + if (_listenSources) { + delete[] _listenSources; + } + _listenSources = new int[_listenSourceCount]; + memcpy(_listenSources, currentBuffer, sizeof(int) * _listenSourceCount); + currentBuffer += sizeof(int) * _listenSourceCount; + + } + + return currentBuffer - sourceBuffer; +} + int PositionalAudioRingBuffer::parsePositionalData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer; diff --git a/audio-mixer/src/PositionalAudioRingBuffer.h b/audio-mixer/src/PositionalAudioRingBuffer.h index 41e775e74a..9fd6921617 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.h +++ b/audio-mixer/src/PositionalAudioRingBuffer.h @@ -16,9 +16,12 @@ class PositionalAudioRingBuffer : public AudioRingBuffer { public: PositionalAudioRingBuffer(); + ~PositionalAudioRingBuffer(); int parseData(unsigned char* sourceBuffer, int numBytes); int parsePositionalData(unsigned char* sourceBuffer, int numBytes); + int parseSourceData(unsigned char* sourceBuffer, int numBytes); + int parseListenModeData(unsigned char* sourceBuffer, int numBytes); bool shouldBeAddedToMix(int numJitterBufferSamples); @@ -36,6 +39,13 @@ protected: glm::vec3 _position; glm::quat _orientation; bool _willBeAddedToMix; + + int _sourceID; + int _listenMode; + float _listenRadius; + int _listenSourceCount; + int* _listenSources; + }; #endif /* defined(__hifi__PositionalAudioRingBuffer__) */ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9571b44839..d13d69ffb9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3447,9 +3447,19 @@ void* Application::networkReceive(void* args) { case PACKET_TYPE_AVATAR_FACE_VIDEO: processAvatarFaceVideoMessage(app->_incomingPacket, bytesReceived); break; - default: + default: { NodeList::getInstance()->processNodeData(&senderAddress, app->_incomingPacket, bytesReceived); + + // Check to see if we have our ownerID + uint16_t ownerID = NodeList::getInstance()->getOwnerID(); + + if (ownerID != app->_audio.getSourceID()) { + app->_audio.setSourceID(ownerID); + } + + break; + } } } } else if (!app->_enableNetworkThread) { diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 41090584f3..6bc2528bf0 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -120,6 +120,27 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o unsigned char* currentPacketPtr = dataPacket + populateTypeAndVersion(dataPacket, packetType); + // pack Source Data + memcpy(currentPacketPtr, &_sourceID, sizeof(_sourceID)); + currentPacketPtr += (sizeof(_sourceID)); + + // pack Listen Mode Data + memcpy(currentPacketPtr, &_listenMode, sizeof(_listenMode)); + currentPacketPtr += (sizeof(_listenMode)); + + if (_listenMode == AudioRingBuffer::OMNI_DIRECTIONAL_POINT) { + memcpy(currentPacketPtr, &_listenRadius, sizeof(_listenRadius)); + currentPacketPtr += (sizeof(_listenRadius)); + } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { + memcpy(currentPacketPtr, &_listenSourceCount, sizeof(_listenSourceCount)); + currentPacketPtr += (sizeof(_listenSourceCount)); + + if (_listenSources) { + memcpy(currentPacketPtr, &_listenSources, sizeof(int) * _listenSourceCount); + currentPacketPtr += (sizeof(int) * _listenSourceCount); + } + } + // memcpy the three float positions memcpy(currentPacketPtr, &headPosition, sizeof(headPosition)); currentPacketPtr += (sizeof(headPosition)); @@ -309,6 +330,49 @@ void Audio::reset() { _ringBuffer.reset(); } +void Audio::addListenSource(int sourceID) { + + // If we don't yet have a list of listen sources, make one + if (!_listenSources) { + _listenSources = new int[AudioRingBuffer::DEFAULT_LISTEN_LIST_SIZE]; + } + + // First check to see if the source is already in our list + for (int i = 0; i < _listenSourceCount; i++) { + if (_listenSources[i] == sourceID) { + return; // already in list + } + } + + // we know it's not in the list, check to see if we have room to add our source + if (_listenSourceCount + 1 < _listenSourcesArraySize) { + int* newList = new int[_listenSourcesArraySize + AudioRingBuffer::DEFAULT_LISTEN_LIST_SIZE]; + memmove(newList, _listenSources, _listenSourcesArraySize); + delete[] _listenSources; + _listenSources = newList; + _listenSourcesArraySize += AudioRingBuffer::DEFAULT_LISTEN_LIST_SIZE; + } + _listenSources[_listenSourceCount] = sourceID; + _listenSourceCount++; +} + +void Audio::removeListenSource(int sourceID) { + // If we don't yet have a list of listen sources, make one + if (_listenSources) { + // First check to see if the source is already in our list + for (int i = 0; i < _listenSourceCount; i++) { + if (_listenSources[i] == sourceID) { + + // found it, so, move the items forward in list + memmove(&_listenSources[i], &_listenSources[i+1], _listenSourceCount - i); + _listenSourceCount--; + return; + } + } + } +} + + Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _stream(NULL), _ringBuffer(true), @@ -338,7 +402,13 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _collisionSoundNoise(0.0f), _collisionSoundDuration(0.0f), _proceduralEffectSample(0), - _heartbeatMagnitude(0.0f) + _heartbeatMagnitude(0.0f), + _sourceID(UNKNOWN_NODE_ID), + _listenMode(AudioRingBuffer::NORMAL), + _listenRadius(0.0f), + _listenSourceCount(0), + _listenSourcesArraySize(0), + _listenSources(NULL) { outputPortAudioError(Pa_Initialize()); @@ -407,6 +477,10 @@ Audio::~Audio() { outputPortAudioError(Pa_Terminate()); } delete[] _echoSamplesLeft; + + if (_listenSources) { + delete[] _listenSources; + } } void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBytes) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 37db447381..ca665c66f0 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -54,6 +54,12 @@ public: // The results of the analysis are written to the log. bool eventuallyAnalyzePing(); + int getSourceID() const { return _sourceID; }; + void setSourceID(int sourceID) { _sourceID = sourceID; }; + void setListenMode(int mode) { _listenMode = mode; }; + void setListenRadius(float radius) { _listenRadius = radius; }; + void addListenSource(int sourceID); + void removeListenSource(int sourceID); private: PaStream* _stream; @@ -90,6 +96,13 @@ private: float _collisionSoundDuration; int _proceduralEffectSample; float _heartbeatMagnitude; + + int _sourceID; + int _listenMode; + float _listenRadius; + int _listenSourceCount; + int _listenSourcesArraySize; + int* _listenSources; // Audio callback in class context. inline void performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* outputRight); diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index dea4a13fec..be87558010 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -27,6 +27,14 @@ const short RING_BUFFER_LENGTH_SAMPLES = RING_BUFFER_LENGTH_FRAMES * BUFFER_LENG class AudioRingBuffer : public NodeData { public: + + static int const DEFAULT_LISTEN_LIST_SIZE = 100; + enum { + NORMAL, + OMNI_DIRECTIONAL_POINT, + SELECTED_SOURCES + }; + AudioRingBuffer(bool isStereo); ~AudioRingBuffer(); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 821a2d0247..292c4bbc0a 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -14,6 +14,12 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { switch (type) { + + case PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO: + case PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO: + return 1; + break; + case PACKET_TYPE_HEAD_DATA: return 2; break; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index c62abb85e9..9652ac14e7 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -35,8 +35,6 @@ const PACKET_TYPE PACKET_TYPE_ENVIRONMENT_DATA = 'e'; const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L'; const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C'; -// this is a test... - typedef char PACKET_VERSION; PACKET_VERSION versionForPacketType(PACKET_TYPE type); From 307cfcc7a295f1660c1f8b972b8e2da33d6e0998 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 13:58:15 -0700 Subject: [PATCH 27/50] CR feedback --- interface/src/ui/VoxelStatsDialog.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/ui/VoxelStatsDialog.h b/interface/src/ui/VoxelStatsDialog.h index 1d30ec8881..eab5b6a45a 100644 --- a/interface/src/ui/VoxelStatsDialog.h +++ b/interface/src/ui/VoxelStatsDialog.h @@ -17,7 +17,6 @@ class VoxelStatsDialog : public QDialog { Q_OBJECT public: - // Sets up the UI VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model); @@ -25,11 +24,9 @@ signals: void closed(); public slots: - void reject(); protected: - // State <- data model held by BandwidthMeter void paintEvent(QPaintEvent*); From d3c46cce8fd07fd1b511ed5306f4be22247ea14b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 14:01:47 -0700 Subject: [PATCH 28/50] CR feedback --- interface/src/ui/VoxelStatsDialog.cpp | 4 +++- libraries/voxels/src/VoxelSceneStats.cpp | 1 + libraries/voxels/src/VoxelSceneStats.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index 8ab7df3ddd..bfe93ec119 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -38,7 +38,9 @@ VoxelStatsDialog::VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model) : // Set foreground color to 62.5% brightness of the meter (otherwise will be hard to read on the bright background) QPalette palette = label->palette(); unsigned rgb = itemInfo.colorRGBA >> 8; - rgb = ((rgb & 0xfefefeu) >> 1) + ((rgb & 0xf8f8f8) >> 3); + const unsigned colorpart1 = 0xfefefeu; + const unsigned colorpart2 = 0xf8f8f8; + rgb = ((rgb & colorpart1) >> 1) + ((rgb & colorpart2) >> 3); palette.setColor(QPalette::WindowText, QColor::fromRgb(rgb)); label->setPalette(palette); diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index c38057ec89..256d374171 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -3,6 +3,7 @@ // hifi // // Created by Brad Hefta-Gaub on 7/18/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // // diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index bf7b38f988..c738d14d0f 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -3,6 +3,7 @@ // hifi // // Created by Brad Hefta-Gaub on 7/18/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // // From 70516c8cb4f2ebfe0d8d1c71ff2fd46c1ac950b8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 14:08:48 -0700 Subject: [PATCH 29/50] CR feedback --- libraries/voxels/src/VoxelSceneStats.cpp | 47 ++++++++++++------------ libraries/voxels/src/VoxelSceneStats.h | 7 ++-- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 256d374171..4f725193da 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -14,36 +14,37 @@ #include "VoxelSceneStats.h" -VoxelSceneStats::VoxelSceneStats() : _elapsedAverage(100), _bitsPerVoxelAverage(100) { +const int samples = 100; +VoxelSceneStats::VoxelSceneStats() : + _elapsedAverage(samples), + _bitsPerVoxelAverage(samples) +{ reset(); _readyToSend = false; - _started = false; + _isStarted = false; } -VoxelSceneStats::~VoxelSceneStats() { -} - -void VoxelSceneStats::sceneStarted(bool fullScene, bool moving, VoxelNode* root) { +void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* root) { reset(); // resets packet and voxel stats - _started = true; + _isStarted = true; _start = usecTimestampNow(); _totalVoxels = root->getSubTreeNodeCount(); _totalInternal = root->getSubTreeInternalNodeCount(); _totalLeaves = root->getSubTreeLeafNodeCount(); - _fullSceneDraw = fullScene; - _moving = moving; + _isFullScene = isFullScene; + _isMoving = isMoving; } void VoxelSceneStats::sceneCompleted() { - if (_started) { + if (_isStarted) { _end = usecTimestampNow(); _elapsed = _end - _start; _elapsedAverage.updateAverage((float)_elapsed); _statsMessageLength = packIntoMessage(_statsMessage, sizeof(_statsMessage)); _readyToSend = true; - _started = false; + _isStarted = false; } } @@ -220,10 +221,10 @@ int VoxelSceneStats::packIntoMessage(unsigned char* destinationBuffer, int avail destinationBuffer += sizeof(_elapsed); memcpy(destinationBuffer, &_totalEncodeTime, sizeof(_totalEncodeTime)); destinationBuffer += sizeof(_totalEncodeTime); - memcpy(destinationBuffer, &_fullSceneDraw, sizeof(_fullSceneDraw)); - destinationBuffer += sizeof(_fullSceneDraw); - memcpy(destinationBuffer, &_moving, sizeof(_moving)); - destinationBuffer += sizeof(_moving); + memcpy(destinationBuffer, &_isFullScene, sizeof(_isFullScene)); + destinationBuffer += sizeof(_isFullScene); + memcpy(destinationBuffer, &_isMoving, sizeof(_isMoving)); + destinationBuffer += sizeof(_isMoving); memcpy(destinationBuffer, &_packets, sizeof(_packets)); destinationBuffer += sizeof(_packets); memcpy(destinationBuffer, &_bytes, sizeof(_bytes)); @@ -292,10 +293,10 @@ int VoxelSceneStats::unpackFromMessage(unsigned char* sourceBuffer, int availabl sourceBuffer += sizeof(_elapsed); memcpy(&_totalEncodeTime, sourceBuffer, sizeof(_totalEncodeTime)); sourceBuffer += sizeof(_totalEncodeTime); - memcpy(&_fullSceneDraw, sourceBuffer, sizeof(_fullSceneDraw)); - sourceBuffer += sizeof(_fullSceneDraw); - memcpy(&_moving, sourceBuffer, sizeof(_moving)); - sourceBuffer += sizeof(_moving); + memcpy(&_isFullScene, sourceBuffer, sizeof(_isFullScene)); + sourceBuffer += sizeof(_isFullScene); + memcpy(&_isMoving, sourceBuffer, sizeof(_isMoving)); + sourceBuffer += sizeof(_isMoving); memcpy(&_packets, sourceBuffer, sizeof(_packets)); sourceBuffer += sizeof(_packets); memcpy(&_bytes, sourceBuffer, sizeof(_bytes)); @@ -383,8 +384,8 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" elapsed : %llu \n", _elapsed); qDebug(" encoding : %llu \n", _totalEncodeTime); qDebug("\n"); - qDebug(" full scene: %s\n", debug::valueOf(_fullSceneDraw)); - qDebug(" moving: %s\n", debug::valueOf(_moving)); + qDebug(" full scene: %s\n", debug::valueOf(_isFullScene)); + qDebug(" moving: %s\n", debug::valueOf(_isMoving)); qDebug("\n"); qDebug(" packets: %d\n", _packets); qDebug(" bytes : %ld\n", _bytes); @@ -540,8 +541,8 @@ char* VoxelSceneStats::getItemValue(int item) { break; } case ITEM_MODE: { - sprintf(_itemValueBuffer, "%s - %s", (_fullSceneDraw ? "Full Scene" : "Partial Scene"), - (_moving ? "Moving" : "Stationary")); + sprintf(_itemValueBuffer, "%s - %s", (_isFullScene ? "Full Scene" : "Partial Scene"), + (_isMoving ? "Moving" : "Stationary")); break; } default: diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index c738d14d0f..2bf71d7440 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -18,7 +18,6 @@ class VoxelNode; class VoxelSceneStats { public: VoxelSceneStats(); - ~VoxelSceneStats(); void reset(); void sceneStarted(bool fullScene, bool moving, VoxelNode* root); void sceneCompleted(); @@ -85,7 +84,7 @@ private: int _statsMessageLength; // scene timing data in usecs - bool _started; + bool _isStarted; uint64_t _start; uint64_t _end; uint64_t _elapsed; @@ -159,8 +158,8 @@ private: unsigned int _passes; // features related items - bool _moving; - bool _fullSceneDraw; + bool _isMoving; + bool _isFullScene; static ItemInfo _ITEMS[]; From 8186145d3510ae6dd63c7cd3357507cc9cab3bf6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 14:09:29 -0700 Subject: [PATCH 30/50] CR feedback --- libraries/voxels/src/VoxelSceneStats.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 4f725193da..2e12684dfb 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -56,7 +56,6 @@ void VoxelSceneStats::encodeStopped() { _totalEncodeTime += (usecTimestampNow() - _encodeStart); } - void VoxelSceneStats::reset() { _totalEncodeTime = 0; _encodeStart = 0; From 60750d1d804351dd5ebde3a47da647f184a253e2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 14:13:10 -0700 Subject: [PATCH 31/50] CR feedback --- libraries/voxels/src/VoxelSceneStats.cpp | 35 +++++++++++++----------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 2e12684dfb..0f22352eb9 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -424,24 +424,27 @@ void VoxelSceneStats::printDebugDetails() { qDebug(" trees removed : %lu\n", _treesRemoved ); } +const unsigned greenish = 0x40ff40d0; +const unsigned yellowish = 0xffef40c0; +const unsigned greyish = 0xd0d0d0a0; VoxelSceneStats::ItemInfo VoxelSceneStats::_ITEMS[] = { - { "Elapsed" , 0x40ff40d0 }, - { "Encode" , 0xffef40c0 }, - { "Network" , 0xd0d0d0a0 }, - { "Voxels on Server" , 0x40ff40d0 }, - { "Voxels Sent" , 0xffef40c0 }, - { "Colors Sent" , 0xd0d0d0a0 }, - { "Bitmasks Sent" , 0x40ff40d0 }, - { "Traversed" , 0xffef40c0 }, - { "Skipped - Total" , 0xd0d0d0a0 }, - { "Skipped - Distance" , 0x40ff40d0 }, - { "Skipped - Out of View", 0xffef40c0 }, - { "Skipped - Was in View", 0xd0d0d0a0 }, - { "Skipped - No Change" , 0x40ff40d0 }, - { "Skipped - Occluded" , 0xffef40c0 }, - { "Didn't fit in packet" , 0xd0d0d0a0 }, - { "Mode" , 0x40ff40d0 }, + { "Elapsed" , greenish }, + { "Encode" , yellowish }, + { "Network" , greyish }, + { "Voxels on Server" , greenish }, + { "Voxels Sent" , yellowish }, + { "Colors Sent" , greyish }, + { "Bitmasks Sent" , greenish }, + { "Traversed" , yellowish }, + { "Skipped - Total" , greyish }, + { "Skipped - Distance" , greenish }, + { "Skipped - Out of View", yellowish }, + { "Skipped - Was in View", greyish }, + { "Skipped - No Change" , greenish }, + { "Skipped - Occluded" , yellowish }, + { "Didn't fit in packet" , greyish }, + { "Mode" , greenish }, }; char* VoxelSceneStats::getItemValue(int item) { From 86aeaf175c61cdc747437bed15bd366e85e9711c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 14:15:10 -0700 Subject: [PATCH 32/50] CR feedback --- voxel-server/src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index e995012bef..c02211f182 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -249,8 +249,8 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, nodeData->nodeBag.insert(serverTree.rootNode); // start tracking our stats - bool fullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging(); - nodeData->stats.sceneStarted(fullScene, viewFrustumChanged, ::serverTree.rootNode); + bool isFullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging(); + nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, ::serverTree.rootNode); } // If we have something in our nodeBag, then turn them into packets and send them out... @@ -284,14 +284,14 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, int boundaryLevelAdjust = viewFrustumChanged && nodeData->getWantLowResMoving() ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST; - bool fullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && + bool isFullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging(); EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, wantOcclusionCulling, coverageMap, boundaryLevelAdjust, nodeData->getLastTimeBagEmpty(), - fullScene, &nodeData->stats); + isFullScene, &nodeData->stats); nodeData->stats.encodeStarted(); bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, From f4749aa916aad4b7921174e61bc347b81eebb08c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 14:17:18 -0700 Subject: [PATCH 33/50] CR feedback --- libraries/voxels/src/VoxelSceneStats.cpp | 4 ++-- libraries/voxels/src/VoxelSceneStats.h | 6 +++--- voxel-server/src/main.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index 0f22352eb9..b226886a25 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -20,7 +20,7 @@ VoxelSceneStats::VoxelSceneStats() : _bitsPerVoxelAverage(samples) { reset(); - _readyToSend = false; + _isReadyToSend = false; _isStarted = false; } @@ -43,7 +43,7 @@ void VoxelSceneStats::sceneCompleted() { _elapsedAverage.updateAverage((float)_elapsed); _statsMessageLength = packIntoMessage(_statsMessage, sizeof(_statsMessage)); - _readyToSend = true; + _isReadyToSend = true; _isStarted = false; } } diff --git a/libraries/voxels/src/VoxelSceneStats.h b/libraries/voxels/src/VoxelSceneStats.h index 2bf71d7440..ded2061a6e 100644 --- a/libraries/voxels/src/VoxelSceneStats.h +++ b/libraries/voxels/src/VoxelSceneStats.h @@ -44,8 +44,8 @@ public: int packIntoMessage(unsigned char* destinationBuffer, int availableBytes); int unpackFromMessage(unsigned char* sourceBuffer, int availableBytes); - bool readyToSend() const { return _readyToSend; } - void markAsSent() { _readyToSend = false; } + bool isReadyToSend() const { return _isReadyToSend; } + void markAsSent() { _isReadyToSend = false; } unsigned char* getStatsMessage() { return &_statsMessage[0]; } int getStatsMessageLength() const { return _statsMessageLength; } @@ -79,7 +79,7 @@ public: char* getItemValue(int item); private: - bool _readyToSend; + bool _isReadyToSend; unsigned char _statsMessage[MAX_PACKET_SIZE]; int _statsMessageLength; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index c02211f182..c009eec2a5 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -117,7 +117,7 @@ void handlePacketSend(NodeList* nodeList, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent) { // If we've got a stats message ready to send, then see if we can piggyback them together - if (nodeData->stats.readyToSend()) { + if (nodeData->stats.isReadyToSend()) { // Send the stats message to the client unsigned char* statsMessage = nodeData->stats.getStatsMessage(); int statsMessageLength = nodeData->stats.getStatsMessageLength(); From d5e62b0f5af4f589677e1e2e3d5843dc1c1bac22 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 14:18:16 -0700 Subject: [PATCH 34/50] CR feedback --- libraries/voxels/src/VoxelTree.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 362df3b3f7..b26a70f34b 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1300,8 +1300,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp } // wants occlusion culling & isLeaf() - bool shouldRender = !params.viewFrustum ? true : - childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust); + bool shouldRender = !params.viewFrustum + ? true + : childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust); // track some stats if (params.stats) { From 0f1ac2b2267b86e033220f26c61865813b440fa2 Mon Sep 17 00:00:00 2001 From: Mark Peng Date: Mon, 22 Jul 2013 16:46:06 -0700 Subject: [PATCH 35/50] Fix eyePosition so that lookatVectors point directly to eyes, even when looking at someone from above. --- interface/src/Application.cpp | 9 ++++++--- interface/src/avatar/Head.cpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9571b44839..0aee4a726c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1953,10 +1953,13 @@ bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& m void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera) { const float DISTANCE_FROM_HEAD_SPHERE = 0.1f; + const float INDICATOR_RADIUS = 0.1f; const float YELLOW[] = { 1.0f, 1.0f, 0.0f }; + const int NUM_SEGMENTS = 30; glm::vec3 haloOrigin(pointOfInterest.x, pointOfInterest.y + DISTANCE_FROM_HEAD_SPHERE, pointOfInterest.z); glColor3f(YELLOW[0], YELLOW[1], YELLOW[2]); - renderCircle(haloOrigin, 0.1f, glm::vec3(0.0f, 1.0f, 0.0f), 30); + glm::vec3 normalToFloor(0.0f, 1.0f, 0.0f); + renderCircle(haloOrigin, INDICATOR_RADIUS, normalToFloor, NUM_SEGMENTS); } void Application::update(float deltaTime) { @@ -2003,7 +2006,7 @@ void Application::update(float deltaTime) { glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 up = orientation * IDENTITY_UP; glm::vec3 towardVoxel = getMouseVoxelWorldCoordinates(_mouseVoxelDragging) - - _myAvatar.getCameraPosition(); // is this an error? getCameraPosition dne + - _myAvatar.getCameraPosition(); towardVoxel = front * glm::length(towardVoxel); glm::vec3 lateralToVoxel = glm::cross(up, glm::normalize(towardVoxel)) * glm::length(towardVoxel); _voxelThrust = glm::vec3(0, 0, 0); @@ -2276,7 +2279,7 @@ void Application::updateAvatar(float deltaTime) { // actually need to calculate the view frustum planes to send these details // to the server. loadViewFrustum(_myCamera, _viewFrustum); - _myAvatar.setCameraPosition(_viewFrustum.getPosition()); // setCameraPosition() dne + _myAvatar.setCameraPosition(_viewFrustum.getPosition()); _myAvatar.setCameraOrientation(_viewFrustum.getOrientation()); _myAvatar.setCameraFov(_viewFrustum.getFieldOfView()); _myAvatar.setCameraAspectRatio(_viewFrustum.getAspectRatio()); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b8393e26ab..76cf13a44d 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -272,7 +272,7 @@ void Head::calculateGeometry() { + up * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET + front * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_FRONT_OFFSET; - _eyeLevelPosition = _position + up * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET; + _eyeLevelPosition = _rightEyePosition - right * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_RIGHT_OFFSET; //calculate the eyebrow positions _leftEyeBrowPosition = _leftEyePosition; From 4e641eed2fd804a53111ef8216c42fc36dee8ab5 Mon Sep 17 00:00:00 2001 From: Mark Peng Date: Mon, 22 Jul 2013 17:11:11 -0700 Subject: [PATCH 36/50] LookatIndicator now scales with the avatar's scale. --- interface/src/Application.cpp | 6 ++++-- interface/src/Application.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0aee4a726c..c0fe2b360b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -200,6 +200,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _mouseVoxelScale(1.0f / 1024.0f), _justEditedVoxel(false), _isLookingAtOtherAvatar(false), + _lookatIndicatorScale(1.0f), _paintOn(false), _dominantColor(0), _perfStatsOn(false), @@ -1942,6 +1943,7 @@ bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& m glm::vec3 headPosition = avatar->getHead().getPosition(); if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) { eyePosition = avatar->getHead().getEyeLevelPosition(); + _lookatIndicatorScale = avatar->getScale(); _lookatOtherPosition = headPosition; return true; } @@ -1952,8 +1954,8 @@ bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& m void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera) { - const float DISTANCE_FROM_HEAD_SPHERE = 0.1f; - const float INDICATOR_RADIUS = 0.1f; + const float DISTANCE_FROM_HEAD_SPHERE = 0.1f * _lookatIndicatorScale; + const float INDICATOR_RADIUS = 0.1f * _lookatIndicatorScale; const float YELLOW[] = { 1.0f, 1.0f, 0.0f }; const int NUM_SEGMENTS = 30; glm::vec3 haloOrigin(pointOfInterest.x, pointOfInterest.y + DISTANCE_FROM_HEAD_SPHERE, pointOfInterest.z); diff --git a/interface/src/Application.h b/interface/src/Application.h index d29328c0b5..85c8334b3a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -373,6 +373,7 @@ private: bool _isLookingAtOtherAvatar; glm::vec3 _lookatOtherPosition; + float _lookatIndicatorScale; bool _paintOn; // Whether to paint voxels as you fly around unsigned char _dominantColor; // The dominant color of the voxel we're painting From c969570e8c8fb64c2f86ed6e4c3bfe105c64b979 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 23:05:42 -0700 Subject: [PATCH 37/50] working on selected audio --- audio-mixer/src/PositionalAudioRingBuffer.cpp | 32 +- audio-mixer/src/PositionalAudioRingBuffer.h | 4 + audio-mixer/src/main.cpp | 281 +++++++++--------- interface/src/Application.cpp | 36 +++ interface/src/Application.h | 4 + interface/src/Audio.cpp | 16 +- interface/src/Audio.h | 1 + interface/src/avatar/Avatar.h | 4 + 8 files changed, 233 insertions(+), 145 deletions(-) diff --git a/audio-mixer/src/PositionalAudioRingBuffer.cpp b/audio-mixer/src/PositionalAudioRingBuffer.cpp index 936b71fb79..26961c76e8 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.cpp +++ b/audio-mixer/src/PositionalAudioRingBuffer.cpp @@ -32,6 +32,32 @@ PositionalAudioRingBuffer::~PositionalAudioRingBuffer() { } } +bool PositionalAudioRingBuffer::isListeningToSource(PositionalAudioRingBuffer* other) { + switch (_listenMode) { + default: + case AudioRingBuffer::NORMAL: + return true; + break; + + case AudioRingBuffer::OMNI_DIRECTIONAL_POINT: { + float distance = glm::distance(_position, other->_position); + return distance <= _listenRadius; + break; + } + case AudioRingBuffer::SELECTED_SOURCES: + if (_listenSources) { + for (int i = 0; i < _listenSourceCount; i++) { + if (other->_sourceID == _listenSources[i]) { + return true; + } + } + } + return false; + break; + } +} + + int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer); currentBuffer += parseSourceData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); @@ -56,21 +82,19 @@ int PositionalAudioRingBuffer::parseListenModeData(unsigned char* sourceBuffer, memcpy(&_listenMode, currentBuffer, sizeof(_listenMode)); currentBuffer += sizeof(_listenMode); - + if (_listenMode == AudioRingBuffer::OMNI_DIRECTIONAL_POINT) { memcpy(&_listenRadius, currentBuffer, sizeof(_listenRadius)); currentBuffer += sizeof(_listenRadius); } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { memcpy(&_listenSourceCount, currentBuffer, sizeof(_listenSourceCount)); currentBuffer += sizeof(_listenSourceCount); - if (_listenSources) { delete[] _listenSources; } _listenSources = new int[_listenSourceCount]; memcpy(_listenSources, currentBuffer, sizeof(int) * _listenSourceCount); currentBuffer += sizeof(int) * _listenSourceCount; - } return currentBuffer - sourceBuffer; @@ -81,7 +105,7 @@ int PositionalAudioRingBuffer::parsePositionalData(unsigned char* sourceBuffer, memcpy(&_position, currentBuffer, sizeof(_position)); currentBuffer += sizeof(_position); - + memcpy(&_orientation, currentBuffer, sizeof(_orientation)); currentBuffer += sizeof(_orientation); diff --git a/audio-mixer/src/PositionalAudioRingBuffer.h b/audio-mixer/src/PositionalAudioRingBuffer.h index 9fd6921617..eb6f0414e7 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.h +++ b/audio-mixer/src/PositionalAudioRingBuffer.h @@ -30,6 +30,10 @@ public: const glm::vec3& getPosition() const { return _position; } const glm::quat& getOrientation() const { return _orientation; } + + bool isListeningToSource(PositionalAudioRingBuffer* other); + int getSourceID() const { return _sourceID; } + int getListeningMode() const { return _listenMode; } protected: // disallow copying of PositionalAudioRingBuffer objects diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index 239eb7a32d..2f17113ba4 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -159,168 +159,174 @@ int main(int argc, const char* argv[]) { // zero out the client mix for this node memset(clientSamples, 0, sizeof(clientSamples)); + // loop through all other nodes that have sufficient audio to mix for (NodeList::iterator otherNode = nodeList->begin(); otherNode != nodeList->end(); otherNode++) { + if (((PositionalAudioRingBuffer*) otherNode->getLinkedData())->willBeAddedToMix() && (otherNode != node || (otherNode == node && nodeRingBuffer->shouldLoopbackForNode()))) { PositionalAudioRingBuffer* otherNodeBuffer = (PositionalAudioRingBuffer*) otherNode->getLinkedData(); + + // based on our listen mode we will do this mixing... + if (nodeRingBuffer->isListeningToSource(otherNodeBuffer)) { + float bearingRelativeAngleToSource = 0.0f; + float attenuationCoefficient = 1.0f; + int numSamplesDelay = 0; + float weakChannelAmplitudeRatio = 1.0f; - float bearingRelativeAngleToSource = 0.0f; - float attenuationCoefficient = 1.0f; - int numSamplesDelay = 0; - float weakChannelAmplitudeRatio = 1.0f; + stk::TwoPole* otherNodeTwoPole = NULL; - stk::TwoPole* otherNodeTwoPole = NULL; - - if (otherNode != node) { + // only do axis/distance attenuation when in normal mode + if (otherNode != node && nodeRingBuffer->getListeningMode() == AudioRingBuffer::NORMAL) { - glm::vec3 listenerPosition = nodeRingBuffer->getPosition(); - glm::vec3 relativePosition = otherNodeBuffer->getPosition() - nodeRingBuffer->getPosition(); - glm::quat inverseOrientation = glm::inverse(nodeRingBuffer->getOrientation()); + glm::vec3 listenerPosition = nodeRingBuffer->getPosition(); + glm::vec3 relativePosition = otherNodeBuffer->getPosition() - nodeRingBuffer->getPosition(); + glm::quat inverseOrientation = glm::inverse(nodeRingBuffer->getOrientation()); - float distanceSquareToSource = glm::dot(relativePosition, relativePosition); - float radius = 0.0f; + float distanceSquareToSource = glm::dot(relativePosition, relativePosition); + float radius = 0.0f; - if (otherNode->getType() == NODE_TYPE_AUDIO_INJECTOR) { - InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) otherNodeBuffer; - radius = injectedBuffer->getRadius(); - attenuationCoefficient *= injectedBuffer->getAttenuationRatio(); - } + if (otherNode->getType() == NODE_TYPE_AUDIO_INJECTOR) { + InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) otherNodeBuffer; + radius = injectedBuffer->getRadius(); + attenuationCoefficient *= injectedBuffer->getAttenuationRatio(); + } - if (radius == 0 || (distanceSquareToSource > radius * radius)) { - // this is either not a spherical source, or the listener is outside the sphere + if (radius == 0 || (distanceSquareToSource > radius * radius)) { + // this is either not a spherical source, or the listener is outside the sphere - if (radius > 0) { - // this is a spherical source - the distance used for the coefficient - // needs to be the closest point on the boundary to the source + if (radius > 0) { + // this is a spherical source - the distance used for the coefficient + // needs to be the closest point on the boundary to the source - // ovveride the distance to the node with the distance to the point on the - // boundary of the sphere - distanceSquareToSource -= (radius * radius); + // ovveride the distance to the node with the distance to the point on the + // boundary of the sphere + distanceSquareToSource -= (radius * radius); - } else { - // calculate the angle delivery for off-axis attenuation - glm::vec3 rotatedListenerPosition = glm::inverse(otherNodeBuffer->getOrientation()) - * relativePosition; + } else { + // calculate the angle delivery for off-axis attenuation + glm::vec3 rotatedListenerPosition = glm::inverse(otherNodeBuffer->getOrientation()) + * relativePosition; - float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedListenerPosition)); + float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedListenerPosition)); - const float MAX_OFF_AXIS_ATTENUATION = 0.2f; - const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; + const float MAX_OFF_AXIS_ATTENUATION = 0.2f; + const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / 90.0f)); + float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / 90.0f)); - // multiply the current attenuation coefficient by the calculated off axis coefficient - attenuationCoefficient *= offAxisCoefficient; + // multiply the current attenuation coefficient by the calculated off axis coefficient + attenuationCoefficient *= offAxisCoefficient; + } + + glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; + + const float DISTANCE_SCALE = 2.5f; + const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f; + const float DISTANCE_LOG_BASE = 2.5f; + const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE); + + // calculate the distance coefficient using the distance to this node + float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, + DISTANCE_SCALE_LOG + + (0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); + distanceCoefficient = std::min(1.0f, distanceCoefficient); + + // multiply the current attenuation coefficient by the distance coefficient + attenuationCoefficient *= distanceCoefficient; + + // project the rotated source position vector onto the XZ plane + rotatedSourcePosition.y = 0.0f; + + // produce an oriented angle about the y-axis + bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedSourcePosition), + glm::vec3(0.0f, 1.0f, 0.0f)); + + const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; + + // figure out the number of samples of delay and the ratio of the amplitude + // in the weak channel for audio spatialization + float sinRatio = fabsf(sinf(glm::radians(bearingRelativeAngleToSource))); + numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); + + // grab the TwoPole object for this source, add it if it doesn't exist + TwoPoleNodeMap& nodeTwoPoles = nodeRingBuffer->getTwoPoles(); + TwoPoleNodeMap::iterator twoPoleIterator = nodeTwoPoles.find(otherNode->getNodeID()); + + if (twoPoleIterator == nodeTwoPoles.end()) { + // setup the freeVerb effect for this source for this client + otherNodeTwoPole = nodeTwoPoles[otherNode->getNodeID()] = new stk::TwoPole; + } else { + otherNodeTwoPole = twoPoleIterator->second; + } + + // calculate the reasonance for this TwoPole based on angle to source + float TWO_POLE_CUT_OFF_FREQUENCY = 800.0f; + float TWO_POLE_MAX_FILTER_STRENGTH = 0.4f; + + otherNodeTwoPole->setResonance(TWO_POLE_CUT_OFF_FREQUENCY, + TWO_POLE_MAX_FILTER_STRENGTH + * fabsf(bearingRelativeAngleToSource) / 180.0f, + true); } + } + + int16_t* sourceBuffer = otherNodeBuffer->getNextOutput(); + + int16_t* goodChannel = (bearingRelativeAngleToSource > 0.0f) + ? clientSamples + : clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + int16_t* delayedChannel = (bearingRelativeAngleToSource > 0.0f) + ? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL + : clientSamples; + + int16_t* delaySamplePointer = otherNodeBuffer->getNextOutput() == otherNodeBuffer->getBuffer() + ? otherNodeBuffer->getBuffer() + RING_BUFFER_LENGTH_SAMPLES - numSamplesDelay + : otherNodeBuffer->getNextOutput() - numSamplesDelay; + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { + // load up the stkFrameBuffer with this source's samples + stkFrameBuffer[s] = (stk::StkFloat) sourceBuffer[s]; + } + + // perform the TwoPole effect on the stkFrameBuffer + if (otherNodeTwoPole) { + otherNodeTwoPole->tick(stkFrameBuffer); + } + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { + if (s < numSamplesDelay) { + // pull the earlier sample for the delayed channel + int earlierSample = delaySamplePointer[s] * attenuationCoefficient * weakChannelAmplitudeRatio; - glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - - const float DISTANCE_SCALE = 2.5f; - const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f; - const float DISTANCE_LOG_BASE = 2.5f; - const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE); - - // calculate the distance coefficient using the distance to this node - float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, - DISTANCE_SCALE_LOG + - (0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); - distanceCoefficient = std::min(1.0f, distanceCoefficient); - - // multiply the current attenuation coefficient by the distance coefficient - attenuationCoefficient *= distanceCoefficient; - - // project the rotated source position vector onto the XZ plane - rotatedSourcePosition.y = 0.0f; - - // produce an oriented angle about the y-axis - bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedSourcePosition), - glm::vec3(0.0f, 1.0f, 0.0f)); - - const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; - - // figure out the number of samples of delay and the ratio of the amplitude - // in the weak channel for audio spatialization - float sinRatio = fabsf(sinf(glm::radians(bearingRelativeAngleToSource))); - numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; - weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); - - // grab the TwoPole object for this source, add it if it doesn't exist - TwoPoleNodeMap& nodeTwoPoles = nodeRingBuffer->getTwoPoles(); - TwoPoleNodeMap::iterator twoPoleIterator = nodeTwoPoles.find(otherNode->getNodeID()); - - if (twoPoleIterator == nodeTwoPoles.end()) { - // setup the freeVerb effect for this source for this client - otherNodeTwoPole = nodeTwoPoles[otherNode->getNodeID()] = new stk::TwoPole; - } else { - otherNodeTwoPole = twoPoleIterator->second; + delayedChannel[s] = glm::clamp(delayedChannel[s] + earlierSample, + MIN_SAMPLE_VALUE, + MAX_SAMPLE_VALUE); } - - // calculate the reasonance for this TwoPole based on angle to source - float TWO_POLE_CUT_OFF_FREQUENCY = 800.0f; - float TWO_POLE_MAX_FILTER_STRENGTH = 0.4f; - - otherNodeTwoPole->setResonance(TWO_POLE_CUT_OFF_FREQUENCY, - TWO_POLE_MAX_FILTER_STRENGTH - * fabsf(bearingRelativeAngleToSource) / 180.0f, - true); - } - } - - int16_t* sourceBuffer = otherNodeBuffer->getNextOutput(); - - int16_t* goodChannel = (bearingRelativeAngleToSource > 0.0f) - ? clientSamples - : clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; - int16_t* delayedChannel = (bearingRelativeAngleToSource > 0.0f) - ? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL - : clientSamples; - - int16_t* delaySamplePointer = otherNodeBuffer->getNextOutput() == otherNodeBuffer->getBuffer() - ? otherNodeBuffer->getBuffer() + RING_BUFFER_LENGTH_SAMPLES - numSamplesDelay - : otherNodeBuffer->getNextOutput() - numSamplesDelay; - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - // load up the stkFrameBuffer with this source's samples - stkFrameBuffer[s] = (stk::StkFloat) sourceBuffer[s]; - } - - // perform the TwoPole effect on the stkFrameBuffer - if (otherNodeTwoPole) { - otherNodeTwoPole->tick(stkFrameBuffer); - } - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - if (s < numSamplesDelay) { - // pull the earlier sample for the delayed channel - int earlierSample = delaySamplePointer[s] * attenuationCoefficient * weakChannelAmplitudeRatio; - - delayedChannel[s] = glm::clamp(delayedChannel[s] + earlierSample, - MIN_SAMPLE_VALUE, - MAX_SAMPLE_VALUE); - } - int16_t currentSample = stkFrameBuffer[s] * attenuationCoefficient; + int16_t currentSample = stkFrameBuffer[s] * attenuationCoefficient; - goodChannel[s] = glm::clamp(goodChannel[s] + currentSample, - MIN_SAMPLE_VALUE, - MAX_SAMPLE_VALUE); + goodChannel[s] = glm::clamp(goodChannel[s] + currentSample, + MIN_SAMPLE_VALUE, + MAX_SAMPLE_VALUE); - if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - int sumSample = delayedChannel[s + numSamplesDelay] - + (currentSample * weakChannelAmplitudeRatio); - delayedChannel[s + numSamplesDelay] = glm::clamp(sumSample, - MIN_SAMPLE_VALUE, - MAX_SAMPLE_VALUE); - } + if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { + int sumSample = delayedChannel[s + numSamplesDelay] + + (currentSample * weakChannelAmplitudeRatio); + delayedChannel[s + numSamplesDelay] = glm::clamp(sumSample, + MIN_SAMPLE_VALUE, + MAX_SAMPLE_VALUE); + } - if (s >= BUFFER_LENGTH_SAMPLES_PER_CHANNEL - PHASE_DELAY_AT_90) { - // this could be a delayed sample on the next pass - // so store the affected back in the ARB - otherNodeBuffer->getNextOutput()[s] = (int16_t) stkFrameBuffer[s]; + if (s >= BUFFER_LENGTH_SAMPLES_PER_CHANNEL - PHASE_DELAY_AT_90) { + // this could be a delayed sample on the next pass + // so store the affected back in the ARB + otherNodeBuffer->getNextOutput()[s] = (int16_t) stkFrameBuffer[s]; + } } } } @@ -340,7 +346,6 @@ int main(int argc, const char* argv[]) { if (nodeBuffer->getNextOutput() >= nodeBuffer->getBuffer() + RING_BUFFER_LENGTH_SAMPLES) { nodeBuffer->setNextOutput(nodeBuffer->getBuffer()); } - nodeBuffer->setWillBeAddedToMix(false); } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d13d69ffb9..c1aa032542 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1835,6 +1835,11 @@ void Application::initMenu() { (_simulateLeapHand = debugMenu->addAction("Simulate Leap Hand"))->setCheckable(true); (_testRaveGlove = debugMenu->addAction("Test RaveGlove"))->setCheckable(true); + QMenu* audioDebugMenu = debugMenu->addMenu("Audio Debugging Tools"); + audioDebugMenu->addAction("Listen Mode Normal", this, SLOT(setListenModeNormal()), Qt::CTRL | Qt::Key_1); + audioDebugMenu->addAction("Listen Mode Point/Radius", this, SLOT(setListenModePoint()), Qt::CTRL | Qt::Key_2); + audioDebugMenu->addAction("Listen Mode Single Source", this, SLOT(setListenModeSingleSource()), Qt::CTRL | Qt::Key_3); + QMenu* settingsMenu = menuBar->addMenu("Settings"); (_settingsAutosave = settingsMenu->addAction("Autosave"))->setCheckable(true); _settingsAutosave->setChecked(true); @@ -1846,6 +1851,37 @@ void Application::initMenu() { _networkAccessManager = new QNetworkAccessManager(this); } +void Application::setListenModeNormal() { + _audio.setListenMode(AudioRingBuffer::NORMAL); +} + +void Application::setListenModePoint() { + _audio.setListenMode(AudioRingBuffer::OMNI_DIRECTIONAL_POINT); + _audio.setListenRadius(1.0); +} + +void Application::setListenModeSingleSource() { + _audio.setListenMode(AudioRingBuffer::SELECTED_SOURCES); + _audio.clearListenSources(); + + NodeList* nodeList = NodeList::getInstance(); + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { + Avatar* avatar = (Avatar *) node->getLinkedData(); + glm::vec3 headPosition = avatar->getHead().getPosition(); + glm::vec3 mouseRayOrigin = _myAvatar.getMouseRayOrigin(); + glm::vec3 mouseRayDirection = _myAvatar.getMouseRayDirection(); + const float HEAD_SPHERE_RADIUS = 0.07; + + if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) { + int sourceID = avatar->getOwningNode()->getNodeID(); + _audio.addListenSource(sourceID); + } + } + } +} + + void Application::updateFrustumRenderModeAction() { switch (_frustumDrawingMode) { default: diff --git a/interface/src/Application.h b/interface/src/Application.h index d29328c0b5..d462e88b98 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -170,6 +170,10 @@ private slots: void copyVoxels(); void pasteVoxels(); void runTests(); + void setListenModeNormal(); + void setListenModePoint(); + void setListenModeSingleSource(); + void renderCoverageMap(); void renderCoverageMapsRecursively(CoverageMap* map); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 6bc2528bf0..9119d3984f 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -112,7 +112,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o // we need the amount of bytes in the buffer + 1 for type // + 12 for 3 floats for position + float for bearing + 1 attenuation byte - unsigned char dataPacket[BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes]; + unsigned char dataPacket[MAX_PACKET_SIZE]; PACKET_TYPE packetType = (Application::getInstance()->shouldEchoAudio()) ? PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO @@ -123,21 +123,25 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o // pack Source Data memcpy(currentPacketPtr, &_sourceID, sizeof(_sourceID)); currentPacketPtr += (sizeof(_sourceID)); + leadingBytes += (sizeof(_sourceID)); // pack Listen Mode Data memcpy(currentPacketPtr, &_listenMode, sizeof(_listenMode)); currentPacketPtr += (sizeof(_listenMode)); + leadingBytes += (sizeof(_listenMode)); if (_listenMode == AudioRingBuffer::OMNI_DIRECTIONAL_POINT) { memcpy(currentPacketPtr, &_listenRadius, sizeof(_listenRadius)); currentPacketPtr += (sizeof(_listenRadius)); + leadingBytes += (sizeof(_listenRadius)); } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { memcpy(currentPacketPtr, &_listenSourceCount, sizeof(_listenSourceCount)); currentPacketPtr += (sizeof(_listenSourceCount)); - + leadingBytes += (sizeof(_listenSourceCount)); if (_listenSources) { - memcpy(currentPacketPtr, &_listenSources, sizeof(int) * _listenSourceCount); + memcpy(currentPacketPtr, _listenSources, sizeof(int) * _listenSourceCount); currentPacketPtr += (sizeof(int) * _listenSourceCount); + leadingBytes += (sizeof(int) * _listenSourceCount); } } @@ -356,6 +360,12 @@ void Audio::addListenSource(int sourceID) { _listenSourceCount++; } +void Audio::clearListenSources() { + delete[] _listenSources; + _listenSources = NULL; + _listenSourceCount = 0; +} + void Audio::removeListenSource(int sourceID) { // If we don't yet have a list of listen sources, make one if (_listenSources) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index ca665c66f0..facc6a1caf 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -60,6 +60,7 @@ public: void setListenRadius(float radius) { _listenRadius = radius; }; void addListenSource(int sourceID); void removeListenSource(int sourceID); + void clearListenSources(); private: PaStream* _stream; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 75e0ab2f9b..ec0d5a2ce5 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -164,6 +164,10 @@ public: glm::quat getOrientation () const; glm::quat getWorldAlignedOrientation() const; + const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } + const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } + + glm::vec3 getGravity () const { return _gravity; } glm::vec3 getUprightHeadPosition() const; From 229d16b9c749a1e0671bb8ca3c79dfdfa51c289e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 22 Jul 2013 23:06:08 -0700 Subject: [PATCH 38/50] added local mode to injector --- injector/src/main.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/injector/src/main.cpp b/injector/src/main.cpp index e2c1effc15..0c3ea2bfe6 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -40,11 +40,13 @@ bool hasInjectedAudioOnce = false; float sleepIntervalMin = 1.00; float sleepIntervalMax = 2.00; char *sourceAudioFile = NULL; -const char *allowedParameters = ":sc::a::f::t::r:"; +const char *allowedParameters = ":sc::a::f::t::r:l"; float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f}; unsigned char volume = DEFAULT_INJECTOR_VOLUME; float triggerDistance = 0.0f; float radius = 0.0f; +bool wantLocalDomain = false; + void usage(void) { std::cout << "High Fidelity - Interface audio injector" << std::endl; @@ -54,6 +56,7 @@ void usage(void) { std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl; std::cout << " -t FLOAT Trigger distance for injection. If not specified will loop constantly" << std::endl; std::cout << " -r FLOAT Radius for spherical source. If not specified injected audio is point source" << std::endl; + std::cout << " -l Local domain mode." << std::endl; } bool processParameters(int parameterCount, char* parameterData[]) { @@ -96,6 +99,9 @@ bool processParameters(int parameterCount, char* parameterData[]) { ::radius = atof(optarg); std::cout << "[DEBUG] Injector radius: " << optarg << std::endl; break; + case 'l': + ::wantLocalDomain = true; + break; default: usage(); return false; @@ -111,6 +117,7 @@ void createAvatarDataForNode(Node* node) { } int main(int argc, char* argv[]) { + // new seed for random audio sleep times srand(time(0)); @@ -126,6 +133,11 @@ int main(int argc, char* argv[]) { // create an NodeList instance to handle communication with other nodes NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AUDIO_INJECTOR, AUDIO_UDP_SEND_PORT); + if (::wantLocalDomain) { + printf("Local Domain MODE!\n"); + nodeList->setDomainIPToLocalhost(); + } + // start the node list thread that will kill off nodes when they stop talking nodeList->startSilentNodeRemovalThread(); From a12ebc63c3bdbe627768b5611065f8bcab5da569 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Jul 2013 18:26:10 -0700 Subject: [PATCH 39/50] made listen mode a typedef --- audio-mixer/src/PositionalAudioRingBuffer.h | 12 ++++++------ libraries/audio/src/AudioRingBuffer.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/audio-mixer/src/PositionalAudioRingBuffer.h b/audio-mixer/src/PositionalAudioRingBuffer.h index eb6f0414e7..58a080872d 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.h +++ b/audio-mixer/src/PositionalAudioRingBuffer.h @@ -33,7 +33,7 @@ public: bool isListeningToSource(PositionalAudioRingBuffer* other); int getSourceID() const { return _sourceID; } - int getListeningMode() const { return _listenMode; } + ListenMode getListeningMode() const { return _listenMode; } protected: // disallow copying of PositionalAudioRingBuffer objects @@ -44,11 +44,11 @@ protected: glm::quat _orientation; bool _willBeAddedToMix; - int _sourceID; - int _listenMode; - float _listenRadius; - int _listenSourceCount; - int* _listenSources; + int _sourceID; + ListenMode _listenMode; + float _listenRadius; + int _listenSourceCount; + int* _listenSources; }; diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index be87558010..4c5374f032 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -29,11 +29,11 @@ class AudioRingBuffer : public NodeData { public: static int const DEFAULT_LISTEN_LIST_SIZE = 100; - enum { + typedef enum { NORMAL, OMNI_DIRECTIONAL_POINT, SELECTED_SOURCES - }; + } ListenMode; AudioRingBuffer(bool isStereo); ~AudioRingBuffer(); From 13ba913fabe58595dcc1114613f724ac2c4d513b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Jul 2013 18:28:30 -0700 Subject: [PATCH 40/50] made listen mode a typedef --- interface/src/Audio.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Audio.h b/interface/src/Audio.h index facc6a1caf..9552d6e2ec 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -56,7 +56,7 @@ public: int getSourceID() const { return _sourceID; }; void setSourceID(int sourceID) { _sourceID = sourceID; }; - void setListenMode(int mode) { _listenMode = mode; }; + void setListenMode(AudioRingBuffer::ListenMode mode) { _listenMode = mode; }; void setListenRadius(float radius) { _listenRadius = radius; }; void addListenSource(int sourceID); void removeListenSource(int sourceID); @@ -98,12 +98,12 @@ private: int _proceduralEffectSample; float _heartbeatMagnitude; - int _sourceID; - int _listenMode; - float _listenRadius; - int _listenSourceCount; - int _listenSourcesArraySize; - int* _listenSources; + int _sourceID; + AudioRingBuffer::ListenMode _listenMode; + float _listenRadius; + int _listenSourceCount; + int _listenSourcesArraySize; + int* _listenSources; // Audio callback in class context. inline void performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* outputRight); From 927b0b6708e131e6985d04c7a6a5ac8a18526659 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Jul 2013 18:31:57 -0700 Subject: [PATCH 41/50] style fixes --- audio-mixer/src/PositionalAudioRingBuffer.cpp | 8 ++++---- injector/src/main.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/audio-mixer/src/PositionalAudioRingBuffer.cpp b/audio-mixer/src/PositionalAudioRingBuffer.cpp index 26961c76e8..55622566a5 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.cpp +++ b/audio-mixer/src/PositionalAudioRingBuffer.cpp @@ -37,13 +37,13 @@ bool PositionalAudioRingBuffer::isListeningToSource(PositionalAudioRingBuffer* o default: case AudioRingBuffer::NORMAL: return true; - break; + break; case AudioRingBuffer::OMNI_DIRECTIONAL_POINT: { float distance = glm::distance(_position, other->_position); return distance <= _listenRadius; - break; - } + break; + } case AudioRingBuffer::SELECTED_SOURCES: if (_listenSources) { for (int i = 0; i < _listenSourceCount; i++) { @@ -53,7 +53,7 @@ bool PositionalAudioRingBuffer::isListeningToSource(PositionalAudioRingBuffer* o } } return false; - break; + break; } } diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 0c3ea2bfe6..9caad19e60 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -45,7 +45,7 @@ float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f}; unsigned char volume = DEFAULT_INJECTOR_VOLUME; float triggerDistance = 0.0f; float radius = 0.0f; -bool wantLocalDomain = false; +bool wantsLocalDomain = false; void usage(void) { @@ -100,7 +100,7 @@ bool processParameters(int parameterCount, char* parameterData[]) { std::cout << "[DEBUG] Injector radius: " << optarg << std::endl; break; case 'l': - ::wantLocalDomain = true; + ::wantsLocalDomain = true; break; default: usage(); @@ -133,7 +133,7 @@ int main(int argc, char* argv[]) { // create an NodeList instance to handle communication with other nodes NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AUDIO_INJECTOR, AUDIO_UDP_SEND_PORT); - if (::wantLocalDomain) { + if (::wantsLocalDomain) { printf("Local Domain MODE!\n"); nodeList->setDomainIPToLocalhost(); } From 686bd6c5d103d9eea0963a8b4fb3de7069b8998e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Jul 2013 19:06:47 -0700 Subject: [PATCH 42/50] removed _sourceID, using getNodeID() feature of Node class --- audio-mixer/src/PositionalAudioRingBuffer.cpp | 21 ++++++------------- audio-mixer/src/PositionalAudioRingBuffer.h | 5 +---- audio-mixer/src/main.cpp | 17 +++++++-------- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/audio-mixer/src/PositionalAudioRingBuffer.cpp b/audio-mixer/src/PositionalAudioRingBuffer.cpp index 55622566a5..4dc409628f 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.cpp +++ b/audio-mixer/src/PositionalAudioRingBuffer.cpp @@ -8,6 +8,7 @@ #include +#include #include #include "PositionalAudioRingBuffer.h" @@ -17,7 +18,6 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer() : _position(0.0f, 0.0f, 0.0f), _orientation(0.0f, 0.0f, 0.0f, 0.0f), _willBeAddedToMix(false), - _sourceID(-1), _listenMode(AudioRingBuffer::NORMAL), _listenRadius(0.0f), _listenSourceCount(0), @@ -32,7 +32,7 @@ PositionalAudioRingBuffer::~PositionalAudioRingBuffer() { } } -bool PositionalAudioRingBuffer::isListeningToSource(PositionalAudioRingBuffer* other) { +bool PositionalAudioRingBuffer::isListeningToNode(Node& other) const { switch (_listenMode) { default: case AudioRingBuffer::NORMAL: @@ -40,14 +40,15 @@ bool PositionalAudioRingBuffer::isListeningToSource(PositionalAudioRingBuffer* o break; case AudioRingBuffer::OMNI_DIRECTIONAL_POINT: { - float distance = glm::distance(_position, other->_position); + PositionalAudioRingBuffer* otherNodeBuffer = (PositionalAudioRingBuffer*) other.getLinkedData(); + float distance = glm::distance(_position, otherNodeBuffer->_position); return distance <= _listenRadius; break; } case AudioRingBuffer::SELECTED_SOURCES: if (_listenSources) { for (int i = 0; i < _listenSourceCount; i++) { - if (other->_sourceID == _listenSources[i]) { + if (other.getNodeID() == _listenSources[i]) { return true; } } @@ -60,7 +61,7 @@ bool PositionalAudioRingBuffer::isListeningToSource(PositionalAudioRingBuffer* o int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer); - currentBuffer += parseSourceData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); + currentBuffer += sizeof(int); // the source ID currentBuffer += parseListenModeData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parseAudioSamples(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); @@ -68,15 +69,6 @@ int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numByt return currentBuffer - sourceBuffer; } -int PositionalAudioRingBuffer::parseSourceData(unsigned char* sourceBuffer, int numBytes) { - unsigned char* currentBuffer = sourceBuffer; - - memcpy(&_sourceID, currentBuffer, sizeof(_sourceID)); - currentBuffer += sizeof(_sourceID); - - return currentBuffer - sourceBuffer; -} - int PositionalAudioRingBuffer::parseListenModeData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer; @@ -134,6 +126,5 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) { return true; } } - return false; } diff --git a/audio-mixer/src/PositionalAudioRingBuffer.h b/audio-mixer/src/PositionalAudioRingBuffer.h index 58a080872d..44d8a2b4f8 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.h +++ b/audio-mixer/src/PositionalAudioRingBuffer.h @@ -20,7 +20,6 @@ public: int parseData(unsigned char* sourceBuffer, int numBytes); int parsePositionalData(unsigned char* sourceBuffer, int numBytes); - int parseSourceData(unsigned char* sourceBuffer, int numBytes); int parseListenModeData(unsigned char* sourceBuffer, int numBytes); bool shouldBeAddedToMix(int numJitterBufferSamples); @@ -31,8 +30,7 @@ public: const glm::vec3& getPosition() const { return _position; } const glm::quat& getOrientation() const { return _orientation; } - bool isListeningToSource(PositionalAudioRingBuffer* other); - int getSourceID() const { return _sourceID; } + bool isListeningToNode(Node& other) const; ListenMode getListeningMode() const { return _listenMode; } protected: @@ -44,7 +42,6 @@ protected: glm::quat _orientation; bool _willBeAddedToMix; - int _sourceID; ListenMode _listenMode; float _listenRadius; int _listenSourceCount; diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index 2f17113ba4..6cfa106e5b 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -141,7 +141,6 @@ int main(int argc, const char* argv[]) { for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { PositionalAudioRingBuffer* positionalRingBuffer = (PositionalAudioRingBuffer*) node->getLinkedData(); - if (positionalRingBuffer && positionalRingBuffer->shouldBeAddedToMix(JITTER_BUFFER_SAMPLES)) { // this is a ring buffer that is ready to go // set its flag so we know to push its buffer when all is said and done @@ -161,14 +160,11 @@ int main(int argc, const char* argv[]) { // loop through all other nodes that have sufficient audio to mix for (NodeList::iterator otherNode = nodeList->begin(); otherNode != nodeList->end(); otherNode++) { - if (((PositionalAudioRingBuffer*) otherNode->getLinkedData())->willBeAddedToMix() && (otherNode != node || (otherNode == node && nodeRingBuffer->shouldLoopbackForNode()))) { - PositionalAudioRingBuffer* otherNodeBuffer = (PositionalAudioRingBuffer*) otherNode->getLinkedData(); - // based on our listen mode we will do this mixing... - if (nodeRingBuffer->isListeningToSource(otherNodeBuffer)) { + if (nodeRingBuffer->isListeningToNode(*otherNode)) { float bearingRelativeAngleToSource = 0.0f; float attenuationCoefficient = 1.0f; int numSamplesDelay = 0; @@ -355,14 +351,15 @@ int main(int argc, const char* argv[]) { packetVersionMatch(packetData)) { if (packetData[0] == PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO || packetData[0] == PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO) { + + unsigned char* currentBuffer = packetData + numBytesForPacketHeader(packetData); + int sourceID; + memcpy(&sourceID, currentBuffer, sizeof(sourceID)); + Node* avatarNode = nodeList->addOrUpdateNode(nodeAddress, nodeAddress, NODE_TYPE_AGENT, - nodeList->getLastNodeID()); - - if (avatarNode->getNodeID() == nodeList->getLastNodeID()) { - nodeList->increaseNodeID(); - } + sourceID); nodeList->updateNodeWithData(nodeAddress, packetData, receivedBytes); From a162643e1e5af883426c586c47c74567c5abda77 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Jul 2013 19:21:43 -0700 Subject: [PATCH 43/50] more removing of SourceID from classes --- audio-mixer/src/PositionalAudioRingBuffer.cpp | 3 ++- audio-mixer/src/main.cpp | 2 +- interface/src/Application.cpp | 12 +----------- interface/src/Audio.cpp | 8 ++++---- interface/src/Audio.h | 3 --- 5 files changed, 8 insertions(+), 20 deletions(-) diff --git a/audio-mixer/src/PositionalAudioRingBuffer.cpp b/audio-mixer/src/PositionalAudioRingBuffer.cpp index 4dc409628f..f0a3d41be5 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.cpp +++ b/audio-mixer/src/PositionalAudioRingBuffer.cpp @@ -61,7 +61,7 @@ bool PositionalAudioRingBuffer::isListeningToNode(Node& other) const { int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer); - currentBuffer += sizeof(int); // the source ID + currentBuffer += sizeof(uint16_t); // the source ID currentBuffer += parseListenModeData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parseAudioSamples(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); @@ -126,5 +126,6 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) { return true; } } + printf("packet mismatch...\n"); return false; } diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index 6cfa106e5b..9fc088a8bf 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -353,7 +353,7 @@ int main(int argc, const char* argv[]) { packetData[0] == PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO) { unsigned char* currentBuffer = packetData + numBytesForPacketHeader(packetData); - int sourceID; + uint16_t sourceID; memcpy(&sourceID, currentBuffer, sizeof(sourceID)); Node* avatarNode = nodeList->addOrUpdateNode(nodeAddress, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c1aa032542..14156b7aee 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3483,19 +3483,9 @@ void* Application::networkReceive(void* args) { case PACKET_TYPE_AVATAR_FACE_VIDEO: processAvatarFaceVideoMessage(app->_incomingPacket, bytesReceived); break; - default: { + default: NodeList::getInstance()->processNodeData(&senderAddress, app->_incomingPacket, bytesReceived); - - // Check to see if we have our ownerID - uint16_t ownerID = NodeList::getInstance()->getOwnerID(); - - if (ownerID != app->_audio.getSourceID()) { - app->_audio.setSourceID(ownerID); - } - - break; - } } } } else if (!app->_enableNetworkThread) { diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 9119d3984f..96c5db4d8c 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -121,9 +121,10 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o unsigned char* currentPacketPtr = dataPacket + populateTypeAndVersion(dataPacket, packetType); // pack Source Data - memcpy(currentPacketPtr, &_sourceID, sizeof(_sourceID)); - currentPacketPtr += (sizeof(_sourceID)); - leadingBytes += (sizeof(_sourceID)); + uint16_t ownerID = NodeList::getInstance()->getOwnerID(); + memcpy(currentPacketPtr, &ownerID, sizeof(ownerID)); + currentPacketPtr += (sizeof(ownerID)); + leadingBytes += (sizeof(ownerID)); // pack Listen Mode Data memcpy(currentPacketPtr, &_listenMode, sizeof(_listenMode)); @@ -413,7 +414,6 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _collisionSoundDuration(0.0f), _proceduralEffectSample(0), _heartbeatMagnitude(0.0f), - _sourceID(UNKNOWN_NODE_ID), _listenMode(AudioRingBuffer::NORMAL), _listenRadius(0.0f), _listenSourceCount(0), diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 9552d6e2ec..3886f9d6fc 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -54,8 +54,6 @@ public: // The results of the analysis are written to the log. bool eventuallyAnalyzePing(); - int getSourceID() const { return _sourceID; }; - void setSourceID(int sourceID) { _sourceID = sourceID; }; void setListenMode(AudioRingBuffer::ListenMode mode) { _listenMode = mode; }; void setListenRadius(float radius) { _listenRadius = radius; }; void addListenSource(int sourceID); @@ -98,7 +96,6 @@ private: int _proceduralEffectSample; float _heartbeatMagnitude; - int _sourceID; AudioRingBuffer::ListenMode _listenMode; float _listenRadius; int _listenSourceCount; From 9507cd8955d372199f4cdcd07cdaf6dba81df293 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Jul 2013 19:54:29 -0700 Subject: [PATCH 44/50] switched to vector --- audio-mixer/src/PositionalAudioRingBuffer.cpp | 30 ++++----- audio-mixer/src/PositionalAudioRingBuffer.h | 9 ++- interface/src/Audio.cpp | 67 +++++-------------- interface/src/Audio.h | 5 +- 4 files changed, 33 insertions(+), 78 deletions(-) diff --git a/audio-mixer/src/PositionalAudioRingBuffer.cpp b/audio-mixer/src/PositionalAudioRingBuffer.cpp index f0a3d41be5..9980b48a3e 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.cpp +++ b/audio-mixer/src/PositionalAudioRingBuffer.cpp @@ -19,17 +19,12 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer() : _orientation(0.0f, 0.0f, 0.0f, 0.0f), _willBeAddedToMix(false), _listenMode(AudioRingBuffer::NORMAL), - _listenRadius(0.0f), - _listenSourceCount(0), - _listenSources(NULL) + _listenRadius(0.0f) { } PositionalAudioRingBuffer::~PositionalAudioRingBuffer() { - if (_listenSources) { - delete[] _listenSources; - } } bool PositionalAudioRingBuffer::isListeningToNode(Node& other) const { @@ -46,11 +41,9 @@ bool PositionalAudioRingBuffer::isListeningToNode(Node& other) const { break; } case AudioRingBuffer::SELECTED_SOURCES: - if (_listenSources) { - for (int i = 0; i < _listenSourceCount; i++) { - if (other.getNodeID() == _listenSources[i]) { - return true; - } + for (int i = 0; i < _listenSources.size(); i++) { + if (other.getNodeID() == _listenSources[i]) { + return true; } } return false; @@ -79,14 +72,15 @@ int PositionalAudioRingBuffer::parseListenModeData(unsigned char* sourceBuffer, memcpy(&_listenRadius, currentBuffer, sizeof(_listenRadius)); currentBuffer += sizeof(_listenRadius); } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { - memcpy(&_listenSourceCount, currentBuffer, sizeof(_listenSourceCount)); - currentBuffer += sizeof(_listenSourceCount); - if (_listenSources) { - delete[] _listenSources; + int listenSourcesCount; + memcpy(&listenSourcesCount, currentBuffer, sizeof(listenSourcesCount)); + currentBuffer += sizeof(listenSourcesCount); + for (int i = 0; i < listenSourcesCount; i++) { + int sourceID; + memcpy(&sourceID, currentBuffer, sizeof(sourceID)); + currentBuffer += sizeof(sourceID); + _listenSources.push_back(sourceID); } - _listenSources = new int[_listenSourceCount]; - memcpy(_listenSources, currentBuffer, sizeof(int) * _listenSourceCount); - currentBuffer += sizeof(int) * _listenSourceCount; } return currentBuffer - sourceBuffer; diff --git a/audio-mixer/src/PositionalAudioRingBuffer.h b/audio-mixer/src/PositionalAudioRingBuffer.h index 44d8a2b4f8..6c7ee9ce3f 100644 --- a/audio-mixer/src/PositionalAudioRingBuffer.h +++ b/audio-mixer/src/PositionalAudioRingBuffer.h @@ -9,6 +9,7 @@ #ifndef __hifi__PositionalAudioRingBuffer__ #define __hifi__PositionalAudioRingBuffer__ +#include #include #include @@ -42,11 +43,9 @@ protected: glm::quat _orientation; bool _willBeAddedToMix; - ListenMode _listenMode; - float _listenRadius; - int _listenSourceCount; - int* _listenSources; - + ListenMode _listenMode; + float _listenRadius; + std::vector _listenSources; }; #endif /* defined(__hifi__PositionalAudioRingBuffer__) */ diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 96c5db4d8c..a9aa61a34e 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -136,13 +136,14 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o currentPacketPtr += (sizeof(_listenRadius)); leadingBytes += (sizeof(_listenRadius)); } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { - memcpy(currentPacketPtr, &_listenSourceCount, sizeof(_listenSourceCount)); - currentPacketPtr += (sizeof(_listenSourceCount)); - leadingBytes += (sizeof(_listenSourceCount)); - if (_listenSources) { - memcpy(currentPacketPtr, _listenSources, sizeof(int) * _listenSourceCount); - currentPacketPtr += (sizeof(int) * _listenSourceCount); - leadingBytes += (sizeof(int) * _listenSourceCount); + int listenSourceCount = _listenSources.size(); + memcpy(currentPacketPtr, &listenSourceCount, sizeof(listenSourceCount)); + currentPacketPtr += (sizeof(listenSourceCount)); + leadingBytes += (sizeof(listenSourceCount)); + for (int i = 0; i < listenSourceCount; i++) { + memcpy(currentPacketPtr, &_listenSources[i], sizeof(_listenSources[i])); + currentPacketPtr += sizeof(_listenSources[i]); + leadingBytes += sizeof(_listenSources[i]); } } @@ -336,49 +337,18 @@ void Audio::reset() { } void Audio::addListenSource(int sourceID) { - - // If we don't yet have a list of listen sources, make one - if (!_listenSources) { - _listenSources = new int[AudioRingBuffer::DEFAULT_LISTEN_LIST_SIZE]; - } - - // First check to see if the source is already in our list - for (int i = 0; i < _listenSourceCount; i++) { - if (_listenSources[i] == sourceID) { - return; // already in list - } - } - - // we know it's not in the list, check to see if we have room to add our source - if (_listenSourceCount + 1 < _listenSourcesArraySize) { - int* newList = new int[_listenSourcesArraySize + AudioRingBuffer::DEFAULT_LISTEN_LIST_SIZE]; - memmove(newList, _listenSources, _listenSourcesArraySize); - delete[] _listenSources; - _listenSources = newList; - _listenSourcesArraySize += AudioRingBuffer::DEFAULT_LISTEN_LIST_SIZE; - } - _listenSources[_listenSourceCount] = sourceID; - _listenSourceCount++; + _listenSources.push_back(sourceID); } void Audio::clearListenSources() { - delete[] _listenSources; - _listenSources = NULL; - _listenSourceCount = 0; + _listenSources.clear(); } void Audio::removeListenSource(int sourceID) { - // If we don't yet have a list of listen sources, make one - if (_listenSources) { - // First check to see if the source is already in our list - for (int i = 0; i < _listenSourceCount; i++) { - if (_listenSources[i] == sourceID) { - - // found it, so, move the items forward in list - memmove(&_listenSources[i], &_listenSources[i+1], _listenSourceCount - i); - _listenSourceCount--; - return; - } + for (int i = 0; i < _listenSources.size(); i++) { + if (_listenSources[i] == sourceID) { + _listenSources.erase(_listenSources.begin() + i); + return; } } } @@ -415,10 +385,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _proceduralEffectSample(0), _heartbeatMagnitude(0.0f), _listenMode(AudioRingBuffer::NORMAL), - _listenRadius(0.0f), - _listenSourceCount(0), - _listenSourcesArraySize(0), - _listenSources(NULL) + _listenRadius(0.0f) { outputPortAudioError(Pa_Initialize()); @@ -487,10 +454,6 @@ Audio::~Audio() { outputPortAudioError(Pa_Terminate()); } delete[] _echoSamplesLeft; - - if (_listenSources) { - delete[] _listenSources; - } } void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBytes) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 3886f9d6fc..2eb4e7ef70 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -9,6 +9,7 @@ #ifndef __interface__Audio__ #define __interface__Audio__ +#include #include #include #include @@ -98,9 +99,7 @@ private: AudioRingBuffer::ListenMode _listenMode; float _listenRadius; - int _listenSourceCount; - int _listenSourcesArraySize; - int* _listenSources; + std::vector _listenSources; // Audio callback in class context. inline void performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* outputRight); From eb8c5653500df4df5a9cd50e09a006e965cd6c94 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Jul 2013 20:08:57 -0700 Subject: [PATCH 45/50] dry up code --- interface/src/Application.cpp | 33 +++++++++++++++++---------------- interface/src/Application.h | 4 +++- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 14156b7aee..9784a8a7e6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1864,20 +1864,13 @@ void Application::setListenModeSingleSource() { _audio.setListenMode(AudioRingBuffer::SELECTED_SOURCES); _audio.clearListenSources(); - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { - Avatar* avatar = (Avatar *) node->getLinkedData(); - glm::vec3 headPosition = avatar->getHead().getPosition(); - glm::vec3 mouseRayOrigin = _myAvatar.getMouseRayOrigin(); - glm::vec3 mouseRayDirection = _myAvatar.getMouseRayDirection(); - const float HEAD_SPHERE_RADIUS = 0.07; + glm::vec3 mouseRayOrigin = _myAvatar.getMouseRayOrigin(); + glm::vec3 mouseRayDirection = _myAvatar.getMouseRayDirection(); + glm::vec3 eyePositionIgnored; + uint16_t nodeID; - if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) { - int sourceID = avatar->getOwningNode()->getNodeID(); - _audio.addListenSource(sourceID); - } - } + if (isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeID)) { + _audio.addListenSource(nodeID); } } @@ -1970,7 +1963,10 @@ const float MAX_AVATAR_EDIT_VELOCITY = 1.0f; const float MAX_VOXEL_EDIT_DISTANCE = 20.0f; const float HEAD_SPHERE_RADIUS = 0.07; -bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, glm::vec3& eyePosition) { + +bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, + glm::vec3& eyePosition, uint16_t& nodeID) { + NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { @@ -1979,6 +1975,7 @@ bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& m if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) { eyePosition = avatar->getHead().getEyeLevelPosition(); _lookatOtherPosition = headPosition; + nodeID = avatar->getOwningNode()->getNodeID(); return true; } } @@ -2022,7 +2019,9 @@ void Application::update(float deltaTime) { // Set where I am looking based on my mouse ray (so that other people can see) glm::vec3 eyePosition; - if (_isLookingAtOtherAvatar = isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition)) { + uint16_t ignored; + _isLookingAtOtherAvatar = isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition, ignored); + if (_isLookingAtOtherAvatar) { // If the mouse is over another avatar's head... glm::vec3 myLookAtFromMouse(eyePosition); _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); @@ -2284,7 +2283,9 @@ void Application::updateAvatar(float deltaTime) { _viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection); glm::vec3 eyePosition; - if (_isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition)) { + uint16_t ignored; + _isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition, ignored); + if (_isLookingAtOtherAvatar) { glm::vec3 myLookAtFromMouse(eyePosition); _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); } diff --git a/interface/src/Application.h b/interface/src/Application.h index d462e88b98..da8cf96189 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -203,7 +203,9 @@ private: void init(); void update(float deltaTime); - bool isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, glm::vec3& eyePosition); + bool isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, + glm::vec3& eyePosition, uint16_t& nodeID); + void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera); void updateAvatar(float deltaTime); void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); From 7177b71bc77f29b635787d2e1048ecf36c5f6e5e Mon Sep 17 00:00:00 2001 From: Mark Peng Date: Wed, 24 Jul 2013 00:19:25 -0700 Subject: [PATCH 46/50] Replace var in renderLookatIndicator with const IDENTITY_UP --- interface/src/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c0fe2b360b..c5f12822fe 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1960,8 +1960,7 @@ void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& which const int NUM_SEGMENTS = 30; glm::vec3 haloOrigin(pointOfInterest.x, pointOfInterest.y + DISTANCE_FROM_HEAD_SPHERE, pointOfInterest.z); glColor3f(YELLOW[0], YELLOW[1], YELLOW[2]); - glm::vec3 normalToFloor(0.0f, 1.0f, 0.0f); - renderCircle(haloOrigin, INDICATOR_RADIUS, normalToFloor, NUM_SEGMENTS); + renderCircle(haloOrigin, INDICATOR_RADIUS, IDENTITY_UP, NUM_SEGMENTS); } void Application::update(float deltaTime) { From b2b67d2b3dac6f20dbd079606520874677220559 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 24 Jul 2013 01:18:54 -0700 Subject: [PATCH 47/50] split multiple avatars into multiple packets if needed --- avatar-mixer/src/main.cpp | 62 ++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/avatar-mixer/src/main.cpp b/avatar-mixer/src/main.cpp index f8bc36f6e6..b2e28fe484 100644 --- a/avatar-mixer/src/main.cpp +++ b/avatar-mixer/src/main.cpp @@ -36,7 +36,7 @@ const int AVATAR_LISTEN_PORT = 55444; -unsigned char *addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) { +unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) { currentPosition += packNodeId(currentPosition, nodeToAdd->getNodeID()); AvatarData *nodeData = (AvatarData *)nodeToAdd->getLinkedData(); @@ -51,6 +51,47 @@ void attachAvatarDataToNode(Node* newNode) { } } +unsigned char broadcastPacketBuffer[MAX_PACKET_SIZE]; +unsigned char avatarDataBuffer[MAX_PACKET_SIZE]; +void broadcastAvatarData(NodeList* nodeList, sockaddr* nodeAddress) { + unsigned char* broadcastPacket = (unsigned char*)&::broadcastPacketBuffer[0]; + int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_BULK_AVATAR_DATA); + unsigned char* currentBufferPosition = NULL; + currentBufferPosition = broadcastPacket + numHeaderBytes; + int packetLength = currentBufferPosition - broadcastPacket; + int packetsSent = 0; + + // send back a packet with other active node data to this node + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getLinkedData() && !socketMatch(nodeAddress, node->getActiveSocket())) { + unsigned char* avatarDataEndpoint = addNodeToBroadcastPacket((unsigned char*)&avatarDataBuffer[0], &*node); + int avatarDataLength = avatarDataEndpoint - (unsigned char*)&avatarDataBuffer; + + if (avatarDataLength + packetLength <= MAX_PACKET_SIZE) { + memcpy(currentBufferPosition, &avatarDataBuffer[0], avatarDataLength); + packetLength += avatarDataLength; + currentBufferPosition += avatarDataLength; + } else { + packetsSent++; + //printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength); + nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket); + + // reset the packet + currentBufferPosition = broadcastPacket + numHeaderBytes; + packetLength = currentBufferPosition - broadcastPacket; + + // copy the avatar that didn't fit into the next packet + memcpy(currentBufferPosition, &avatarDataBuffer[0], avatarDataLength); + packetLength += avatarDataLength; + currentBufferPosition += avatarDataLength; + } + } + } + packetsSent++; + //printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength); + nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket); +} + int main(int argc, const char* argv[]) { NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT); @@ -67,14 +108,11 @@ int main(int argc, const char* argv[]) { nodeList->startSilentNodeRemovalThread(); - sockaddr *nodeAddress = new sockaddr; - unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; + sockaddr* nodeAddress = new sockaddr; ssize_t receivedBytes = 0; - unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE]; - int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_BULK_AVATAR_DATA); + unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE]; - unsigned char* currentBufferPosition = NULL; uint16_t nodeID = 0; Node* avatarNode = NULL; @@ -104,17 +142,7 @@ int main(int argc, const char* argv[]) { // parse positional data from an node nodeList->updateNodeWithData(avatarNode, packetData, receivedBytes); case PACKET_TYPE_INJECT_AUDIO: - currentBufferPosition = broadcastPacket + numHeaderBytes; - - // send back a packet with other active node data to this node - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData() && !socketMatch(nodeAddress, node->getActiveSocket())) { - currentBufferPosition = addNodeToBroadcastPacket(currentBufferPosition, &*node); - } - } - - nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket); - + broadcastAvatarData(nodeList, nodeAddress); break; case PACKET_TYPE_AVATAR_VOXEL_URL: case PACKET_TYPE_AVATAR_FACE_VIDEO: From bacb4f96e37e68492c82c027888ff28521001166 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 24 Jul 2013 09:59:51 -0700 Subject: [PATCH 48/50] added notes --- avatar-mixer/src/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/avatar-mixer/src/main.cpp b/avatar-mixer/src/main.cpp index b2e28fe484..8383c992b2 100644 --- a/avatar-mixer/src/main.cpp +++ b/avatar-mixer/src/main.cpp @@ -51,6 +51,13 @@ void attachAvatarDataToNode(Node* newNode) { } } +// NOTE: some additional optimizations to consider. +// 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present +// if the avatar is not in view or in the keyhole. +// 2) after culling for view frustum, sort order the avatars by distance, send the closest ones first. +// 3) if we need to rate limit the amount of data we send, we can use a distance weighted "semi-random" function to +// determine which avatars are included in the packet stream +// 4) we should optimize the avatar data format to be more compact (100 bytes is pretty wasteful). unsigned char broadcastPacketBuffer[MAX_PACKET_SIZE]; unsigned char avatarDataBuffer[MAX_PACKET_SIZE]; void broadcastAvatarData(NodeList* nodeList, sockaddr* nodeAddress) { From 212fddbd346f4ecd52c19f44e4c0f742a8e4f114 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 25 Jul 2013 12:29:17 -0700 Subject: [PATCH 49/50] CR feedback --- avatar-mixer/src/main.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/avatar-mixer/src/main.cpp b/avatar-mixer/src/main.cpp index 8383c992b2..0677ffbc7e 100644 --- a/avatar-mixer/src/main.cpp +++ b/avatar-mixer/src/main.cpp @@ -58,13 +58,12 @@ void attachAvatarDataToNode(Node* newNode) { // 3) if we need to rate limit the amount of data we send, we can use a distance weighted "semi-random" function to // determine which avatars are included in the packet stream // 4) we should optimize the avatar data format to be more compact (100 bytes is pretty wasteful). -unsigned char broadcastPacketBuffer[MAX_PACKET_SIZE]; -unsigned char avatarDataBuffer[MAX_PACKET_SIZE]; void broadcastAvatarData(NodeList* nodeList, sockaddr* nodeAddress) { - unsigned char* broadcastPacket = (unsigned char*)&::broadcastPacketBuffer[0]; + static unsigned char broadcastPacketBuffer[MAX_PACKET_SIZE]; + static unsigned char avatarDataBuffer[MAX_PACKET_SIZE]; + unsigned char* broadcastPacket = (unsigned char*)&broadcastPacketBuffer[0]; int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_BULK_AVATAR_DATA); - unsigned char* currentBufferPosition = NULL; - currentBufferPosition = broadcastPacket + numHeaderBytes; + unsigned char* currentBufferPosition = broadcastPacket + numHeaderBytes; int packetLength = currentBufferPosition - broadcastPacket; int packetsSent = 0; From 919f2a4a939df264e11a4ef82ed7827c759683b6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 25 Jul 2013 12:56:00 -0700 Subject: [PATCH 50/50] fix voxel-server crash --- libraries/voxels/src/VoxelTree.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index b26a70f34b..fe67a50dee 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1071,6 +1071,9 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node, unsigned char* outputBuffer, int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag, EncodeBitstreamParams& params, int& currentEncodeLevel) const { + // you can't call this without a valid node + assert(node); + // How many bytes have we written so far at this level; int bytesAtThisLevel = 0; @@ -1228,6 +1231,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp } // track stats + // must check childNode here, because it could be we got here with no childNode if (params.stats && childNode) { params.stats->traversed(childNode); } @@ -1243,7 +1247,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp bool childIsInView = (childNode && (!params.viewFrustum || childNode->isInView(*params.viewFrustum))); if (!childIsInView) { - if (params.stats) { + // must check childNode here, because it could be we got here because there was no childNode + if (params.stats && childNode) { params.stats->skippedOutOfView(childNode); } } else { @@ -1253,6 +1258,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust); if (!(distance < boundaryDistance)) { + // don't need to check childNode here, because we can't get here with no childNode if (params.stats) { params.stats->skippedDistance(childNode); } @@ -1306,9 +1312,11 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // track some stats if (params.stats) { + // don't need to check childNode here, because we can't get here with no childNode if (!shouldRender && childNode->isLeaf()) { params.stats->skippedDistance(childNode); } + // don't need to check childNode here, because we can't get here with no childNode if (childIsOccluded) { params.stats->skippedOccluded(childNode); } @@ -1339,6 +1347,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp inViewWithColorCount++; } else { // otherwise just track stats of the items we discarded + // don't need to check childNode here, because we can't get here with no childNode if (params.stats) { if (childWasInView) { params.stats->skippedWasInView(childNode); @@ -1368,6 +1377,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color + // don't need to check childNode here, because we can't get here with no childNode if (params.stats) { params.stats->colorSent(childNode); } @@ -1407,6 +1417,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp } else { bag.insert(node); + // don't need to check node here, because we can't get here with no node if (params.stats) { params.stats->didntFit(node); }