mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 10:19:06 +02:00
Stats variable width for panels
This commit is contained in:
parent
c3430b8e45
commit
5fe59acb87
4 changed files with 525 additions and 415 deletions
|
@ -76,6 +76,7 @@
|
||||||
#include "ui/TextRenderer.h"
|
#include "ui/TextRenderer.h"
|
||||||
#include "InfoView.h"
|
#include "InfoView.h"
|
||||||
#include "ui/Snapshot.h"
|
#include "ui/Snapshot.h"
|
||||||
|
#include "ui/Stats.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -105,8 +106,6 @@ const float MIRROR_FIELD_OF_VIEW = 30.0f;
|
||||||
const QString CHECK_VERSION_URL = "http://highfidelity.io/latestVersion.xml";
|
const QString CHECK_VERSION_URL = "http://highfidelity.io/latestVersion.xml";
|
||||||
const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";
|
const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";
|
||||||
|
|
||||||
const int STATS_PELS_PER_LINE = 20;
|
|
||||||
|
|
||||||
const QString CUSTOM_URL_SCHEME = "hifi:";
|
const QString CUSTOM_URL_SCHEME = "hifi:";
|
||||||
|
|
||||||
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
|
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
|
||||||
|
@ -132,7 +131,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
QApplication(argc, argv),
|
QApplication(argc, argv),
|
||||||
_window(new QMainWindow(desktop())),
|
_window(new QMainWindow(desktop())),
|
||||||
_glWidget(new GLCanvas()),
|
_glWidget(new GLCanvas()),
|
||||||
_statsExpanded(false),
|
|
||||||
_nodeThread(new QThread(this)),
|
_nodeThread(new QThread(this)),
|
||||||
_datagramProcessor(),
|
_datagramProcessor(),
|
||||||
_frameCount(0),
|
_frameCount(0),
|
||||||
|
@ -162,8 +160,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
_voxelHideShowThread(&_voxels),
|
_voxelHideShowThread(&_voxels),
|
||||||
_packetsPerSecond(0),
|
_packetsPerSecond(0),
|
||||||
_bytesPerSecond(0),
|
_bytesPerSecond(0),
|
||||||
_recentMaxPackets(0),
|
|
||||||
_resetRecentMaxPacketsSoon(true),
|
|
||||||
_logger(new FileLogger(this))
|
_logger(new FileLogger(this))
|
||||||
{
|
{
|
||||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||||
|
@ -594,6 +590,8 @@ void Application::resizeGL(int width, int height) {
|
||||||
|
|
||||||
updateProjectionMatrix();
|
updateProjectionMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
|
Stats::getInstance()->resetWidthOnResizeGL(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateProjectionMatrix() {
|
void Application::updateProjectionMatrix() {
|
||||||
|
@ -1053,8 +1051,12 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
_mousePressed = false;
|
_mousePressed = false;
|
||||||
checkBandwidthMeterClick();
|
checkBandwidthMeterClick();
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||||
checkStatsClick();
|
int horizontalOffset = 0;
|
||||||
}
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
||||||
|
horizontalOffset = MIRROR_VIEW_WIDTH;
|
||||||
|
}
|
||||||
|
Stats::getInstance()->checkClick(_mouseX, _mouseY, _mouseDragStartedX, _mouseDragStartedY, horizontalOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2486,11 +2488,17 @@ void Application::displayOverlay() {
|
||||||
glPointSize(1.0f);
|
glPointSize(1.0f);
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||||
|
int horizontalOffset = 0;
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
||||||
|
// mirror is enabled, let's set horizontal offset to give stats some margin
|
||||||
|
horizontalOffset += MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2;
|
||||||
|
}
|
||||||
|
int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount();
|
||||||
// Onscreen text about position, servers, etc
|
// Onscreen text about position, servers, etc
|
||||||
displayStats();
|
Stats::getInstance()->display(WHITE_TEXT, horizontalOffset, _fps, _packetsPerSecond, _bytesPerSecond, voxelPacketsToProcess);
|
||||||
// Bandwidth meter
|
// Bandwidth meter
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) {
|
||||||
displayStatsBackground(0x33333399, _glWidget->width() - 296, _glWidget->height() - 68, 296, 68);
|
Stats::drawBackground(0x33333399, _glWidget->width() - 296, _glWidget->height() - 68, 296, 68);
|
||||||
_bandwidthMeter.render(_glWidget->width(), _glWidget->height());
|
_bandwidthMeter.render(_glWidget->width(), _glWidget->height());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2512,404 +2520,6 @@ void Application::displayOverlay() {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
// translucent background box that makes stats more readable
|
|
||||||
void Application::displayStatsBackground(unsigned int rgba, int x, int y, int width, int height) {
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glColor4f(((rgba >> 24) & 0xff) / 255.0f,
|
|
||||||
((rgba >> 16) & 0xff) / 255.0f,
|
|
||||||
((rgba >> 8) & 0xff) / 255.0f,
|
|
||||||
(rgba & 0xff) / 255.0f);
|
|
||||||
glVertex3f(x, y, 0);
|
|
||||||
glVertex3f(x + width, y, 0);
|
|
||||||
glVertex3f(x + width, y + height, 0);
|
|
||||||
glVertex3f(x , y + height, 0);
|
|
||||||
glEnd();
|
|
||||||
glColor4f(1, 1, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// display expanded or contracted stats
|
|
||||||
|
|
||||||
void Application::displayStats() {
|
|
||||||
unsigned int backgroundColor = 0x33333399;
|
|
||||||
int verticalOffset = 0, horizontalOffset = 0, lines = 0;
|
|
||||||
bool mirrorEnabled = Menu::getInstance()->isOptionChecked(MenuOption::Mirror);
|
|
||||||
|
|
||||||
QLocale locale(QLocale::English);
|
|
||||||
std::stringstream voxelStats;
|
|
||||||
|
|
||||||
glPointSize(1.0f);
|
|
||||||
|
|
||||||
// we need to take one avatar out so we don't include ourselves
|
|
||||||
int totalAvatars = _avatarManager.size() - 1;
|
|
||||||
int totalServers = NodeList::getInstance()->size();
|
|
||||||
|
|
||||||
if (mirrorEnabled) {
|
|
||||||
horizontalOffset += MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines = _statsExpanded ? 5 : 3;
|
|
||||||
displayStatsBackground(backgroundColor, horizontalOffset, 0, 165, lines * STATS_PELS_PER_LINE + 10);
|
|
||||||
horizontalOffset += 5;
|
|
||||||
|
|
||||||
char serverNodes[30];
|
|
||||||
sprintf(serverNodes, "Servers: %d", totalServers);
|
|
||||||
char avatarNodes[30];
|
|
||||||
sprintf(avatarNodes, "Avatars: %d", totalAvatars);
|
|
||||||
char framesPerSecond[30];
|
|
||||||
sprintf(framesPerSecond, "Framerate: %3.0f FPS", _fps);
|
|
||||||
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, serverNodes, WHITE_TEXT);
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarNodes, WHITE_TEXT);
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, framesPerSecond, WHITE_TEXT);
|
|
||||||
|
|
||||||
if (_statsExpanded) {
|
|
||||||
char packetsPerSecond[30];
|
|
||||||
sprintf(packetsPerSecond, "Pkts/sec: %d", _packetsPerSecond);
|
|
||||||
char averageMegabitsPerSecond[30];
|
|
||||||
sprintf(averageMegabitsPerSecond, "Mbps: %3.2f", (float)_bytesPerSecond * 8.f / 1000000.f);
|
|
||||||
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, packetsPerSecond, WHITE_TEXT);
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, averageMegabitsPerSecond, WHITE_TEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
verticalOffset = 0;
|
|
||||||
horizontalOffset += 161;
|
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
|
|
||||||
int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0;
|
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
|
||||||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
|
||||||
SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
|
||||||
|
|
||||||
pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0;
|
|
||||||
pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0;
|
|
||||||
|
|
||||||
// Now handle voxel servers, since there could be more than one, we average their ping times
|
|
||||||
unsigned long totalPingVoxel = 0;
|
|
||||||
int voxelServerCount = 0;
|
|
||||||
|
|
||||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
|
||||||
if (node->getType() == NodeType::VoxelServer) {
|
|
||||||
totalPingVoxel += node->getPingMs();
|
|
||||||
voxelServerCount++;
|
|
||||||
if (pingVoxelMax < node->getPingMs()) {
|
|
||||||
pingVoxelMax = node->getPingMs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (voxelServerCount) {
|
|
||||||
pingVoxel = totalPingVoxel/voxelServerCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines = _statsExpanded ? 4 : 3;
|
|
||||||
displayStatsBackground(backgroundColor, horizontalOffset, 0, 175, lines * STATS_PELS_PER_LINE + 10);
|
|
||||||
horizontalOffset += 5;
|
|
||||||
|
|
||||||
char audioJitter[30];
|
|
||||||
sprintf(audioJitter,
|
|
||||||
"Buffer msecs %.1f",
|
|
||||||
(float) (_audio.getNetworkBufferLengthSamplesPerChannel() + (float) _audio.getJitterBufferSamples()) /
|
|
||||||
(float)_audio.getNetworkSampleRate() * 1000.f);
|
|
||||||
drawText(30, _glWidget->height() - 22, 0.10f, 0.f, 2.f, audioJitter, WHITE_TEXT);
|
|
||||||
|
|
||||||
|
|
||||||
char audioPing[30];
|
|
||||||
sprintf(audioPing, "Audio ping: %d", pingAudio);
|
|
||||||
|
|
||||||
|
|
||||||
char avatarPing[30];
|
|
||||||
sprintf(avatarPing, "Avatar ping: %d", pingAvatar);
|
|
||||||
char voxelAvgPing[30];
|
|
||||||
sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel);
|
|
||||||
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, audioPing, WHITE_TEXT);
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPing, WHITE_TEXT);
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelAvgPing, WHITE_TEXT);
|
|
||||||
|
|
||||||
if (_statsExpanded) {
|
|
||||||
char voxelMaxPing[30];
|
|
||||||
sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax);
|
|
||||||
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelMaxPing, WHITE_TEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
verticalOffset = 0;
|
|
||||||
horizontalOffset += 171;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 avatarPos = _myAvatar->getPosition();
|
|
||||||
|
|
||||||
lines = _statsExpanded ? 4 : 3;
|
|
||||||
displayStatsBackground(backgroundColor, horizontalOffset, 0, _glWidget->width() - (mirrorEnabled ? 301 : 411) - horizontalOffset, lines * STATS_PELS_PER_LINE + 10);
|
|
||||||
horizontalOffset += 5;
|
|
||||||
|
|
||||||
char avatarPosition[200];
|
|
||||||
if (mirrorEnabled) {
|
|
||||||
// shorthand formatting
|
|
||||||
sprintf(avatarPosition, "Pos: %.0f,%.0f,%.0f", avatarPos.x, avatarPos.y, avatarPos.z);
|
|
||||||
} else {
|
|
||||||
// longhand way
|
|
||||||
sprintf(avatarPosition, "Position: %.1f, %.1f, %.1f", avatarPos.x, avatarPos.y, avatarPos.z);
|
|
||||||
}
|
|
||||||
char avatarVelocity[30];
|
|
||||||
sprintf(avatarVelocity, "Velocity: %.1f", glm::length(_myAvatar->getVelocity()));
|
|
||||||
char avatarBodyYaw[30];
|
|
||||||
sprintf(avatarBodyYaw, "Yaw: %.1f", _myAvatar->getBodyYaw());
|
|
||||||
char avatarMixerStats[200];
|
|
||||||
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPosition, WHITE_TEXT);
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarVelocity, WHITE_TEXT);
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarBodyYaw, WHITE_TEXT);
|
|
||||||
|
|
||||||
if (_statsExpanded) {
|
|
||||||
SharedNodePointer avatarMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AvatarMixer);
|
|
||||||
if (avatarMixer) {
|
|
||||||
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
|
||||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
|
||||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
|
||||||
} else {
|
|
||||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
|
||||||
}
|
|
||||||
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarMixerStats, WHITE_TEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
verticalOffset = 0;
|
|
||||||
horizontalOffset = _glWidget->width() - (mirrorEnabled ? 300 : 410);
|
|
||||||
|
|
||||||
lines = _statsExpanded ? 11 : 3;
|
|
||||||
displayStatsBackground(backgroundColor, horizontalOffset, 0, _glWidget->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10);
|
|
||||||
horizontalOffset += 5;
|
|
||||||
|
|
||||||
if (_statsExpanded) {
|
|
||||||
// Local Voxel Memory Usage
|
|
||||||
voxelStats.str("");
|
|
||||||
voxelStats << "Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.f << "MB";
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
|
|
||||||
|
|
||||||
voxelStats.str("");
|
|
||||||
voxelStats <<
|
|
||||||
"Geometry RAM: " << _voxels.getVoxelMemoryUsageRAM() / 1000000.f << "MB / " <<
|
|
||||||
"VBO: " << _voxels.getVoxelMemoryUsageVBO() / 1000000.f << "MB";
|
|
||||||
if (_voxels.hasVoxelMemoryUsageGPU()) {
|
|
||||||
voxelStats << " / GPU: " << _voxels.getVoxelMemoryUsageGPU() / 1000000.f << "MB";
|
|
||||||
}
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
|
|
||||||
|
|
||||||
// Voxel Rendering
|
|
||||||
voxelStats.str("");
|
|
||||||
voxelStats.precision(4);
|
|
||||||
voxelStats << "Voxel Rendering Slots Max: " << _voxels.getMaxVoxels() / 1000.f << "K";
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
voxelStats.str("");
|
|
||||||
voxelStats.precision(4);
|
|
||||||
voxelStats << "Drawn: " << _voxels.getVoxelsWritten() / 1000.f << "K " <<
|
|
||||||
"Abandoned: " << _voxels.getAbandonedVoxels() / 1000.f << "K ";
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT);
|
|
||||||
|
|
||||||
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
|
||||||
std::stringstream sendingMode("");
|
|
||||||
sendingMode << "Octree Sending Mode: [";
|
|
||||||
int serverCount = 0;
|
|
||||||
int movingServerCount = 0;
|
|
||||||
unsigned long totalNodes = 0;
|
|
||||||
unsigned long totalInternal = 0;
|
|
||||||
unsigned long totalLeaves = 0;
|
|
||||||
for(NodeToOctreeSceneStatsIterator i = _octreeServerSceneStats.begin(); i != _octreeServerSceneStats.end(); i++) {
|
|
||||||
//const QUuid& uuid = i->first;
|
|
||||||
OctreeSceneStats& stats = i->second;
|
|
||||||
serverCount++;
|
|
||||||
if (_statsExpanded) {
|
|
||||||
if (serverCount > 1) {
|
|
||||||
sendingMode << ",";
|
|
||||||
}
|
|
||||||
if (stats.isMoving()) {
|
|
||||||
sendingMode << "M";
|
|
||||||
movingServerCount++;
|
|
||||||
} else {
|
|
||||||
sendingMode << "S";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate server node totals
|
|
||||||
totalNodes += stats.getTotalElements();
|
|
||||||
if (_statsExpanded) {
|
|
||||||
totalInternal += stats.getTotalInternal();
|
|
||||||
totalLeaves += stats.getTotalLeaves();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_statsExpanded) {
|
|
||||||
if (serverCount == 0) {
|
|
||||||
sendingMode << "---";
|
|
||||||
}
|
|
||||||
sendingMode << "] " << serverCount << " servers";
|
|
||||||
if (movingServerCount > 0) {
|
|
||||||
sendingMode << " <SCENE NOT STABLE>";
|
|
||||||
} else {
|
|
||||||
sendingMode << " <SCENE STABLE>";
|
|
||||||
}
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)sendingMode.str().c_str(), WHITE_TEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Incoming packets
|
|
||||||
int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount();
|
|
||||||
if (_statsExpanded) {
|
|
||||||
voxelStats.str("");
|
|
||||||
QString packetsString = locale.toString((int)voxelPacketsToProcess);
|
|
||||||
QString maxString = locale.toString((int)_recentMaxPackets);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) {
|
|
||||||
_recentMaxPackets = 0;
|
|
||||||
_resetRecentMaxPacketsSoon = false;
|
|
||||||
}
|
|
||||||
if (voxelPacketsToProcess == 0) {
|
|
||||||
_resetRecentMaxPacketsSoon = true;
|
|
||||||
} else {
|
|
||||||
if (voxelPacketsToProcess > _recentMaxPackets) {
|
|
||||||
_recentMaxPackets = voxelPacketsToProcess;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verticalOffset += (_statsExpanded ? STATS_PELS_PER_LINE : 0);
|
|
||||||
|
|
||||||
QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' ');
|
|
||||||
|
|
||||||
// Server Voxels
|
|
||||||
voxelStats.str("");
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (_statsExpanded) {
|
|
||||||
QString serversInternalString = locale.toString((uint)totalInternal);
|
|
||||||
QString serversLeavesString = locale.toString((uint)totalLeaves);
|
|
||||||
|
|
||||||
voxelStats.str("");
|
|
||||||
voxelStats <<
|
|
||||||
"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);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long localTotal = VoxelTreeElement::getNodeCount();
|
|
||||||
QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' ');
|
|
||||||
|
|
||||||
// Local Voxels
|
|
||||||
voxelStats.str("");
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (_statsExpanded) {
|
|
||||||
unsigned long localInternal = VoxelTreeElement::getInternalNodeCount();
|
|
||||||
unsigned long localLeaves = VoxelTreeElement::getLeafNodeCount();
|
|
||||||
QString localInternalString = locale.toString((uint)localInternal);
|
|
||||||
QString localLeavesString = locale.toString((uint)localLeaves);
|
|
||||||
|
|
||||||
voxelStats.str("");
|
|
||||||
voxelStats <<
|
|
||||||
"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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// called on mouse click release
|
|
||||||
// check for clicks over stats in order to expand or contract them
|
|
||||||
void Application::checkStatsClick() {
|
|
||||||
if (0 != glm::compMax(glm::abs(glm::ivec2(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY)))) {
|
|
||||||
// not worried about dragging on stats
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int statsHeight = 0, statsWidth = 0, statsX = 0, statsY = 0, lines = 0;
|
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
|
||||||
statsX += MIRROR_VIEW_WIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
// top-left stats click
|
|
||||||
lines = _statsExpanded ? 5 : 3;
|
|
||||||
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
|
||||||
statsWidth = 165;
|
|
||||||
if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) {
|
|
||||||
toggleStatsExpanded();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ping stats click
|
|
||||||
lines = _statsExpanded ? 4 : 3;
|
|
||||||
statsX += statsWidth;
|
|
||||||
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
|
||||||
statsWidth = 175;
|
|
||||||
if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) {
|
|
||||||
toggleStatsExpanded();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// top-center stats panel click
|
|
||||||
lines = _statsExpanded ? 4 : 3;
|
|
||||||
statsX += statsWidth;
|
|
||||||
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
|
||||||
statsWidth = _glWidget->width() - 411 - statsX;
|
|
||||||
if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) {
|
|
||||||
toggleStatsExpanded();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// top-right stats click
|
|
||||||
lines = _statsExpanded ? 11 : 3;
|
|
||||||
statsX = _glWidget->width() - 410;
|
|
||||||
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
|
||||||
statsWidth = _glWidget->width() - statsX;
|
|
||||||
if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) {
|
|
||||||
toggleStatsExpanded();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::toggleStatsExpanded() {
|
|
||||||
_statsExpanded = !_statsExpanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
|
glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
|
||||||
float horizontalScale = _glWidget->width() / 2.0f;
|
float horizontalScale = _glWidget->width() / 2.0f;
|
||||||
float verticalScale = _glWidget->height() / 2.0f;
|
float verticalScale = _glWidget->height() / 2.0f;
|
||||||
|
|
|
@ -321,10 +321,6 @@ private:
|
||||||
|
|
||||||
void updateShadowMap();
|
void updateShadowMap();
|
||||||
void displayOverlay();
|
void displayOverlay();
|
||||||
void displayStatsBackground(unsigned int rgba, int x, int y, int width, int height);
|
|
||||||
void displayStats();
|
|
||||||
void checkStatsClick();
|
|
||||||
void toggleStatsExpanded();
|
|
||||||
void renderRearViewMirror(const QRect& region, bool billboard = false);
|
void renderRearViewMirror(const QRect& region, bool billboard = false);
|
||||||
void renderViewFrustum(ViewFrustum& viewFrustum);
|
void renderViewFrustum(ViewFrustum& viewFrustum);
|
||||||
|
|
||||||
|
@ -345,7 +341,6 @@ private:
|
||||||
QMainWindow* _window;
|
QMainWindow* _window;
|
||||||
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
||||||
|
|
||||||
bool _statsExpanded;
|
|
||||||
BandwidthMeter _bandwidthMeter;
|
BandwidthMeter _bandwidthMeter;
|
||||||
|
|
||||||
QThread* _nodeThread;
|
QThread* _nodeThread;
|
||||||
|
@ -456,9 +451,6 @@ private:
|
||||||
int _packetsPerSecond;
|
int _packetsPerSecond;
|
||||||
int _bytesPerSecond;
|
int _bytesPerSecond;
|
||||||
|
|
||||||
int _recentMaxPackets; // recent max incoming voxel packets to process
|
|
||||||
bool _resetRecentMaxPacketsSoon;
|
|
||||||
|
|
||||||
StDev _idleLoopStdev;
|
StDev _idleLoopStdev;
|
||||||
float _idleLoopMeasuredJitter;
|
float _idleLoopMeasuredJitter;
|
||||||
|
|
||||||
|
|
468
interface/src/ui/Stats.cpp
Normal file
468
interface/src/ui/Stats.cpp
Normal file
|
@ -0,0 +1,468 @@
|
||||||
|
//
|
||||||
|
// Stats.cpp
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/component_wise.hpp>
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
|
|
||||||
|
#include "Stats.h"
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
const int STATS_PELS_PER_LINE = 20;
|
||||||
|
|
||||||
|
const int STATS_GENERAL_MIN_WIDTH = 165;
|
||||||
|
const int STATS_PING_MIN_WIDTH = 190;
|
||||||
|
const int STATS_GEO_MIN_WIDTH = 240;
|
||||||
|
const int STATS_VOXEL_MIN_WIDTH = 410;
|
||||||
|
|
||||||
|
Stats* Stats::getInstance() {
|
||||||
|
static Stats stats;
|
||||||
|
return &stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stats::Stats():
|
||||||
|
_expanded(false),
|
||||||
|
_recentMaxPackets(0),
|
||||||
|
_resetRecentMaxPacketsSoon(true),
|
||||||
|
_generalStatsWidth(STATS_GENERAL_MIN_WIDTH),
|
||||||
|
_pingStatsWidth(STATS_PING_MIN_WIDTH),
|
||||||
|
_geoStatsWidth(STATS_GEO_MIN_WIDTH),
|
||||||
|
_voxelStatsWidth(STATS_VOXEL_MIN_WIDTH)
|
||||||
|
{
|
||||||
|
// no constructor behavior yet, only members initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stats::toggleExpanded() {
|
||||||
|
_expanded = !_expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
// called on mouse click release
|
||||||
|
// check for clicks over stats in order to expand or contract them
|
||||||
|
void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) {
|
||||||
|
QGLWidget* glWidget = Application::getInstance()->getGLWidget();
|
||||||
|
|
||||||
|
if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) {
|
||||||
|
// not worried about dragging on stats
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int statsHeight = 0,
|
||||||
|
statsWidth = 0,
|
||||||
|
statsX = 0,
|
||||||
|
statsY = 0,
|
||||||
|
lines = 0;
|
||||||
|
|
||||||
|
statsX = horizontalOffset;
|
||||||
|
|
||||||
|
// top-left stats click
|
||||||
|
lines = _expanded ? 5 : 3;
|
||||||
|
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
||||||
|
if (mouseX > statsX && mouseX < statsX + _generalStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
|
||||||
|
toggleExpanded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
statsX += _generalStatsWidth;
|
||||||
|
|
||||||
|
// ping stats click
|
||||||
|
lines = _expanded ? 4 : 3;
|
||||||
|
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
||||||
|
if (mouseX > statsX && mouseX < statsX + _pingStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
|
||||||
|
toggleExpanded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
statsX += _pingStatsWidth;
|
||||||
|
|
||||||
|
// top-center stats panel click
|
||||||
|
lines = _expanded ? 4 : 3;
|
||||||
|
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
||||||
|
if (mouseX > statsX && mouseX < statsX + _geoStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
|
||||||
|
toggleExpanded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
statsX += _geoStatsWidth;
|
||||||
|
|
||||||
|
// top-right stats click
|
||||||
|
lines = _expanded ? 11 : 3;
|
||||||
|
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
||||||
|
statsWidth = glWidget->width() - statsX;
|
||||||
|
if (mouseX > statsX && mouseX < statsX + statsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
|
||||||
|
toggleExpanded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stats::resetWidthOnResizeGL(int width) {
|
||||||
|
QGLWidget* glWidget = Application::getInstance()->getGLWidget();
|
||||||
|
int extraSpace = glWidget->width()
|
||||||
|
- STATS_GENERAL_MIN_WIDTH
|
||||||
|
- STATS_PING_MIN_WIDTH
|
||||||
|
- STATS_GEO_MIN_WIDTH
|
||||||
|
- STATS_VOXEL_MIN_WIDTH
|
||||||
|
- 3;
|
||||||
|
|
||||||
|
_generalStatsWidth = STATS_GENERAL_MIN_WIDTH;
|
||||||
|
_pingStatsWidth = STATS_PING_MIN_WIDTH;
|
||||||
|
_geoStatsWidth = STATS_GEO_MIN_WIDTH;
|
||||||
|
_voxelStatsWidth = STATS_VOXEL_MIN_WIDTH;
|
||||||
|
|
||||||
|
if (extraSpace > 4) {
|
||||||
|
_generalStatsWidth += (int) extraSpace / 4;
|
||||||
|
_pingStatsWidth += (int) extraSpace / 4;
|
||||||
|
_geoStatsWidth += (int) extraSpace / 4;
|
||||||
|
_voxelStatsWidth += glWidget->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// translucent background box that makes stats more readable
|
||||||
|
void Stats::drawBackground(unsigned int rgba, int x, int y, int width, int height) {
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor4f(((rgba >> 24) & 0xff) / 255.0f,
|
||||||
|
((rgba >> 16) & 0xff) / 255.0f,
|
||||||
|
((rgba >> 8) & 0xff) / 255.0f,
|
||||||
|
(rgba & 0xff) / 255.0f);
|
||||||
|
glVertex3f(x, y, 0);
|
||||||
|
glVertex3f(x + width, y, 0);
|
||||||
|
glVertex3f(x + width, y + height, 0);
|
||||||
|
glVertex3f(x , y + height, 0);
|
||||||
|
glEnd();
|
||||||
|
glColor4f(1, 1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// display expanded or contracted stats
|
||||||
|
void Stats::display(
|
||||||
|
const float* color,
|
||||||
|
int horizontalOffset,
|
||||||
|
float fps,
|
||||||
|
int packetsPerSecond,
|
||||||
|
int bytesPerSecond,
|
||||||
|
int voxelPacketsToProcess)
|
||||||
|
{
|
||||||
|
QGLWidget* glWidget = Application::getInstance()->getGLWidget();
|
||||||
|
|
||||||
|
unsigned int backgroundColor = 0x33333399;
|
||||||
|
int verticalOffset = 0, lines = 0;
|
||||||
|
|
||||||
|
QLocale locale(QLocale::English);
|
||||||
|
std::stringstream voxelStats;
|
||||||
|
|
||||||
|
glPointSize(1.0f);
|
||||||
|
|
||||||
|
// we need to take one avatar out so we don't include ourselves
|
||||||
|
int totalAvatars = Application::getInstance()->getAvatarManager().size() - 1;
|
||||||
|
int totalServers = NodeList::getInstance()->size();
|
||||||
|
|
||||||
|
lines = _expanded ? 5 : 3;
|
||||||
|
drawBackground(backgroundColor, horizontalOffset, 0, _generalStatsWidth, lines * STATS_PELS_PER_LINE + 10);
|
||||||
|
horizontalOffset += 5;
|
||||||
|
|
||||||
|
char serverNodes[30];
|
||||||
|
sprintf(serverNodes, "Servers: %d", totalServers);
|
||||||
|
char avatarNodes[30];
|
||||||
|
sprintf(avatarNodes, "Avatars: %d", totalAvatars);
|
||||||
|
char framesPerSecond[30];
|
||||||
|
sprintf(framesPerSecond, "Framerate: %3.0f FPS", fps);
|
||||||
|
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, serverNodes, color);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarNodes, color);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, framesPerSecond, color);
|
||||||
|
|
||||||
|
if (_expanded) {
|
||||||
|
char packetsPerSecondString[30];
|
||||||
|
sprintf(packetsPerSecondString, "Pkts/sec: %d", packetsPerSecond);
|
||||||
|
char averageMegabitsPerSecond[30];
|
||||||
|
sprintf(averageMegabitsPerSecond, "Mbps: %3.2f", (float)bytesPerSecond * 8.f / 1000000.f);
|
||||||
|
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, packetsPerSecondString, color);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, averageMegabitsPerSecond, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalOffset = 0;
|
||||||
|
horizontalOffset = _generalStatsWidth +1;
|
||||||
|
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
|
||||||
|
int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0;
|
||||||
|
|
||||||
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||||
|
SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
||||||
|
|
||||||
|
pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0;
|
||||||
|
pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0;
|
||||||
|
|
||||||
|
// Now handle voxel servers, since there could be more than one, we average their ping times
|
||||||
|
unsigned long totalPingVoxel = 0;
|
||||||
|
int voxelServerCount = 0;
|
||||||
|
|
||||||
|
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||||
|
if (node->getType() == NodeType::VoxelServer) {
|
||||||
|
totalPingVoxel += node->getPingMs();
|
||||||
|
voxelServerCount++;
|
||||||
|
if (pingVoxelMax < node->getPingMs()) {
|
||||||
|
pingVoxelMax = node->getPingMs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (voxelServerCount) {
|
||||||
|
pingVoxel = totalPingVoxel/voxelServerCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = _expanded ? 4 : 3;
|
||||||
|
drawBackground(backgroundColor, horizontalOffset, 0, _pingStatsWidth, lines * STATS_PELS_PER_LINE + 10);
|
||||||
|
horizontalOffset += 5;
|
||||||
|
|
||||||
|
Audio* audio = Application::getInstance()->getAudio();
|
||||||
|
|
||||||
|
char audioJitter[30];
|
||||||
|
sprintf(audioJitter,
|
||||||
|
"Buffer msecs %.1f",
|
||||||
|
(float) (audio->getNetworkBufferLengthSamplesPerChannel() + (float) audio->getJitterBufferSamples()) /
|
||||||
|
(float) audio->getNetworkSampleRate() * 1000.f);
|
||||||
|
drawText(30, glWidget->height() - 22, 0.10f, 0.f, 2.f, audioJitter, color);
|
||||||
|
|
||||||
|
|
||||||
|
char audioPing[30];
|
||||||
|
sprintf(audioPing, "Audio ping: %d", pingAudio);
|
||||||
|
|
||||||
|
|
||||||
|
char avatarPing[30];
|
||||||
|
sprintf(avatarPing, "Avatar ping: %d", pingAvatar);
|
||||||
|
char voxelAvgPing[30];
|
||||||
|
sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel);
|
||||||
|
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, audioPing, color);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPing, color);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelAvgPing, color);
|
||||||
|
|
||||||
|
if (_expanded) {
|
||||||
|
char voxelMaxPing[30];
|
||||||
|
sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax);
|
||||||
|
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelMaxPing, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalOffset = 0;
|
||||||
|
horizontalOffset = _generalStatsWidth + _pingStatsWidth + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||||
|
glm::vec3 avatarPos = myAvatar->getPosition();
|
||||||
|
|
||||||
|
lines = _expanded ? 4 : 3;
|
||||||
|
drawBackground(backgroundColor, horizontalOffset, 0, _geoStatsWidth, lines * STATS_PELS_PER_LINE + 10);
|
||||||
|
horizontalOffset += 5;
|
||||||
|
|
||||||
|
char avatarPosition[200];
|
||||||
|
sprintf(avatarPosition, "Position: %.1f, %.1f, %.1f", avatarPos.x, avatarPos.y, avatarPos.z);
|
||||||
|
char avatarVelocity[30];
|
||||||
|
sprintf(avatarVelocity, "Velocity: %.1f", glm::length(myAvatar->getVelocity()));
|
||||||
|
char avatarBodyYaw[30];
|
||||||
|
sprintf(avatarBodyYaw, "Yaw: %.1f", myAvatar->getBodyYaw());
|
||||||
|
char avatarMixerStats[200];
|
||||||
|
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPosition, color);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarVelocity, color);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarBodyYaw, color);
|
||||||
|
|
||||||
|
if (_expanded) {
|
||||||
|
SharedNodePointer avatarMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AvatarMixer);
|
||||||
|
if (avatarMixer) {
|
||||||
|
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
||||||
|
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||||
|
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||||
|
} else {
|
||||||
|
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarMixerStats, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalOffset = 0;
|
||||||
|
horizontalOffset = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3;
|
||||||
|
|
||||||
|
VoxelSystem* voxels = Application::getInstance()->getVoxels();
|
||||||
|
|
||||||
|
lines = _expanded ? 11 : 3;
|
||||||
|
drawBackground(backgroundColor, horizontalOffset, 0, glWidget->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10);
|
||||||
|
horizontalOffset += 5;
|
||||||
|
|
||||||
|
if (_expanded) {
|
||||||
|
// Local Voxel Memory Usage
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats << "Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.f << "MB";
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||||
|
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats <<
|
||||||
|
"Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.f << "MB / " <<
|
||||||
|
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.f << "MB";
|
||||||
|
if (voxels->hasVoxelMemoryUsageGPU()) {
|
||||||
|
voxelStats << " / GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.f << "MB";
|
||||||
|
}
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||||
|
|
||||||
|
// Voxel Rendering
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats.precision(4);
|
||||||
|
voxelStats << "Voxel Rendering Slots Max: " << voxels->getMaxVoxels() / 1000.f << "K";
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats.precision(4);
|
||||||
|
voxelStats << "Drawn: " << voxels->getVoxelsWritten() / 1000.f << "K " <<
|
||||||
|
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.f << "K ";
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||||
|
|
||||||
|
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
||||||
|
std::stringstream sendingMode("");
|
||||||
|
sendingMode << "Octree Sending Mode: [";
|
||||||
|
int serverCount = 0;
|
||||||
|
int movingServerCount = 0;
|
||||||
|
unsigned long totalNodes = 0;
|
||||||
|
unsigned long totalInternal = 0;
|
||||||
|
unsigned long totalLeaves = 0;
|
||||||
|
NodeToOctreeSceneStats* octreeServerSceneStats = Application::getInstance()->getOcteeSceneStats();
|
||||||
|
for(NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) {
|
||||||
|
//const QUuid& uuid = i->first;
|
||||||
|
OctreeSceneStats& stats = i->second;
|
||||||
|
serverCount++;
|
||||||
|
if (_expanded) {
|
||||||
|
if (serverCount > 1) {
|
||||||
|
sendingMode << ",";
|
||||||
|
}
|
||||||
|
if (stats.isMoving()) {
|
||||||
|
sendingMode << "M";
|
||||||
|
movingServerCount++;
|
||||||
|
} else {
|
||||||
|
sendingMode << "S";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate server node totals
|
||||||
|
totalNodes += stats.getTotalElements();
|
||||||
|
if (_expanded) {
|
||||||
|
totalInternal += stats.getTotalInternal();
|
||||||
|
totalLeaves += stats.getTotalLeaves();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_expanded) {
|
||||||
|
if (serverCount == 0) {
|
||||||
|
sendingMode << "---";
|
||||||
|
}
|
||||||
|
sendingMode << "] " << serverCount << " servers";
|
||||||
|
if (movingServerCount > 0) {
|
||||||
|
sendingMode << " <SCENE NOT STABLE>";
|
||||||
|
} else {
|
||||||
|
sendingMode << " <SCENE STABLE>";
|
||||||
|
}
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)sendingMode.str().c_str(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Incoming packets
|
||||||
|
if (_expanded) {
|
||||||
|
voxelStats.str("");
|
||||||
|
QString packetsString = locale.toString((int)voxelPacketsToProcess);
|
||||||
|
QString maxString = locale.toString((int)_recentMaxPackets);
|
||||||
|
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(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) {
|
||||||
|
_recentMaxPackets = 0;
|
||||||
|
_resetRecentMaxPacketsSoon = false;
|
||||||
|
}
|
||||||
|
if (voxelPacketsToProcess == 0) {
|
||||||
|
_resetRecentMaxPacketsSoon = true;
|
||||||
|
} else {
|
||||||
|
if (voxelPacketsToProcess > _recentMaxPackets) {
|
||||||
|
_recentMaxPackets = voxelPacketsToProcess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalOffset += (_expanded ? STATS_PELS_PER_LINE : 0);
|
||||||
|
|
||||||
|
QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' ');
|
||||||
|
|
||||||
|
// Server Voxels
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats << "Server voxels: " << qPrintable(serversTotalString);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||||
|
|
||||||
|
if (_expanded) {
|
||||||
|
QString serversInternalString = locale.toString((uint)totalInternal);
|
||||||
|
QString serversLeavesString = locale.toString((uint)totalLeaves);
|
||||||
|
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats <<
|
||||||
|
"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(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long localTotal = VoxelTreeElement::getNodeCount();
|
||||||
|
QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' ');
|
||||||
|
|
||||||
|
// Local Voxels
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats << "Local voxels: " << qPrintable(localTotalString);
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||||
|
|
||||||
|
if (_expanded) {
|
||||||
|
unsigned long localInternal = VoxelTreeElement::getInternalNodeCount();
|
||||||
|
unsigned long localLeaves = VoxelTreeElement::getLeafNodeCount();
|
||||||
|
QString localInternalString = locale.toString((uint)localInternal);
|
||||||
|
QString localLeavesString = locale.toString((uint)localLeaves);
|
||||||
|
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats <<
|
||||||
|
"Internal: " << qPrintable(localInternalString) << " " <<
|
||||||
|
"Leaves: " << qPrintable(localLeavesString) << "";
|
||||||
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOD Details
|
||||||
|
if (_expanded) {
|
||||||
|
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(), color);
|
||||||
|
}
|
||||||
|
}
|
40
interface/src/ui/Stats.h
Normal file
40
interface/src/ui/Stats.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
//
|
||||||
|
// Stats.h
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <NodeList.h>
|
||||||
|
|
||||||
|
//#include "Menu.h"
|
||||||
|
|
||||||
|
class Stats: public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static Stats* getInstance();
|
||||||
|
|
||||||
|
Stats();
|
||||||
|
|
||||||
|
static void drawBackground(unsigned int rgba, int x, int y, int width, int height);
|
||||||
|
|
||||||
|
void toggleExpanded();
|
||||||
|
void checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset);
|
||||||
|
void resetWidthOnResizeGL(int width);
|
||||||
|
void display(const float* color, int horizontalOffset, float fps, int packetsPerSecond, int bytesPerSecond, int voxelPacketsToProcess);
|
||||||
|
private:
|
||||||
|
static Stats* _sharedInstance;
|
||||||
|
|
||||||
|
bool _expanded;
|
||||||
|
|
||||||
|
int _recentMaxPackets; // recent max incoming voxel packets to process
|
||||||
|
bool _resetRecentMaxPacketsSoon;
|
||||||
|
|
||||||
|
int _generalStatsWidth;
|
||||||
|
int _pingStatsWidth;
|
||||||
|
int _geoStatsWidth;
|
||||||
|
int _voxelStatsWidth;
|
||||||
|
};
|
Loading…
Reference in a new issue