diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp
index 751583960e..ef69771607 100644
--- a/assignment-client/src/octree/OctreeSendThread.cpp
+++ b/assignment-client/src/octree/OctreeSendThread.cpp
@@ -241,6 +241,9 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
int truePacketsSent = 0;
int trueBytesSent = 0;
int packetsSentThisInterval = 0;
+ bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging())
+ || nodeData->hasLodChanged();
+
bool somethingToSend = true; // assume we have something
// FOR NOW... node tells us if it wants to receive only view frustum deltas
@@ -365,10 +368,6 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
<< " Wasted:" << _totalWastedBytes;
}
- // start tracking our stats
- bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta())
- && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged();
-
// If we're starting a full scene, then definitely we want to empty the nodeBag
if (isFullScene) {
nodeData->nodeBag.deleteAll();
@@ -382,6 +381,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
}
::startSceneSleepTime = _usleepTime;
+ // start tracking our stats
nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getOctree()->getRoot(), _myServer->getJurisdiction());
// This is the start of "resending" the scene.
@@ -432,10 +432,6 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
int boundaryLevelAdjust = boundaryLevelAdjustClient + (viewFrustumChanged && nodeData->getWantLowResMoving()
? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
-
- bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) &&
- nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged();
-
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor,
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
wantOcclusionCulling, coverageMap, boundaryLevelAdjust, voxelSizeScale,
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index e5979c561f..a425052970 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -544,8 +544,16 @@ void DomainServer::readAvailableDatagrams() {
// construct the requested assignment from the packet data
Assignment requestAssignment(receivedPacket);
- qDebug() << "Received a request for assignment type" << requestAssignment.getType()
- << "from" << senderSockAddr;
+ // Suppress these for Assignment::AgentType to once per 5 seconds
+ static quint64 lastNoisyMessage = usecTimestampNow();
+ quint64 timeNow = usecTimestampNow();
+ const quint64 NOISY_TIME_ELAPSED = 5 * USECS_PER_SECOND;
+ bool noisyMessage = false;
+ if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastNoisyMessage) > NOISY_TIME_ELAPSED) {
+ qDebug() << "Received a request for assignment type" << requestAssignment.getType()
+ << "from" << senderSockAddr;
+ noisyMessage = true;
+ }
SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
@@ -562,8 +570,15 @@ void DomainServer::readAvailableDatagrams() {
nodeList->getNodeSocket().writeDatagram(assignmentPacket,
senderSockAddr.getAddress(), senderSockAddr.getPort());
} else {
- qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
- << "from" << senderSockAddr;
+ if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastNoisyMessage) > NOISY_TIME_ELAPSED) {
+ qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
+ << "from" << senderSockAddr;
+ noisyMessage = true;
+ }
+ }
+
+ if (noisyMessage) {
+ lastNoisyMessage = timeNow;
}
}
}
diff --git a/interface/interface_en.ts b/interface/interface_en.ts
index f700be655c..72299befa4 100644
--- a/interface/interface_en.ts
+++ b/interface/interface_en.ts
@@ -28,19 +28,19 @@
ChatWindow
-
+
Chat
-
+
Connecting to XMPP...
-
+
online now:
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index f709b24eb3..854e449c23 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -141,6 +141,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_justStarted(true),
_voxelImporter(NULL),
_wantToKillLocalVoxels(false),
+ _viewFrustum(),
+ _lastQueriedViewFrustum(),
+ _lastQueriedTime(usecTimestampNow()),
_audioScope(256, 200, true),
_myAvatar(),
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
@@ -1895,8 +1898,19 @@ void Application::updateMyAvatar(float deltaTime) {
loadViewFrustum(_myCamera, _viewFrustum);
// Update my voxel servers with my current voxel query...
- queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
- queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
+ quint64 now = usecTimestampNow();
+ quint64 sinceLastQuery = now - _lastQueriedTime;
+ const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
+ bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY;
+ bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum);
+
+ // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it
+ if (queryIsDue || viewIsDifferentEnough) {
+ _lastQueriedTime = now;
+ queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
+ queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
+ _lastQueriedViewFrustum = _viewFrustum;
+ }
}
void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {
@@ -2745,8 +2759,8 @@ void Application::displayStats() {
voxelStats.str("");
QString packetsString = locale.toString((int)voxelPacketsToProcess);
QString maxString = locale.toString((int)_recentMaxPackets);
- voxelStats << "Voxel Packets to Process: " << packetsString.toLocal8Bit().constData()
- << " [Recent Max: " << maxString.toLocal8Bit().constData() << "]";
+ voxelStats << "Voxel Packets to Process: " << qPrintable(packetsString)
+ << " [Recent Max: " << qPrintable(maxString) << "]";
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
}
@@ -2769,7 +2783,7 @@ void Application::displayStats() {
// Server Voxels
voxelStats.str("");
- voxelStats << "Server voxels: " << serversTotalString.toLocal8Bit().constData();
+ voxelStats << "Server voxels: " << qPrintable(serversTotalString);
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
@@ -2779,8 +2793,8 @@ void Application::displayStats() {
voxelStats.str("");
voxelStats <<
- "Internal: " << serversInternalString.toLocal8Bit().constData() << " " <<
- "Leaves: " << serversLeavesString.toLocal8Bit().constData() << "";
+ "Internal: " << qPrintable(serversInternalString) << " " <<
+ "Leaves: " << qPrintable(serversLeavesString) << "";
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
}
@@ -2790,7 +2804,7 @@ void Application::displayStats() {
// Local Voxels
voxelStats.str("");
- voxelStats << "Local voxels: " << localTotalString.toLocal8Bit().constData();
+ voxelStats << "Local voxels: " << qPrintable(localTotalString);
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
@@ -2802,8 +2816,17 @@ void Application::displayStats() {
voxelStats.str("");
voxelStats <<
- "Internal: " << localInternalString.toLocal8Bit().constData() << " " <<
- "Leaves: " << localLeavesString.toLocal8Bit().constData() << "";
+ "Internal: " << qPrintable(localInternalString) << " " <<
+ "Leaves: " << qPrintable(localLeavesString) << "";
+ verticalOffset += STATS_PELS_PER_LINE;
+ drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT);
+ }
+
+ // LOD Details
+ if (_statsExpanded) {
+ voxelStats.str("");
+ QString displayLODDetails = Menu::getInstance()->getLODFeedbackText();
+ voxelStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed());
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
}
diff --git a/interface/src/Application.h b/interface/src/Application.h
index f1437c62ba..de6ac2ad06 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -376,6 +376,8 @@ private:
MetavoxelSystem _metavoxels;
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
+ ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels, particles)
+ quint64 _lastQueriedTime;
Oscilloscope _audioScope;
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 21c470c0cf..f73da0400a 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -1091,6 +1091,40 @@ void Menu::octreeStatsDetailsClosed() {
}
}
+QString Menu::getLODFeedbackText() {
+ // determine granularity feedback
+ int boundaryLevelAdjust = getBoundaryLevelAdjust();
+ QString granularityFeedback;
+
+ switch (boundaryLevelAdjust) {
+ case 0: {
+ granularityFeedback = QString("at standard granularity.");
+ } break;
+ case 1: {
+ granularityFeedback = QString("at half of standard granularity.");
+ } break;
+ case 2: {
+ granularityFeedback = QString("at a third of standard granularity.");
+ } break;
+ default: {
+ granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1);
+ } break;
+ }
+
+ // distance feedback
+ float voxelSizeScale = getVoxelSizeScale();
+ float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
+ QString result;
+ if (relativeToDefault > 1.01) {
+ result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback);
+ } else if (relativeToDefault > 0.99) {
+ result = QString("the default distance %1").arg(granularityFeedback);
+ } else {
+ result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback);
+ }
+ return result;
+}
+
void Menu::autoAdjustLOD(float currentFPS) {
// NOTE: our first ~100 samples at app startup are completely all over the place, and we don't
// really want to count them in our average, so we will ignore the real frame rates and stuff
diff --git a/interface/src/Menu.h b/interface/src/Menu.h
index 380fe2d3b7..00ef51178a 100644
--- a/interface/src/Menu.h
+++ b/interface/src/Menu.h
@@ -84,6 +84,7 @@ public:
void handleViewFrustumOffsetKeyModifier(int key);
// User Tweakable LOD Items
+ QString getLODFeedbackText();
void autoAdjustLOD(float currentFPS);
void setVoxelSizeScale(float sizeScale);
float getVoxelSizeScale() const { return _voxelSizeScale; }
diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp
index 2fd3d4f9cb..5fc5d56430 100644
--- a/interface/src/ui/ChatWindow.cpp
+++ b/interface/src/ui/ChatWindow.cpp
@@ -184,11 +184,8 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
}
QLabel* userLabel = new QLabel(getParticipantName(message.from()));
- QFont font = userLabel->font();
- font.setBold(true);
- userLabel->setFont(font);
userLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- userLabel->setStyleSheet("padding: 2px;");
+ userLabel->setStyleSheet("padding: 2px; font-weight: bold");
userLabel->setAlignment(Qt::AlignTop);
QLabel* messageLabel = new QLabel(message.body().replace(regexLinks, "\\1"));
diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp
index 4cf4a29bf1..564669757c 100644
--- a/interface/src/ui/LodToolsDialog.cpp
+++ b/interface/src/ui/LodToolsDialog.cpp
@@ -68,7 +68,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
const unsigned redish = 0xfff00000;
palette.setColor(QPalette::WindowText, QColor::fromRgb(redish));
_feedback->setPalette(palette);
- _feedback->setText(getFeedbackText());
+ _feedback->setText(Menu::getInstance()->getLODFeedbackText());
const int FEEDBACK_WIDTH = 350;
_feedback->setFixedWidth(FEEDBACK_WIDTH);
form->addRow("You can see... ", _feedback);
@@ -81,40 +81,6 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
this->QDialog::setLayout(form);
}
-QString LodToolsDialog::getFeedbackText() {
- // determine granularity feedback
- int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
- QString granularityFeedback;
-
- switch (boundaryLevelAdjust) {
- case 0: {
- granularityFeedback = QString("at standard granularity.");
- } break;
- case 1: {
- granularityFeedback = QString("at half of standard granularity.");
- } break;
- case 2: {
- granularityFeedback = QString("at a third of standard granularity.");
- } break;
- default: {
- granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1);
- } break;
- }
-
- // distance feedback
- float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
- float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
- QString result;
- if (relativeToDefault > 1.01) {
- result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback);
- } else if (relativeToDefault > 0.99) {
- result = QString("the default distance %1").arg(granularityFeedback);
- } else {
- result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback);
- }
- return result;
-}
-
LodToolsDialog::~LodToolsDialog() {
delete _feedback;
delete _lodSize;
@@ -124,19 +90,19 @@ LodToolsDialog::~LodToolsDialog() {
void LodToolsDialog::reloadSliders() {
_lodSize->setValue(Menu::getInstance()->getVoxelSizeScale() / TREE_SCALE);
_boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust());
- _feedback->setText(getFeedbackText());
+ _feedback->setText(Menu::getInstance()->getLODFeedbackText());
}
void LodToolsDialog::sizeScaleValueChanged(int value) {
float realValue = value * TREE_SCALE;
Menu::getInstance()->setVoxelSizeScale(realValue);
- _feedback->setText(getFeedbackText());
+ _feedback->setText(Menu::getInstance()->getLODFeedbackText());
}
void LodToolsDialog::boundaryLevelValueChanged(int value) {
Menu::getInstance()->setBoundaryLevelAdjust(value);
- _feedback->setText(getFeedbackText());
+ _feedback->setText(Menu::getInstance()->getLODFeedbackText());
}
void LodToolsDialog::resetClicked(bool checked) {
diff --git a/interface/src/ui/LodToolsDialog.h b/interface/src/ui/LodToolsDialog.h
index ee96cffd7e..98a5fce5f8 100644
--- a/interface/src/ui/LodToolsDialog.h
+++ b/interface/src/ui/LodToolsDialog.h
@@ -36,8 +36,6 @@ protected:
void closeEvent(QCloseEvent*);
private:
- QString getFeedbackText();
-
QSlider* _lodSize;
QSlider* _boundaryLevelAdjust;
QLabel* _feedback;
diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp
index 974964da04..daf5a68587 100644
--- a/interface/src/ui/OctreeStatsDialog.cpp
+++ b/interface/src/ui/OctreeStatsDialog.cpp
@@ -157,9 +157,9 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) {
statsValue.str("");
statsValue <<
- "Total: " << localTotalString.toLocal8Bit().constData() << " / " <<
- "Internal: " << localInternalString.toLocal8Bit().constData() << " / " <<
- "Leaves: " << localLeavesString.toLocal8Bit().constData() << "";
+ "Total: " << qPrintable(localTotalString) << " / " <<
+ "Internal: " << qPrintable(localInternalString) << " / " <<
+ "Leaves: " << qPrintable(localLeavesString) << "";
label->setText(statsValue.str().c_str());
// iterate all the current voxel stats, and list their sending modes, total their voxels, etc...
@@ -212,9 +212,9 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) {
label = _labels[_serverVoxels];
statsValue.str("");
statsValue <<
- "Total: " << serversTotalString.toLocal8Bit().constData() << " / " <<
- "Internal: " << serversInternalString.toLocal8Bit().constData() << " / " <<
- "Leaves: " << serversLeavesString.toLocal8Bit().constData() << "";
+ "Total: " << qPrintable(serversTotalString) << " / " <<
+ "Internal: " << qPrintable(serversInternalString) << " / " <<
+ "Leaves: " << qPrintable(serversLeavesString) << "";
label->setText(statsValue.str().c_str());
showAllOctreeServers();
@@ -290,7 +290,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
serverBounds.scale(TREE_SCALE);
serverDetails << " jurisdiction: "
- << rootCodeHex.toLocal8Bit().constData()
+ << qPrintable(rootCodeHex)
<< " ["
<< rootDetails.x << ", "
<< rootDetails.y << ", "
@@ -315,13 +315,25 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
const unsigned long USECS_PER_MSEC = 1000;
float lastFullEncode = stats.getLastFullTotalEncodeTime() / USECS_PER_MSEC;
float lastFullSend = stats.getLastFullElapsedTime() / USECS_PER_MSEC;
+ float lastFullSendInSeconds = stats.getLastFullElapsedTime() / USECS_PER_SECOND;
+ float lastFullPackets = stats.getLastFullTotalPackets();
+ float lastFullPPS = lastFullPackets;
+ if (lastFullSendInSeconds > 0) {
+ lastFullPPS = lastFullPackets / lastFullSendInSeconds;
+ }
QString lastFullEncodeString = locale.toString(lastFullEncode);
QString lastFullSendString = locale.toString(lastFullSend);
+ QString lastFullPacketsString = locale.toString(lastFullPackets);
+ QString lastFullBytesString = locale.toString((uint)stats.getLastFullTotalBytes());
+ QString lastFullPPSString = locale.toString(lastFullPPS);
extraDetails << "
" << "Last Full Scene... " <<
- "Encode Time: " << lastFullEncodeString.toLocal8Bit().constData() << " ms " <<
- "Send Time: " << lastFullSendString.toLocal8Bit().constData() << " ms ";
+ "Encode: " << qPrintable(lastFullEncodeString) << " ms " <<
+ "Send: " << qPrintable(lastFullSendString) << " ms " <<
+ "Packets: " << qPrintable(lastFullPacketsString) << " " <<
+ "Bytes: " << qPrintable(lastFullBytesString) << " " <<
+ "Rate: " << qPrintable(lastFullPPSString) << " PPS";
for (int i = 0; i < OctreeSceneStats::ITEM_COUNT; i++) {
OctreeSceneStats::Item item = (OctreeSceneStats::Item)(i);
@@ -334,42 +346,51 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
QString internalString = locale.toString((uint)stats.getTotalInternal());
QString leavesString = locale.toString((uint)stats.getTotalLeaves());
- serverDetails << "
" << "Node UUID: " <<
- nodeUUID.toString().toLocal8Bit().constData() << " ";
+ serverDetails << "
" << "Node UUID: " << qPrintable(nodeUUID.toString()) << " ";
serverDetails << "
" << "Voxels: " <<
- totalString.toLocal8Bit().constData() << " total " <<
- internalString.toLocal8Bit().constData() << " internal " <<
- leavesString.toLocal8Bit().constData() << " leaves ";
+ qPrintable(totalString) << " total " <<
+ qPrintable(internalString) << " internal " <<
+ qPrintable(leavesString) << " leaves ";
QString incomingPacketsString = locale.toString((uint)stats.getIncomingPackets());
QString incomingBytesString = locale.toString((uint)stats.getIncomingBytes());
QString incomingWastedBytesString = locale.toString((uint)stats.getIncomingWastedBytes());
QString incomingOutOfOrderString = locale.toString((uint)stats.getIncomingOutOfOrder());
+ QString incomingLateString = locale.toString((uint)stats.getIncomingLate());
+ QString incomingReallyLateString = locale.toString((uint)stats.getIncomingReallyLate());
+ QString incomingEarlyString = locale.toString((uint)stats.getIncomingEarly());
QString incomingLikelyLostString = locale.toString((uint)stats.getIncomingLikelyLost());
+ QString incomingRecovered = locale.toString((uint)stats.getIncomingRecovered());
+ QString incomingDuplicateString = locale.toString((uint)stats.getIncomingPossibleDuplicate());
int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC;
QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage());
QString incomingPingTimeString = locale.toString(node->getPingMs());
QString incomingClockSkewString = locale.toString(clockSkewInMS);
- serverDetails << "
" << "Incoming Packets: " <<
- incomingPacketsString.toLocal8Bit().constData() <<
- " Out of Order: " << incomingOutOfOrderString.toLocal8Bit().constData() <<
- " Likely Lost: " << incomingLikelyLostString.toLocal8Bit().constData();
+ serverDetails << "
" << "Incoming Packets: " << qPrintable(incomingPacketsString) <<
+ "/ Lost: " << qPrintable(incomingLikelyLostString) <<
+ "/ Recovered: " << qPrintable(incomingRecovered);
+
+ serverDetails << "
" << " Out of Order: " << qPrintable(incomingOutOfOrderString) <<
+ "/ Early: " << qPrintable(incomingEarlyString) <<
+ "/ Late: " << qPrintable(incomingLateString) <<
+ "/ Really Late: " << qPrintable(incomingReallyLateString) <<
+ "/ Duplicate: " << qPrintable(incomingDuplicateString);
serverDetails << "
" <<
- " Average Flight Time: " << incomingFlightTimeString.toLocal8Bit().constData() << " msecs";
+ " Average Flight Time: " << qPrintable(incomingFlightTimeString) << " msecs";
serverDetails << "
" <<
- " Average Ping Time: " << incomingPingTimeString.toLocal8Bit().constData() << " msecs";
+ " Average Ping Time: " << qPrintable(incomingPingTimeString) << " msecs";
serverDetails << "
" <<
- " Average Clock Skew: " << incomingClockSkewString.toLocal8Bit().constData() << " msecs";
-
+ " Average Clock Skew: " << qPrintable(incomingClockSkewString) << " msecs";
+
serverDetails << "
" << "Incoming" <<
- " Bytes: " << incomingBytesString.toLocal8Bit().constData() <<
- " Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData();
+ " Bytes: " << qPrintable(incomingBytesString) <<
+ " Wasted Bytes: " << qPrintable(incomingWastedBytesString);
serverDetails << extraDetails.str();
if (_extraServerDetails[serverCount-1] == MORE) {
diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui
index 199d9b42e3..18c9b3814a 100644
--- a/interface/ui/chatWindow.ui
+++ b/interface/ui/chatWindow.ui
@@ -67,7 +67,7 @@
-
- margin-top: 12px;
+ margin-top: 12px; font-family: Helvetica, Arial, sans-serif;
Qt::ScrollBarAlwaysOff
@@ -121,6 +121,9 @@
0
+
+ font-family: Helvetica, Arial, sans-serif;
+
Qt::ScrollBarAlwaysOff
diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp
index f85ed7f487..4c8ed8c9f6 100644
--- a/libraries/octree/src/Octree.cpp
+++ b/libraries/octree/src/Octree.cpp
@@ -15,8 +15,6 @@
#include
#include // to load voxels from file
-#include
-
#include
#include "CoverageMap.h"
diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp
index 794884334f..e42fe17df0 100644
--- a/libraries/octree/src/OctreeSceneStats.cpp
+++ b/libraries/octree/src/OctreeSceneStats.cpp
@@ -18,20 +18,32 @@
#include "OctreeSceneStats.h"
+const uint16_t MAX_MISSING_SEQUENCE = 100; /// how many items in our _missingSequenceNumbers before we start to prune them
+const uint16_t MAX_MISSING_SEQUENCE_OLD_AGE = 1000; /// age we allow items in _missingSequenceNumbers to be before pruning
+
+
const int samples = 100;
OctreeSceneStats::OctreeSceneStats() :
_isReadyToSend(false),
_isStarted(false),
_lastFullElapsed(0),
+ _lastFullTotalEncodeTime(0),
+ _lastFullTotalPackets(0),
+ _lastFullTotalBytes(0),
+
_elapsedAverage(samples),
_bitsPerOctreeAverage(samples),
- _lastFullTotalEncodeTime(0),
_incomingPacket(0),
_incomingBytes(0),
_incomingWastedBytes(0),
_incomingLastSequence(0),
- _incomingOutOfOrder(0),
_incomingLikelyLost(0),
+ _incomingRecovered(0),
+ _incomingEarly(0),
+ _incomingLate(0),
+ _incomingReallyLate(0),
+ _incomingPossibleDuplicate(0),
+ _missingSequenceNumbers(),
_incomingFlightTimeAverage(samples),
_jurisdictionRoot(NULL)
{
@@ -53,8 +65,10 @@ OctreeSceneStats& OctreeSceneStats::operator=(const OctreeSceneStats& other) {
void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) {
_totalEncodeTime = other._totalEncodeTime;
_elapsed = other._elapsed;
- _lastFullTotalEncodeTime = other._lastFullTotalEncodeTime;
_lastFullElapsed = other._lastFullElapsed;
+ _lastFullTotalEncodeTime = other._lastFullTotalEncodeTime;
+ _lastFullTotalPackets = other._lastFullTotalPackets;
+ _lastFullTotalBytes = other._lastFullTotalBytes;
_encodeStart = other._encodeStart;
_packets = other._packets;
@@ -134,8 +148,14 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) {
_incomingBytes = other._incomingBytes;
_incomingWastedBytes = other._incomingWastedBytes;
_incomingLastSequence = other._incomingLastSequence;
- _incomingOutOfOrder = other._incomingOutOfOrder;
_incomingLikelyLost = other._incomingLikelyLost;
+ _incomingRecovered = other._incomingRecovered;
+ _incomingEarly = other._incomingEarly;
+ _incomingLate = other._incomingLate;
+ _incomingReallyLate = other._incomingReallyLate;
+ _incomingPossibleDuplicate = other._incomingPossibleDuplicate;
+
+ _missingSequenceNumbers = other._missingSequenceNumbers;
}
@@ -493,12 +513,6 @@ int OctreeSceneStats::unpackFromMessage(const unsigned char* sourceBuffer, int a
memcpy(&_isFullScene, sourceBuffer, sizeof(_isFullScene));
sourceBuffer += sizeof(_isFullScene);
-
- if (_isFullScene) {
- _lastFullElapsed = _elapsed;
- _lastFullTotalEncodeTime = _totalEncodeTime;
- }
-
memcpy(&_isMoving, sourceBuffer, sizeof(_isMoving));
sourceBuffer += sizeof(_isMoving);
memcpy(&_packets, sourceBuffer, sizeof(_packets));
@@ -506,6 +520,13 @@ int OctreeSceneStats::unpackFromMessage(const unsigned char* sourceBuffer, int a
memcpy(&_bytes, sourceBuffer, sizeof(_bytes));
sourceBuffer += sizeof(_bytes);
+ if (_isFullScene) {
+ _lastFullElapsed = _elapsed;
+ _lastFullTotalEncodeTime = _totalEncodeTime;
+ _lastFullTotalPackets = _packets;
+ _lastFullTotalBytes = _bytes;
+ }
+
memcpy(&_totalInternal, sourceBuffer, sizeof(_totalInternal));
sourceBuffer += sizeof(_totalInternal);
memcpy(&_totalLeaves, sourceBuffer, sizeof(_totalLeaves));
@@ -823,18 +844,95 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
float flightTimeMsecs = flightTime / USECS_PER_MSEC;
_incomingFlightTimeAverage.updateAverage(flightTimeMsecs);
+ // track out of order and possibly lost packets...
+ const bool wantExtraDebugging = false;
+ if (sequence == _incomingLastSequence) {
+ if (wantExtraDebugging) {
+ qDebug() << "last packet duplicate got:" << sequence << "_incomingLastSequence:" << _incomingLastSequence;
+ }
+ } else {
+ OCTREE_PACKET_SEQUENCE expected = _incomingLastSequence+1;
+ if (sequence != expected) {
+ if (wantExtraDebugging) {
+ qDebug() << "out of order... got:" << sequence << "expected:" << expected;
+ }
+
+ // if the sequence is less than our expected, then this might be a packet
+ // that was delayed and so we should find it in our lostSequence list
+ if (sequence < expected) {
+ if (wantExtraDebugging) {
+ qDebug() << "this packet is later than expected...";
+ }
+ if (sequence < std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) {
+ _incomingReallyLate++;
+ } else {
+ _incomingLate++;
+ }
+
+ if (_missingSequenceNumbers.contains(sequence)) {
+ if (wantExtraDebugging) {
+ qDebug() << "found it in _missingSequenceNumbers";
+ }
+ _missingSequenceNumbers.remove(sequence);
+ _incomingLikelyLost--;
+ _incomingRecovered++;
+ } else {
+ // if we're still in our pruning window, and we didn't find it in our missing list,
+ // than this is really unexpected and can probably only happen if the packet was a
+ // duplicate
+ if (sequence >= std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) {
+ if (wantExtraDebugging) {
+ qDebug() << "sequence:" << sequence << "WAS NOT found in _missingSequenceNumbers, and not that old... (expected - MAX_MISSING_SEQUENCE_OLD_AGE):" << (expected - MAX_MISSING_SEQUENCE_OLD_AGE);
+ }
+ _incomingPossibleDuplicate++;
+ }
+ }
+ }
+
+ if (sequence > expected) {
+ if (wantExtraDebugging) {
+ qDebug() << "this packet is earlier than expected...";
+ }
+ _incomingEarly++;
+
+ // hmm... so, we either didn't get some packets, or this guy came early...
+ unsigned int missing = sequence - expected;
+ if (wantExtraDebugging) {
+ qDebug() << ">>>>>>>> missing gap=" << missing;
+ }
+ _incomingLikelyLost += missing;
+ for(unsigned int missingSequence = expected; missingSequence < sequence; missingSequence++) {
+ _missingSequenceNumbers << missingSequence;
+ }
+ }
+ }
+ }
+
+ // only bump the last sequence if it was greater than our previous last sequence, this will keep us from
+ // accidentally going backwards when an out of order (recovered) packet comes in
+ if (sequence > _incomingLastSequence) {
+ _incomingLastSequence = sequence;
+ }
- // detect out of order packets
- if (sequence < _incomingLastSequence) {
- _incomingOutOfOrder++;
+ // do some garbage collecting on our _missingSequenceNumbers
+ if (_missingSequenceNumbers.size() > MAX_MISSING_SEQUENCE) {
+ if (wantExtraDebugging) {
+ qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size();
+ }
+ foreach(unsigned int missingItem, _missingSequenceNumbers) {
+ if (wantExtraDebugging) {
+ qDebug() << "checking item:" << missingItem << "is it in need of pruning?";
+ qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):"
+ << (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE);
+ }
+ if (missingItem <= std::max(0, (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE))) {
+ if (wantExtraDebugging) {
+ qDebug() << "pruning really old missing sequence:" << missingItem;
+ }
+ _missingSequenceNumbers.remove(missingItem);
+ }
+ }
}
-
- // detect likely lost packets
- OCTREE_PACKET_SEQUENCE expected = _incomingLastSequence+1;
- if (sequence > expected) {
- _incomingLikelyLost++;
- }
-
- _incomingLastSequence = sequence;
+
}
diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h
index e106f53589..2b39b3434c 100644
--- a/libraries/octree/src/OctreeSceneStats.h
+++ b/libraries/octree/src/OctreeSceneStats.h
@@ -150,8 +150,10 @@ public:
unsigned long getTotalEncodeTime() const { return _totalEncodeTime; }
unsigned long getElapsedTime() const { return _elapsed; }
- unsigned long getLastFullTotalEncodeTime() const { return _lastFullTotalEncodeTime; }
unsigned long getLastFullElapsedTime() const { return _lastFullElapsed; }
+ unsigned long getLastFullTotalEncodeTime() const { return _lastFullTotalEncodeTime; }
+ unsigned int getLastFullTotalPackets() const { return _lastFullTotalPackets; }
+ unsigned long getLastFullTotalBytes() const { return _lastFullTotalBytes; }
// Used in client implementations to track individual octree packets
void trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec);
@@ -159,8 +161,13 @@ public:
unsigned int getIncomingPackets() const { return _incomingPacket; }
unsigned long getIncomingBytes() const { return _incomingBytes; }
unsigned long getIncomingWastedBytes() const { return _incomingWastedBytes; }
- unsigned int getIncomingOutOfOrder() const { return _incomingOutOfOrder; }
+ unsigned int getIncomingOutOfOrder() const { return _incomingLate + _incomingEarly; }
unsigned int getIncomingLikelyLost() const { return _incomingLikelyLost; }
+ unsigned int getIncomingRecovered() const { return _incomingRecovered; }
+ unsigned int getIncomingEarly() const { return _incomingEarly; }
+ unsigned int getIncomingLate() const { return _incomingLate; }
+ unsigned int getIncomingReallyLate() const { return _incomingReallyLate; }
+ unsigned int getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; }
float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); }
private:
@@ -176,13 +183,16 @@ private:
quint64 _start;
quint64 _end;
quint64 _elapsed;
+
quint64 _lastFullElapsed;
+ quint64 _lastFullTotalEncodeTime;
+ unsigned int _lastFullTotalPackets;
+ unsigned long _lastFullTotalBytes;
SimpleMovingAverage _elapsedAverage;
SimpleMovingAverage _bitsPerOctreeAverage;
quint64 _totalEncodeTime;
- quint64 _lastFullTotalEncodeTime;
quint64 _encodeStart;
// scene octree related data
@@ -251,9 +261,15 @@ private:
unsigned int _incomingPacket;
unsigned long _incomingBytes;
unsigned long _incomingWastedBytes;
- unsigned int _incomingLastSequence;
- unsigned int _incomingOutOfOrder;
- unsigned int _incomingLikelyLost;
+
+ uint16_t _incomingLastSequence; /// last incoming sequence number
+ unsigned int _incomingLikelyLost; /// count of packets likely lost, may be off by _incomingReallyLate count
+ unsigned int _incomingRecovered; /// packets that were late, and we had in our missing list, we consider recovered
+ unsigned int _incomingEarly; /// out of order earlier than expected
+ unsigned int _incomingLate; /// out of order later than expected
+ unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late
+ unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate
+ QSet _missingSequenceNumbers;
SimpleMovingAverage _incomingFlightTimeAverage;
// features related items
diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp
index 4c756c2257..5c48244a39 100644
--- a/libraries/voxels/src/VoxelTree.cpp
+++ b/libraries/voxels/src/VoxelTree.cpp
@@ -8,8 +8,6 @@
#include
-#include
-
#include
#include
#include