mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 15:13:41 +02:00
Merge pull request #1227 from ZappoMan/new_voxel_scene_stats
New voxel scene stats
This commit is contained in:
commit
5c219697bc
10 changed files with 344 additions and 131 deletions
|
@ -3396,20 +3396,91 @@ void Application::displayStats() {
|
|||
sprintf(avatarStats, "Avatar: pos %.3f, %.3f, %.3f, vel %.1f, yaw = %.2f", avatarPos.x, avatarPos.y, avatarPos.z, glm::length(_myAvatar.getVelocity()), _myAvatar.getBodyYaw());
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, avatarStats);
|
||||
|
||||
|
||||
QLocale locale(QLocale::English);
|
||||
Node* avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
|
||||
char avatarMixerStats[200];
|
||||
if (avatarMixer) {
|
||||
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||
} else {
|
||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||
}
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
||||
|
||||
|
||||
// Used for formatting voxel stats details
|
||||
statsVerticalOffset += PELS_PER_LINE; // skip a line for voxels
|
||||
QLocale locale(QLocale::English);
|
||||
std::stringstream voxelStats;
|
||||
voxelStats.precision(4);
|
||||
voxelStats << "Voxels " <<
|
||||
"Max: " << _voxels.getMaxVoxels() / 1000.f << "K " <<
|
||||
"Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K " <<
|
||||
"Written: " << _voxels.getVoxelsWritten() / 1000.f << "K " <<
|
||||
"Abandoned: " << _voxels.getAbandonedVoxels() / 1000.f << "K " <<
|
||||
"Updated: " << _voxels.getVoxelsUpdated() / 1000.f << "K ";
|
||||
|
||||
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
||||
std::stringstream sendingMode("");
|
||||
sendingMode << "Voxel Sending Mode: [";
|
||||
int serverCount = 0;
|
||||
int movingServerCount = 0;
|
||||
unsigned long totalNodes = 0;
|
||||
unsigned long totalInternal = 0;
|
||||
unsigned long totalLeaves = 0;
|
||||
for(NodeToVoxelSceneStatsIterator i = _voxelServerSceneStats.begin(); i != _voxelServerSceneStats.end(); i++) {
|
||||
//const QUuid& uuid = i->first;
|
||||
VoxelSceneStats& stats = i->second;
|
||||
serverCount++;
|
||||
if (serverCount > 1) {
|
||||
sendingMode << ",";
|
||||
}
|
||||
if (stats.isMoving()) {
|
||||
sendingMode << "M";
|
||||
movingServerCount++;
|
||||
} else {
|
||||
sendingMode << "S";
|
||||
}
|
||||
|
||||
// calculate server node totals
|
||||
totalNodes += stats.getTotalVoxels();
|
||||
totalInternal += stats.getTotalInternal();
|
||||
totalLeaves += stats.getTotalLeaves();
|
||||
}
|
||||
if (serverCount == 0) {
|
||||
sendingMode << "---";
|
||||
}
|
||||
sendingMode << "] " << serverCount << " servers";
|
||||
if (movingServerCount > 0) {
|
||||
sendingMode << " <SCENE NOT STABLE>";
|
||||
} else {
|
||||
sendingMode << " <SCENE STABLE>";
|
||||
}
|
||||
|
||||
QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' ');
|
||||
QString serversInternalString = locale.toString((uint)totalInternal);
|
||||
QString serversLeavesString = locale.toString((uint)totalLeaves);
|
||||
|
||||
// Server Voxels
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
"Server Voxels Total: " << serversTotalString.toLocal8Bit().constData() << " / " <<
|
||||
"Internal: " << serversInternalString.toLocal8Bit().constData() << " / " <<
|
||||
"Leaves: " << serversLeavesString.toLocal8Bit().constData() << "";
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
unsigned long localTotal = VoxelNode::getNodeCount();
|
||||
unsigned long localInternal = VoxelNode::getInternalNodeCount();
|
||||
unsigned long localLeaves = VoxelNode::getLeafNodeCount();
|
||||
QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' ');
|
||||
QString localInternalString = locale.toString((uint)localInternal);
|
||||
QString localLeavesString = locale.toString((uint)localLeaves);
|
||||
|
||||
// Local Voxels
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
"Local Voxels Total: " << localTotalString.toLocal8Bit().constData() << " / " <<
|
||||
"Internal: " << localInternalString.toLocal8Bit().constData() << " / " <<
|
||||
"Leaves: " << localLeavesString.toLocal8Bit().constData() << "";
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
// Local Voxel Memory Usage
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
"Voxels Memory Nodes: " << VoxelNode::getTotalMemoryUsage() / 1000000.f << "MB "
|
||||
|
@ -3421,51 +3492,25 @@ void Application::displayStats() {
|
|||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
unsigned long localTotal = VoxelNode::getNodeCount();
|
||||
unsigned long localInternal = VoxelNode::getInternalNodeCount();
|
||||
unsigned long localLeaves = VoxelNode::getLeafNodeCount();
|
||||
QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' ');
|
||||
QString localInternalString = locale.toString((uint)localInternal);
|
||||
QString localLeavesString = locale.toString((uint)localLeaves);
|
||||
|
||||
|
||||
// Voxel Rendering
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
"Local Voxels Total: " << localTotalString.toLocal8Bit().constData() << " / " <<
|
||||
"Internal: " << localInternalString.toLocal8Bit().constData() << " / " <<
|
||||
"Leaves: " << localLeavesString.toLocal8Bit().constData() << "";
|
||||
voxelStats.precision(4);
|
||||
voxelStats << "Voxel Rendering Slots" <<
|
||||
"Max: " << _voxels.getMaxVoxels() / 1000.f << "K " <<
|
||||
"Drawn: " << _voxels.getVoxelsWritten() / 1000.f << "K " <<
|
||||
"Abandoned: " << _voxels.getAbandonedVoxels() / 1000.f << "K ";
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
voxelStats.str("");
|
||||
char* voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_VOXELS);
|
||||
voxelStats << "Voxels Sent from Server: " << voxelDetails;
|
||||
// draw Sending mode AFTER server node stats
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
voxelStats.str("");
|
||||
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ELAPSED);
|
||||
voxelStats << "Scene Send Time from Server: " << voxelDetails;
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 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;
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
voxelStats.str("");
|
||||
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_MODE);
|
||||
voxelStats << "Sending Mode: " << voxelDetails;
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)sendingMode.str().c_str());
|
||||
|
||||
// Incoming packets
|
||||
voxelStats.str("");
|
||||
int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount();
|
||||
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() << "]";
|
||||
|
||||
|
@ -3483,19 +3528,8 @@ void Application::displayStats() {
|
|||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
|
||||
Node *avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
|
||||
char avatarMixerStats[200];
|
||||
|
||||
if (avatarMixer) {
|
||||
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||
} else {
|
||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||
}
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
||||
|
||||
// Leap data
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)LeapManager::statusString().c_str());
|
||||
|
||||
|
@ -4075,6 +4109,10 @@ void Application::domainChanged(QString domain) {
|
|||
|
||||
// reset the environment so that we don't erroneously end up with multiple
|
||||
_environment.resetToDefault();
|
||||
|
||||
// reset our node to stats and node to jurisdiction maps... since these must be changing...
|
||||
_voxelServerJurisdictions.clear();
|
||||
_voxelServerSceneStats.clear();
|
||||
}
|
||||
|
||||
void Application::nodeAdded(Node* node) {
|
||||
|
@ -4101,6 +4139,14 @@ void Application::nodeKilled(Node* node) {
|
|||
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
||||
_voxelFades.push_back(fade);
|
||||
}
|
||||
|
||||
// If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
|
||||
_voxelServerJurisdictions.erase(nodeUUID);
|
||||
}
|
||||
|
||||
// also clean up scene stats for that server
|
||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||
_voxelServerSceneStats.erase(nodeUUID);
|
||||
}
|
||||
} else if (node->getLinkedData() == _lookatTargetAvatar) {
|
||||
_lookatTargetAvatar = NULL;
|
||||
|
@ -4109,19 +4155,43 @@ void Application::nodeKilled(Node* node) {
|
|||
|
||||
int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLength, sockaddr senderAddress) {
|
||||
|
||||
// parse the incoming stats data, and stick it into our averaging stats object for now... even though this
|
||||
// means mixing in stats from potentially multiple servers.
|
||||
int statsMessageLength = _voxelSceneStats.unpackFromMessage(messageData, messageLength);
|
||||
|
||||
// But, also identify the sender, and keep track of the contained jurisdiction root for this server
|
||||
Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress);
|
||||
|
||||
// parse the incoming stats datas stick it in a temporary object for now, while we
|
||||
// determine which server it belongs to
|
||||
VoxelSceneStats temp;
|
||||
int statsMessageLength = temp.unpackFromMessage(messageData, messageLength);
|
||||
|
||||
// quick fix for crash... why would voxelServer be NULL?
|
||||
if (voxelServer) {
|
||||
QUuid nodeUUID = voxelServer->getUUID();
|
||||
|
||||
|
||||
// now that we know the node ID, let's add these stats to the stats for that node...
|
||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||
VoxelSceneStats& oldStats = _voxelServerSceneStats[nodeUUID];
|
||||
|
||||
// this if construct is a little strange because we aren't quite using it yet. But
|
||||
// we want to keep this logic in here for now because we plan to use it soon to determine
|
||||
// additional network optimization states and better rate control
|
||||
if (!oldStats.isMoving() && temp.isMoving()) {
|
||||
// we think we are starting to move
|
||||
_voxelServerSceneStats[nodeUUID].unpackFromMessage(messageData, messageLength);
|
||||
} else if (oldStats.isMoving() && !temp.isMoving()) {
|
||||
// we think we are done moving
|
||||
_voxelServerSceneStats[nodeUUID].unpackFromMessage(messageData, messageLength);
|
||||
} else if (!oldStats.isMoving() && !temp.isMoving()) {
|
||||
// we think we are still not moving
|
||||
} else {
|
||||
// we think we are still moving
|
||||
}
|
||||
|
||||
} else {
|
||||
_voxelServerSceneStats[nodeUUID] = temp;
|
||||
}
|
||||
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(_voxelSceneStats.getJurisdictionRoot(), rootDetails);
|
||||
voxelDetailsForCode(temp.getJurisdictionRoot(), rootDetails);
|
||||
|
||||
// see if this is the first we've heard of this node...
|
||||
if (_voxelServerJurisdictions.find(nodeUUID) == _voxelServerJurisdictions.end()) {
|
||||
|
@ -4142,7 +4212,7 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng
|
|||
// but VoxelSceneStats thinks it's just returning a reference to it's contents. So we need to make a copy of the
|
||||
// details from the VoxelSceneStats to construct the JurisdictionMap
|
||||
JurisdictionMap jurisdictionMap;
|
||||
jurisdictionMap.copyContents(_voxelSceneStats.getJurisdictionRoot(), _voxelSceneStats.getJurisdictionEndNodes());
|
||||
jurisdictionMap.copyContents(temp.getJurisdictionRoot(), temp.getJurisdictionEndNodes());
|
||||
_voxelServerJurisdictions[nodeUUID] = jurisdictionMap;
|
||||
}
|
||||
return statsMessageLength;
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
QSettings* getSettings() { return _settings; }
|
||||
Swatch* getSwatch() { return &_swatch; }
|
||||
QMainWindow* getWindow() { return _window; }
|
||||
VoxelSceneStats* getVoxelSceneStats() { return &_voxelSceneStats; }
|
||||
NodeToVoxelSceneStats* getVoxelSceneStats() { return &_voxelServerSceneStats; }
|
||||
|
||||
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
||||
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||
|
@ -448,10 +448,10 @@ private:
|
|||
|
||||
PieMenu _pieMenu;
|
||||
|
||||
VoxelSceneStats _voxelSceneStats;
|
||||
int parseVoxelStats(unsigned char* messageData, ssize_t messageLength, sockaddr senderAddress);
|
||||
|
||||
NodeToJurisdictionMap _voxelServerJurisdictions;
|
||||
NodeToVoxelSceneStats _voxelServerSceneStats;
|
||||
|
||||
std::vector<VoxelFade> _voxelFades;
|
||||
};
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#include <QLabel>
|
||||
#include <QSlider>
|
||||
|
||||
#include <VoxelSceneStats.h>
|
||||
|
||||
class LodToolsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -14,46 +14,72 @@
|
|||
|
||||
#include <VoxelSceneStats.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "ui/VoxelStatsDialog.h"
|
||||
|
||||
|
||||
VoxelStatsDialog::VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model) :
|
||||
VoxelStatsDialog::VoxelStatsDialog(QWidget* parent, NodeToVoxelSceneStats* model) :
|
||||
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint),
|
||||
_model(model) {
|
||||
|
||||
_statCount = 0;
|
||||
|
||||
char strBuf[64];
|
||||
for (int i = 0; i < MAX_STATS; i++) {
|
||||
_labels[i] = NULL;
|
||||
}
|
||||
|
||||
this->setWindowTitle("Voxel Statistics");
|
||||
|
||||
// Create layouter
|
||||
QFormLayout* form = new QFormLayout();
|
||||
this->QDialog::setLayout(form);
|
||||
_form = new QFormLayout();
|
||||
this->QDialog::setLayout(_form);
|
||||
|
||||
// Setup labels
|
||||
for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; i++) {
|
||||
VoxelSceneStats::Item item = (VoxelSceneStats::Item)(i);
|
||||
VoxelSceneStats::ItemInfo& itemInfo = _model->getItemInfo(item);
|
||||
QLabel* label = _labels[item] = new QLabel();
|
||||
// Setup stat items
|
||||
_serverVoxels = AddStatItem("Voxels on Servers", GREENISH);
|
||||
_localVoxels = AddStatItem("Local Voxels", YELLOWISH);
|
||||
_localVoxelsMemory = AddStatItem("Voxels Memory", GREYISH);
|
||||
_voxelsRendered = AddStatItem("Voxels Rendered", GREENISH);
|
||||
_sendingMode = AddStatItem("Sending Mode", YELLOWISH);
|
||||
|
||||
// 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;
|
||||
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);
|
||||
|
||||
const int STATS_LABEL_WIDTH = 550;
|
||||
label->setFixedWidth(STATS_LABEL_WIDTH);
|
||||
/** NOT YET READY
|
||||
VoxelSceneStats temp;
|
||||
for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; i++) {
|
||||
VoxelSceneStats::Item item = (VoxelSceneStats::Item)(i);
|
||||
VoxelSceneStats::ItemInfo& itemInfo = temp.getItemInfo(item);
|
||||
AddStatItem(itemInfo.caption, itemInfo.colorRGBA);
|
||||
}
|
||||
**/
|
||||
}
|
||||
|
||||
snprintf(strBuf, sizeof(strBuf), " %s:", itemInfo.caption);
|
||||
form->addRow(strBuf, label);
|
||||
}
|
||||
int VoxelStatsDialog::AddStatItem(const char* caption, unsigned colorRGBA) {
|
||||
char strBuf[64];
|
||||
const int STATS_LABEL_WIDTH = 550;
|
||||
|
||||
_statCount++; // increment our current stat count
|
||||
|
||||
QLabel* label = _labels[_statCount] = new QLabel();
|
||||
|
||||
// Set foreground color to 62.5% brightness of the meter (otherwise will be hard to read on the bright background)
|
||||
QPalette palette = label->palette();
|
||||
|
||||
// This goofiness came from the bandwidth meter code, it basically stores a color in an unsigned and extracts it
|
||||
unsigned rgb = colorRGBA >> 8;
|
||||
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);
|
||||
|
||||
label->setFixedWidth(STATS_LABEL_WIDTH);
|
||||
|
||||
snprintf(strBuf, sizeof(strBuf), " %s:", caption);
|
||||
_form->addRow(strBuf, label);
|
||||
|
||||
return _statCount;
|
||||
}
|
||||
|
||||
VoxelStatsDialog::~VoxelStatsDialog() {
|
||||
for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; ++i) {
|
||||
for (int i = 0; i < _statCount; i++) {
|
||||
delete _labels[i];
|
||||
}
|
||||
}
|
||||
|
@ -61,16 +87,104 @@ VoxelStatsDialog::~VoxelStatsDialog() {
|
|||
void VoxelStatsDialog::paintEvent(QPaintEvent* event) {
|
||||
|
||||
// Update labels
|
||||
char strBuf[256];
|
||||
for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; i++) {
|
||||
VoxelSceneStats::Item item = (VoxelSceneStats::Item)(i);
|
||||
QLabel* label = _labels[item];
|
||||
snprintf(strBuf, sizeof(strBuf), "%s", _model->getItemValue(item));
|
||||
label->setText(strBuf);
|
||||
|
||||
VoxelSystem* voxels = Application::getInstance()->getVoxels();
|
||||
QLabel* label;
|
||||
QLocale locale(QLocale::English);
|
||||
std::stringstream statsValue;
|
||||
statsValue.precision(4);
|
||||
|
||||
// Voxels Rendered
|
||||
label = _labels[_voxelsRendered];
|
||||
statsValue << "Max: " << voxels->getMaxVoxels() / 1000.f << "K " <<
|
||||
"Drawn: " << voxels->getVoxelsWritten() / 1000.f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.f << "K " <<
|
||||
"ReadBuffer: " << voxels->getVoxelsRendered() / 1000.f << "K " <<
|
||||
"Changed: " << voxels->getVoxelsUpdated() / 1000.f << "K ";
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
// Voxels Memory Usage
|
||||
label = _labels[_localVoxelsMemory];
|
||||
statsValue.str("");
|
||||
statsValue <<
|
||||
"Nodes RAM: " << VoxelNode::getTotalMemoryUsage() / 1000000.f << "MB "
|
||||
"Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.f << "MB " <<
|
||||
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.f << "MB ";
|
||||
if (voxels->hasVoxelMemoryUsageGPU()) {
|
||||
statsValue << "GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.f << "MB ";
|
||||
}
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
// Local Voxels
|
||||
label = _labels[_localVoxels];
|
||||
unsigned long localTotal = VoxelNode::getNodeCount();
|
||||
unsigned long localInternal = VoxelNode::getInternalNodeCount();
|
||||
unsigned long localLeaves = VoxelNode::getLeafNodeCount();
|
||||
QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' ');
|
||||
QString localInternalString = locale.toString((uint)localInternal);
|
||||
QString localLeavesString = locale.toString((uint)localLeaves);
|
||||
|
||||
statsValue.str("");
|
||||
statsValue <<
|
||||
"Total: " << localTotalString.toLocal8Bit().constData() << " / " <<
|
||||
"Internal: " << localInternalString.toLocal8Bit().constData() << " / " <<
|
||||
"Leaves: " << localLeavesString.toLocal8Bit().constData() << "";
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
// iterate all the current voxel stats, and list their sending modes, total their voxels, etc...
|
||||
std::stringstream sendingMode("");
|
||||
|
||||
int serverCount = 0;
|
||||
int movingServerCount = 0;
|
||||
unsigned long totalNodes = 0;
|
||||
unsigned long totalInternal = 0;
|
||||
unsigned long totalLeaves = 0;
|
||||
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getVoxelSceneStats();
|
||||
for(NodeToVoxelSceneStatsIterator i = sceneStats->begin(); i != sceneStats->end(); i++) {
|
||||
//const QUuid& uuid = i->first;
|
||||
VoxelSceneStats& stats = i->second;
|
||||
serverCount++;
|
||||
|
||||
// calculate server node totals
|
||||
totalNodes += stats.getTotalVoxels();
|
||||
totalInternal += stats.getTotalInternal();
|
||||
totalLeaves += stats.getTotalLeaves();
|
||||
|
||||
// Sending mode
|
||||
if (serverCount > 1) {
|
||||
sendingMode << ",";
|
||||
}
|
||||
if (stats.isMoving()) {
|
||||
sendingMode << "M";
|
||||
movingServerCount++;
|
||||
} else {
|
||||
sendingMode << "S";
|
||||
}
|
||||
}
|
||||
sendingMode << " - " << serverCount << " servers";
|
||||
if (movingServerCount > 0) {
|
||||
sendingMode << " <SCENE NOT STABLE>";
|
||||
} else {
|
||||
sendingMode << " <SCENE STABLE>";
|
||||
}
|
||||
|
||||
label = _labels[_sendingMode];
|
||||
label->setText(sendingMode.str().c_str());
|
||||
|
||||
// Server Voxels
|
||||
QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' ');
|
||||
QString serversInternalString = locale.toString((uint)totalInternal);
|
||||
QString serversLeavesString = locale.toString((uint)totalLeaves);
|
||||
label = _labels[_serverVoxels];
|
||||
statsValue.str("");
|
||||
statsValue <<
|
||||
"Total: " << serversTotalString.toLocal8Bit().constData() << " / " <<
|
||||
"Internal: " << serversInternalString.toLocal8Bit().constData() << " / " <<
|
||||
"Leaves: " << serversLeavesString.toLocal8Bit().constData() << "";
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
this->QDialog::paintEvent(event);
|
||||
this->setFixedSize(this->width(), this->height());
|
||||
//this->setFixedSize(this->width(), this->height());
|
||||
}
|
||||
|
||||
void VoxelStatsDialog::reject() {
|
||||
|
|
|
@ -10,15 +10,18 @@
|
|||
#define __hifi__VoxelStatsDialog__
|
||||
|
||||
#include <QDialog>
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include <VoxelSceneStats.h>
|
||||
|
||||
#define MAX_STATS 40
|
||||
|
||||
class VoxelStatsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Sets up the UI
|
||||
VoxelStatsDialog(QWidget* parent, VoxelSceneStats* model);
|
||||
VoxelStatsDialog(QWidget* parent, NodeToVoxelSceneStats* model);
|
||||
~VoxelStatsDialog();
|
||||
|
||||
signals:
|
||||
|
@ -34,9 +37,19 @@ protected:
|
|||
// Emits a 'closed' signal when this dialog is closed.
|
||||
void closeEvent(QCloseEvent*);
|
||||
|
||||
int AddStatItem(const char* caption, unsigned colorRGBA);
|
||||
|
||||
private:
|
||||
QLabel* _labels[VoxelSceneStats::ITEM_COUNT];
|
||||
VoxelSceneStats* _model;
|
||||
QFormLayout* _form;
|
||||
QLabel* _labels[MAX_STATS];
|
||||
NodeToVoxelSceneStats* _model;
|
||||
int _statCount;
|
||||
|
||||
int _sendingMode;
|
||||
int _serverVoxels;
|
||||
int _localVoxels;
|
||||
int _localVoxelsMemory;
|
||||
int _voxelsRendered;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__VoxelStatsDialog__) */
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
class SimpleMovingAverage {
|
||||
public:
|
||||
SimpleMovingAverage(int numSamplesToAverage);
|
||||
SimpleMovingAverage(int numSamplesToAverage = 100);
|
||||
|
||||
int updateAverage(float sample);
|
||||
void reset();
|
||||
|
@ -30,8 +30,8 @@ private:
|
|||
float _average;
|
||||
float _eventDeltaAverage;
|
||||
|
||||
const float WEIGHTING;
|
||||
const float ONE_MINUS_WEIGHTING;
|
||||
float WEIGHTING;
|
||||
float ONE_MINUS_WEIGHTING;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Stats__) */
|
||||
|
|
|
@ -103,6 +103,7 @@ void VoxelNodeData::resetVoxelPacket() {
|
|||
// the clients requested color state.
|
||||
_currentPacketIsColor = (LOW_RES_MONO && getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor();
|
||||
PACKET_TYPE voxelPacketType = _currentPacketIsColor ? PACKET_TYPE_VOXEL_DATA : PACKET_TYPE_VOXEL_DATA_MONOCHROME;
|
||||
|
||||
int numBytesPacketHeader = populateTypeAndVersion(_voxelPacket, voxelPacketType);
|
||||
_voxelPacketAt = _voxelPacket + numBytesPacketHeader;
|
||||
_voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE - numBytesPacketHeader;
|
||||
|
|
|
@ -107,6 +107,7 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
|
|||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(),
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
}
|
||||
nodeData->stats.markAsSent();
|
||||
} else {
|
||||
// just send the voxel packet
|
||||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(),
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
|
@ -521,30 +524,26 @@ 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" , 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 },
|
||||
{ "Elapsed" , GREENISH , 2 , "Elapsed,fps" },
|
||||
{ "Encode" , YELLOWISH , 2 , "Time,fps" },
|
||||
{ "Network" , GREYISH , 3 , "Packets,Bytes,KBPS" },
|
||||
{ "Voxels on Server" , GREENISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Voxels Sent" , YELLOWISH , 5 , "Total,Bits/Voxel,Avg Bits/Voxel,Internal,Leaves" },
|
||||
{ "Colors Sent" , GREYISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Bitmasks Sent" , GREENISH , 3 , "Colors,Exists,In Packets" },
|
||||
{ "Traversed" , YELLOWISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Skipped - Total" , GREYISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Skipped - Distance" , GREENISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Skipped - Out of View", YELLOWISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Skipped - Was in View", GREYISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Skipped - No Change" , GREENISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Skipped - Occluded" , YELLOWISH , 3 , "Total,Internal,Leaves" },
|
||||
{ "Didn't fit in packet" , GREYISH , 4 , "Total,Internal,Leaves,Removed" },
|
||||
{ "Mode" , GREENISH , 4 , "Moving,Stationary,Partial,Full" },
|
||||
};
|
||||
|
||||
char* VoxelSceneStats::getItemValue(Item item) {
|
||||
const char* VoxelSceneStats::getItemValue(Item item) {
|
||||
const uint64_t USECS_PER_SECOND = 1000 * 1000;
|
||||
int calcFPS, calcAverageFPS, calculatedKBPS;
|
||||
switch(item) {
|
||||
|
@ -651,3 +650,4 @@ char* VoxelSceneStats::getItemValue(Item item) {
|
|||
return _itemValueBuffer;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#include <NodeList.h>
|
||||
#include "JurisdictionMap.h"
|
||||
|
||||
#define GREENISH 0x40ff40d0
|
||||
#define YELLOWISH 0xffef40c0
|
||||
#define GREYISH 0xd0d0d0a0
|
||||
|
||||
class VoxelNode;
|
||||
|
||||
/// Collects statistics for calculating and sending a scene from a voxel server to an interface client
|
||||
|
@ -114,8 +118,10 @@ public:
|
|||
|
||||
/// Meta information about each stats item
|
||||
struct ItemInfo {
|
||||
char const* const caption;
|
||||
unsigned colorRGBA;
|
||||
char const* const caption;
|
||||
unsigned colorRGBA;
|
||||
int detailsCount;
|
||||
const char* detailsLabels;
|
||||
};
|
||||
|
||||
/// Returns details about items tracked by VoxelSceneStats
|
||||
|
@ -124,14 +130,19 @@ public:
|
|||
|
||||
/// Returns a UI formatted value of an item tracked by VoxelSceneStats
|
||||
/// \param Item item The item from the stats you're interested in.
|
||||
char* getItemValue(Item item);
|
||||
|
||||
const char* getItemValue(Item item);
|
||||
|
||||
/// Returns OctCode for root node of the jurisdiction of this particular voxel server
|
||||
unsigned char* getJurisdictionRoot() const { return _jurisdictionRoot; }
|
||||
|
||||
/// Returns list of OctCodes for end nodes of the jurisdiction of this particular voxel server
|
||||
const std::vector<unsigned char*>& getJurisdictionEndNodes() const { return _jurisdictionEndNodes; }
|
||||
|
||||
bool isMoving() const { return _isMoving; };
|
||||
unsigned long getTotalVoxels() const { return _totalVoxels; }
|
||||
unsigned long getTotalInternal() const { return _totalInternal; }
|
||||
unsigned long getTotalLeaves() const { return _totalLeaves; }
|
||||
|
||||
private:
|
||||
bool _isReadyToSend;
|
||||
unsigned char _statsMessage[MAX_PACKET_SIZE];
|
||||
|
@ -224,4 +235,9 @@ private:
|
|||
std::vector<unsigned char*> _jurisdictionEndNodes;
|
||||
};
|
||||
|
||||
/// Map between node IDs and their reported VoxelSceneStats. Typically used by classes that need to know which nodes sent
|
||||
/// which voxel stats
|
||||
typedef std::map<QUuid, VoxelSceneStats> NodeToVoxelSceneStats;
|
||||
typedef std::map<QUuid, VoxelSceneStats>::iterator NodeToVoxelSceneStatsIterator;
|
||||
|
||||
#endif /* defined(__hifi__VoxelSceneStats__) */
|
||||
|
|
Loading…
Reference in a new issue