History

Merge branch 'master' of https://github.com/highfidelity/hifi into add_interface_to_log_user_activity

Atlante45 committed 12 years ago

Commit 8d00a8d2 parents 9d393bb 6312222312 files · +24215 −5270Browse files

Showing the changes to interface/src/Application.cpp (1 of 312 files). Show all

Unified · Split

interface/src/Application.cpp+514−371
@@ -74,6 +74,7 @@ · 73 unmodified lines
74#include "devices/TV3DManager.h"74#include "devices/TV3DManager.h"
75#include "renderer/ProgramObject.h"75#include "renderer/ProgramObject.h"
76 76
77#include "scripting/AccountScriptingInterface.h"
77#include "scripting/AudioDeviceScriptingInterface.h"78#include "scripting/AudioDeviceScriptingInterface.h"
78#include "scripting/ClipboardScriptingInterface.h"79#include "scripting/ClipboardScriptingInterface.h"
79#include "scripting/MenuScriptingInterface.h"80#include "scripting/MenuScriptingInterface.h"
@@ -103,18 +104,11 @@ const int STARTUP_JITTER_SAMPLES = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 2 · 23 unmodified lines
103 // Startup optimistically with small jitter buffer that104 // Startup optimistically with small jitter buffer that
104 // will start playback on the second received audio packet.105 // will start playback on the second received audio packet.
105 106
106const int MIRROR_VIEW_TOP_PADDING = 5;
107const int MIRROR_VIEW_LEFT_PADDING = 10;
108const int MIRROR_VIEW_WIDTH = 265;
109const int MIRROR_VIEW_HEIGHT = 215;
110const float MIRROR_FULLSCREEN_DISTANCE = 0.35f;
111const float MIRROR_REARVIEW_DISTANCE = 0.65f;
112const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
113const float MIRROR_FIELD_OF_VIEW = 30.0f;
114
115const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml";107const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml";
116const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";108const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";
117 109
110const QString DEFAULT_SCRIPTS_JS_URL = "http://public.highfidelity.io/scripts/defaultScripts.js";
111
118void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {112void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
119 if (message.size() > 0) {113 if (message.size() > 0) {
120 QString dateString = QDateTime::currentDateTime().toTimeSpec(Qt::LocalTime).toString(Qt::ISODate);114 QString dateString = QDateTime::currentDateTime().toTimeSpec(Qt::LocalTime).toString(Qt::ISODate);
@@ -141,7 +135,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 20 unmodified lines
141 _nodeThread(new QThread(this)),135 _nodeThread(new QThread(this)),
142 _datagramProcessor(),136 _datagramProcessor(),
143 _frameCount(0),137 _frameCount(0),
144 _fps(120.0f),138 _fps(60.0f),
145 _justStarted(true),139 _justStarted(true),
146 _voxelImporter(NULL),140 _voxelImporter(NULL),
147 _importSucceded(false),141 _importSucceded(false),
@@ -158,6 +152,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 10 unmodified lines
158 _mouseX(0),152 _mouseX(0),
159 _mouseY(0),153 _mouseY(0),
160 _lastMouseMove(usecTimestampNow()),154 _lastMouseMove(usecTimestampNow()),
155 _lastMouseMoveType(QEvent::MouseMove),
161 _mouseHidden(false),156 _mouseHidden(false),
162 _seenMouseMove(false),157 _seenMouseMove(false),
163 _touchAvgX(0.0f),158 _touchAvgX(0.0f),
@@ -166,14 +161,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 2 unmodified lines
166 _mousePressed(false),161 _mousePressed(false),
167 _audio(STARTUP_JITTER_SAMPLES),162 _audio(STARTUP_JITTER_SAMPLES),
168 _enableProcessVoxelsThread(true),163 _enableProcessVoxelsThread(true),
169 _voxelProcessor(),164 _octreeProcessor(),
170 _voxelHideShowThread(&_voxels),165 _voxelHideShowThread(&_voxels),
171 _packetsPerSecond(0),166 _packetsPerSecond(0),
172 _bytesPerSecond(0),167 _bytesPerSecond(0),
173 _nodeBoundsDisplay(this),168 _nodeBoundsDisplay(this),
174 _previousScriptLocation(),169 _previousScriptLocation(),
175 _runningScriptsWidget(new RunningScriptsWidget(_window)),170 _applicationOverlay(),
176 _runningScriptsWidgetWasVisible(false)171 _runningScriptsWidget(NULL),
172 _runningScriptsWidgetWasVisible(false),
173 _trayIcon(new QSystemTrayIcon(_window)),
174 _lastNackTime(usecTimestampNow())
177{175{
178 // read the ApplicationInfo.ini file for Name/Version/Domain information176 // read the ApplicationInfo.ini file for Name/Version/Domain information
179 QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);177 QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
@@ -204,6 +202,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 24 unmodified lines
204 // call Menu getInstance static method to set up the menu202 // call Menu getInstance static method to set up the menu
205 _window->setMenuBar(Menu::getInstance());203 _window->setMenuBar(Menu::getInstance());
206 204
205 _runningScriptsWidget = new RunningScriptsWidget(_window);
206
207 unsigned int listenPort = 0; // bind to an ephemeral port by default207 unsigned int listenPort = 0; // bind to an ephemeral port by default
208 const char** constArgv = const_cast<const char**>(argv);208 const char** constArgv = const_cast<const char**>(argv);
209 const char* portStr = getCmdOption(argc, constArgv, "--listenPort");209 const char* portStr = getCmdOption(argc, constArgv, "--listenPort");
@@ -238,7 +238,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 28 unmodified lines
238 connect(&nodeList->getDomainHandler(), SIGNAL(connectedToDomain(const QString&)), SLOT(connectedToDomain(const QString&)));238 connect(&nodeList->getDomainHandler(), SIGNAL(connectedToDomain(const QString&)), SLOT(connectedToDomain(const QString&)));
239 239
240 // update our location every 5 seconds in the data-server, assuming that we are authenticated with one240 // update our location every 5 seconds in the data-server, assuming that we are authenticated with one
241 const float DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5.0f * 1000.0f;241 const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * 1000;
242 242
243 QTimer* locationUpdateTimer = new QTimer(this);243 QTimer* locationUpdateTimer = new QTimer(this);
244 connect(locationUpdateTimer, &QTimer::timeout, this, &Application::updateLocationInServer);244 connect(locationUpdateTimer, &QTimer::timeout, this, &Application::updateLocationInServer);
@@ -255,6 +255,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 10 unmodified lines
255 255
256 // connect to appropriate slots on AccountManager256 // connect to appropriate slots on AccountManager
257 AccountManager& accountManager = AccountManager::getInstance();257 AccountManager& accountManager = AccountManager::getInstance();
258
259 const qint64 BALANCE_UPDATE_INTERVAL_MSECS = 5 * 1000;
260
261 QTimer* balanceUpdateTimer = new QTimer(this);
262 connect(balanceUpdateTimer, &QTimer::timeout, &accountManager, &AccountManager::updateBalance);
263 balanceUpdateTimer->start(BALANCE_UPDATE_INTERVAL_MSECS);
264
265 connect(&accountManager, &AccountManager::balanceChanged, this, &Application::updateWindowTitle);
266
258 connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain);267 connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain);
259 connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);268 connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
260 269
@@ -289,8 +298,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 28 unmodified lines
289 // move the silentNodeTimer to the _nodeThread298 // move the silentNodeTimer to the _nodeThread
290 QTimer* silentNodeTimer = new QTimer();299 QTimer* silentNodeTimer = new QTimer();
291 connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));300 connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
292 silentNodeTimer->moveToThread(_nodeThread);
293 silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS);301 silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS);
302 silentNodeTimer->moveToThread(_nodeThread);
294 303
295 // send the identity packet for our avatar each second to our avatar mixer304 // send the identity packet for our avatar each second to our avatar mixer
296 QTimer* identityPacketTimer = new QTimer();305 QTimer* identityPacketTimer = new QTimer();
@@ -361,7 +370,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 64 unmodified lines
361 qDebug() << "This is a first run...";370 qDebug() << "This is a first run...";
362 // clear the scripts, and set out script to our default scripts371 // clear the scripts, and set out script to our default scripts
363 clearScriptsBeforeRunning();372 clearScriptsBeforeRunning();
364 loadScript("http://public.highfidelity.io/scripts/defaultScripts.js");373 loadScript(DEFAULT_SCRIPTS_JS_URL);
365 374
366 QMutexLocker locker(&_settingsMutex);375 QMutexLocker locker(&_settingsMutex);
367 _settings->setValue("firstRun",QVariant(false));376 _settings->setValue("firstRun",QVariant(false));
@@ -383,6 +392,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 15 unmodified lines
383 OAuthWebViewHandler::getInstance();392 OAuthWebViewHandler::getInstance();
384 // make sure the High Fidelity root CA is in our list of trusted certs393 // make sure the High Fidelity root CA is in our list of trusted certs
385 OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig();394 OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig();
395
396 _trayIcon->show();
386}397}
387 398
388Application::~Application() {399Application::~Application() {
@@ -412,7 +423,7 @@ Application::~Application() { · 23 unmodified lines
412 _audio.thread()->quit();423 _audio.thread()->quit();
413 _audio.thread()->wait();424 _audio.thread()->wait();
414 425
415 _voxelProcessor.terminate();426 _octreeProcessor.terminate();
416 _voxelHideShowThread.terminate();427 _voxelHideShowThread.terminate();
417 _voxelEditSender.terminate();428 _voxelEditSender.terminate();
418 _particleEditSender.terminate();429 _particleEditSender.terminate();
@@ -511,7 +522,7 @@ void Application::initializeGL() { · 92 unmodified lines
511 qDebug( "init() complete.");522 qDebug( "init() complete.");
512 523
513 // create thread for parsing of voxel data independent of the main network and rendering threads524 // create thread for parsing of voxel data independent of the main network and rendering threads
514 _voxelProcessor.initialize(_enableProcessVoxelsThread);525 _octreeProcessor.initialize(_enableProcessVoxelsThread);
515 _voxelEditSender.initialize(_enableProcessVoxelsThread);526 _voxelEditSender.initialize(_enableProcessVoxelsThread);
516 _voxelHideShowThread.initialize(_enableProcessVoxelsThread);527 _voxelHideShowThread.initialize(_enableProcessVoxelsThread);
517 _particleEditSender.initialize(_enableProcessVoxelsThread);528 _particleEditSender.initialize(_enableProcessVoxelsThread);
@@ -543,26 +554,20 @@ void Application::initializeGL() { · 25 unmodified lines
543 }554 }
544 555
545 // update before the first render556 // update before the first render
546 update(0.0f);557 update(1.f / _fps);
547 558
548 InfoView::showFirstTime();559 InfoView::showFirstTime();
549}560}
550 561
551void Application::paintGL() {562void Application::paintGL() {
563 PerformanceTimer perfTimer("paintGL");
564
552 PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));565 PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
553 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);566 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
554 PerformanceWarning warn(showWarnings, "Application::paintGL()");567 PerformanceWarning warn(showWarnings, "Application::paintGL()");
555 568
556 glEnable(GL_LINE_SMOOTH);569 glEnable(GL_LINE_SMOOTH);
557 570
558 float pushback = 0.0f;
559 float pushbackFocalLength = 0.0f;
560 if (OculusManager::isConnected()) {
561 _myCamera.setUpShift(0.0f);
562 _myCamera.setDistance(0.0f);
563 _myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
564 }
565
566 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {571 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
567 _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay572 _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay
568 _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());573 _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
@@ -577,39 +582,25 @@ void Application::paintGL() { · 8 unmodified lines
577 _myCamera.setTightness(0.0f);582 _myCamera.setTightness(0.0f);
578 glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();583 glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();
579 float headHeight = eyePosition.y - _myAvatar->getPosition().y;584 float headHeight = eyePosition.y - _myAvatar->getPosition().y;
580 _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale() * _scaleMirror);585 _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
581 _myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0));586 _myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0));
582 _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));587 _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
588 }
583 589
584 // if the head would intersect the near clip plane, we must push the camera out590 if (OculusManager::isConnected()) {
585 glm::vec3 relativePosition = glm::inverse(_myCamera.getTargetRotation()) *591 // Oculus in third person causes nausea, so only allow it if option is checked in dev menu
586 (eyePosition - _myCamera.getTargetPosition());592 if (!Menu::getInstance()->isOptionChecked(MenuOption::AllowOculusCameraModeChange) || _myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
587 const float BASE_PUSHBACK_RADIUS = 0.2f;593 _myCamera.setDistance(0.0f);
588 float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;594 _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
589 pushback = relativePosition.z + pushbackRadius - _myCamera.getDistance();595 _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
590 pushbackFocalLength = _myCamera.getDistance();
591 }
592
593 // handle pushback, if any
594 if (pushbackFocalLength > 0.0f) {
595 const float PUSHBACK_DECAY = 0.5f;
596 _cameraPushback = qMax(pushback, _cameraPushback * PUSHBACK_DECAY);
597 if (_cameraPushback > EPSILON) {
598 _myCamera.setTargetPosition(_myCamera.getTargetPosition() +
599 _myCamera.getTargetRotation() * glm::vec3(0.0f, 0.0f, _cameraPushback));
600 float enlargement = pushbackFocalLength / (pushbackFocalLength + _cameraPushback);
601 _myCamera.setFieldOfView(glm::degrees(2.0f * atanf(enlargement * tanf(
602 glm::radians(Menu::getInstance()->getFieldOfView() * 0.5f)))));
603 } else {
604 _myCamera.setFieldOfView(Menu::getInstance()->getFieldOfView());
605 }596 }
606 updateProjectionMatrix(_myCamera, true);597 _myCamera.setUpShift(0.0f);
598 _myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
607 }599 }
608 600
609 // Update camera position601 // Update camera position
610 _myCamera.update( 1.f/_fps );602 _myCamera.update( 1.f/_fps );
611 603
612
613 // Note: whichCamera is used to pick between the normal camera myCamera for our604 // Note: whichCamera is used to pick between the normal camera myCamera for our
614 // main camera, vs, an alternate camera. The alternate camera we support right now605 // main camera, vs, an alternate camera. The alternate camera we support right now
615 // is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism606 // is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
@@ -635,16 +626,18 @@ void Application::paintGL() { · 19 unmodified lines
635 whichCamera = _viewFrustumOffsetCamera;626 whichCamera = _viewFrustumOffsetCamera;
636 }627 }
637 628
638 if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) {629 if (Menu::getInstance()->getShadowsEnabled()) {
639 updateShadowMap();630 updateShadowMap();
640 }631 }
641 632
642 if (OculusManager::isConnected()) {633 if (OculusManager::isConnected()) {
643 OculusManager::display(whichCamera);634 OculusManager::display(whichCamera);
635
644 } else if (TV3DManager::isConnected()) {636 } else if (TV3DManager::isConnected()) {
645 _glowEffect.prepare();637 _glowEffect.prepare();
646 TV3DManager::display(whichCamera);638 TV3DManager::display(whichCamera);
647 _glowEffect.render();639 _glowEffect.render();
640
648 } else {641 } else {
649 _glowEffect.prepare();642 _glowEffect.prepare();
650 643
@@ -663,7 +656,17 @@ void Application::paintGL() { · 12 unmodified lines
663 _rearMirrorTools->render(true);656 _rearMirrorTools->render(true);
664 }657 }
665 658
666 displayOverlay();659 {
660 PerformanceTimer perfTimer("paintGL/renderOverlay");
661 //If alpha is 1, we can render directly to the screen.
662 if (_applicationOverlay.getAlpha() == 1.0f) {
663 _applicationOverlay.renderOverlay();
664 } else {
665 //Render to to texture so we can fade it
666 _applicationOverlay.renderOverlay(true);
667 _applicationOverlay.displayOverlayTexture();
668 }
669 }
667 }670 }
668 671
669 _frameCount++;672 _frameCount++;
@@ -1103,6 +1106,16 @@ void Application::focusOutEvent(QFocusEvent* event) { · 433 unmodified lines
1103}1106}
1104 1107
1105void Application::mouseMoveEvent(QMouseEvent* event) {1108void Application::mouseMoveEvent(QMouseEvent* event) {
1109
1110 bool showMouse = true;
1111 // If this mouse move event is emitted by a controller, dont show the mouse cursor
1112 if (event->type() == CONTROLLER_MOVE_EVENT) {
1113 showMouse = false;
1114 }
1115
1116 // Used by application overlay to determine how to draw cursor(s)
1117 _lastMouseMoveType = event->type();
1118
1106 _controllerScriptingInterface.emitMouseMoveEvent(event); // send events to any registered scripts1119 _controllerScriptingInterface.emitMouseMoveEvent(event); // send events to any registered scripts
1107 1120
1108 // if one of our scripts have asked to capture this event, then stop processing it1121 // if one of our scripts have asked to capture this event, then stop processing it
@@ -1110,9 +1123,9 @@ void Application::mouseMoveEvent(QMouseEvent* event) { · 1 unmodified line
1110 return;1123 return;
1111 }1124 }
1112 1125
1113
1114 _lastMouseMove = usecTimestampNow();1126 _lastMouseMove = usecTimestampNow();
1115 if (_mouseHidden) {1127
1128 if (_mouseHidden && showMouse && !OculusManager::isConnected()) {
1116 getGLWidget()->setCursor(Qt::ArrowCursor);1129 getGLWidget()->setCursor(Qt::ArrowCursor);
1117 _mouseHidden = false;1130 _mouseHidden = false;
1118 _seenMouseMove = true;1131 _seenMouseMove = true;
@@ -1308,11 +1321,13 @@ void Application::timer() { · 189 unmodified lines
1308}1321}
1309 1322
1310void Application::idle() {1323void Application::idle() {
1324 PerformanceTimer perfTimer("idle");
1325
1311 // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing1326 // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing
1312 // details if we're in ExtraDebugging mode. However, the ::update() and it's subcomponents will show their timing1327 // details if we're in ExtraDebugging mode. However, the ::update() and it's subcomponents will show their timing
1313 // details normally.1328 // details normally.
1314 bool showWarnings = getLogger()->extraDebugging();1329 bool showWarnings = getLogger()->extraDebugging();
1315 PerformanceWarning warn(showWarnings, "Application::idle()");1330 PerformanceWarning warn(showWarnings, "idle()");
1316 1331
1317 // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran1332 // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
1318 1333
@@ -1320,15 +1335,18 @@ void Application::idle() { · 1 unmodified line
1320 if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {1335 if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
1321 _lastTimeUpdated.start();1336 _lastTimeUpdated.start();
1322 {1337 {
1338 PerformanceTimer perfTimer("idle/update");
1323 PerformanceWarning warn(showWarnings, "Application::idle()... update()");1339 PerformanceWarning warn(showWarnings, "Application::idle()... update()");
1324 const float BIGGEST_DELTA_TIME_SECS = 0.25f;1340 const float BIGGEST_DELTA_TIME_SECS = 0.25f;
1325 update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));1341 update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
1326 }1342 }
1327 {1343 {
1344 PerformanceTimer perfTimer("idle/updateGL");
1328 PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()");1345 PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()");
1329 _glWidget->updateGL();1346 _glWidget->updateGL();
1330 }1347 }
1331 {1348 {
1349 PerformanceTimer perfTimer("idle/rest");
1332 PerformanceWarning warn(showWarnings, "Application::idle()... rest of it");1350 PerformanceWarning warn(showWarnings, "Application::idle()... rest of it");
1333 _idleLoopStdev.addValue(timeSinceLastUpdate);1351 _idleLoopStdev.addValue(timeSinceLastUpdate);
1334 1352
@@ -1340,14 +1358,16 @@ void Application::idle() { · 5 unmodified lines
1340 }1358 }
1341 1359
1342 if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {1360 if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
1361 PerformanceTimer perfTimer("idle/rest/_buckyBalls");
1343 _buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData());1362 _buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData());
1344 }1363 }
1345 1364
1346 // After finishing all of the above work, restart the idle timer, allowing 2ms to process events.1365 // After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
1347 idleTimer->start(2);1366 idleTimer->start(2);
1348 }1367
1349 if (_numChangedSettings > 0) {1368 if (_numChangedSettings > 0) {
1350 saveSettings();1369 saveSettings();
1370 }
1351 }1371 }
1352 }1372 }
1353}1373}
@@ -1375,6 +1395,9 @@ void Application::setEnable3DTVMode(bool enable3DTVMode) { · 21 unmodified lines
1375 resizeGL(_glWidget->width(),_glWidget->height());1395 resizeGL(_glWidget->width(),_glWidget->height());
1376}1396}
1377 1397
1398void Application::setEnableVRMode(bool enableVRMode) {
1399 resizeGL(_glWidget->width(), _glWidget->height());
1400}
1378 1401
1379void Application::setRenderVoxels(bool voxelRender) {1402void Application::setRenderVoxels(bool voxelRender) {
1380 _voxelEditSender.setShouldSend(voxelRender);1403 _voxelEditSender.setShouldSend(voxelRender);
@@ -1504,10 +1527,10 @@ void Application::importVoxels() { · 123 unmodified lines
1504 }1527 }
1505 1528
1506 if (!_voxelImporter->exec()) {1529 if (!_voxelImporter->exec()) {
1507 qDebug() << "[DEBUG] Import succeeded." << endl;1530 qDebug() << "Import succeeded." << endl;
1508 _importSucceded = true;1531 _importSucceded = true;
1509 } else {1532 } else {
1510 qDebug() << "[DEBUG] Import failed." << endl;1533 qDebug() << "Import failed." << endl;
1511 if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) {1534 if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) {
1512 _sharedVoxelSystem.killLocalVoxels();1535 _sharedVoxelSystem.killLocalVoxels();
1513 _sharedVoxelSystem.changeTree(&_clipboard);1536 _sharedVoxelSystem.changeTree(&_clipboard);
@@ -1749,6 +1772,7 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) { · 235 unmodified lines
1749}1772}
1750 1773
1751void Application::updateLOD() {1774void Application::updateLOD() {
1775 PerformanceTimer perfTimer("idle/update/updateLOD");
1752 // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode1776 // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
1753 if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {1777 if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
1754 Menu::getInstance()->autoAdjustLOD(_fps);1778 Menu::getInstance()->autoAdjustLOD(_fps);
@@ -1758,6 +1782,7 @@ void Application::updateLOD() { · 3 unmodified lines
1758}1782}
1759 1783
1760void Application::updateMouseRay() {1784void Application::updateMouseRay() {
1785 PerformanceTimer perfTimer("idle/update/updateMouseRay");
1761 1786
1762 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1787 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1763 PerformanceWarning warn(showWarnings, "Application::updateMouseRay()");1788 PerformanceWarning warn(showWarnings, "Application::updateMouseRay()");
@@ -1790,6 +1815,7 @@ void Application::updateMouseRay() { · 26 unmodified lines
1790}1815}
1791 1816
1792void Application::updateFaceshift() {1817void Application::updateFaceshift() {
1818 PerformanceTimer perfTimer("idle/update/updateFaceshift");
1793 1819
1794 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1820 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1795 PerformanceWarning warn(showWarnings, "Application::updateFaceshift()");1821 PerformanceWarning warn(showWarnings, "Application::updateFaceshift()");
@@ -1804,6 +1830,7 @@ void Application::updateFaceshift() { · 8 unmodified lines
1804}1830}
1805 1831
1806void Application::updateVisage() {1832void Application::updateVisage() {
1833 PerformanceTimer perfTimer("idle/update/updateVisage");
1807 1834
1808 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1835 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1809 PerformanceWarning warn(showWarnings, "Application::updateVisage()");1836 PerformanceWarning warn(showWarnings, "Application::updateVisage()");
@@ -1813,6 +1840,7 @@ void Application::updateVisage() { · 3 unmodified lines
1813}1840}
1814 1841
1815void Application::updateMyAvatarLookAtPosition() {1842void Application::updateMyAvatarLookAtPosition() {
1843 PerformanceTimer perfTimer("idle/update/updateMyAvatarLookAtPosition");
1816 1844
1817 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1845 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1818 PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");1846 PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
@@ -1844,7 +1872,8 @@ void Application::updateMyAvatarLookAtPosition() { · 25 unmodified lines
1844 }1872 }
1845 } else {1873 } else {
1846 // I am not looking at anyone else, so just look forward1874 // I am not looking at anyone else, so just look forward
1847 lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() + (_myAvatar->getHead()->getFinalOrientation() * glm::vec3(0.f, 0.f, -TREE_SCALE));1875 lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() +
1876 (_myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.f, 0.f, -TREE_SCALE));
1848 }1877 }
1849 // TODO: Add saccade to mouse pointer when stable, IF not looking at someone (since we know we are looking at it)1878 // TODO: Add saccade to mouse pointer when stable, IF not looking at someone (since we know we are looking at it)
1850 /*1879 /*
@@ -1878,12 +1907,13 @@ void Application::updateMyAvatarLookAtPosition() { · 27 unmodified lines
1878}1907}
1879 1908
1880void Application::updateThreads(float deltaTime) {1909void Application::updateThreads(float deltaTime) {
1910 PerformanceTimer perfTimer("idle/update/updateThreads");
1881 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1911 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1882 PerformanceWarning warn(showWarnings, "Application::updateThreads()");1912 PerformanceWarning warn(showWarnings, "Application::updateThreads()");
1883 1913
1884 // parse voxel packets1914 // parse voxel packets
1885 if (!_enableProcessVoxelsThread) {1915 if (!_enableProcessVoxelsThread) {
1886 _voxelProcessor.threadRoutine();1916 _octreeProcessor.threadRoutine();
1887 _voxelHideShowThread.threadRoutine();1917 _voxelHideShowThread.threadRoutine();
1888 _voxelEditSender.threadRoutine();1918 _voxelEditSender.threadRoutine();
1889 _particleEditSender.threadRoutine();1919 _particleEditSender.threadRoutine();
@@ -1892,6 +1922,7 @@ void Application::updateThreads(float deltaTime) { · 2 unmodified lines
1892}1922}
1893 1923
1894void Application::updateMetavoxels(float deltaTime) {1924void Application::updateMetavoxels(float deltaTime) {
1925 PerformanceTimer perfTimer("idle/update/updateMetavoxels");
1895 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1926 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1896 PerformanceWarning warn(showWarnings, "Application::updateMetavoxels()");1927 PerformanceWarning warn(showWarnings, "Application::updateMetavoxels()");
1897 1928
@@ -1921,6 +1952,7 @@ void Application::cameraMenuChanged() { · 23 unmodified lines
1921}1952}
1922 1953
1923void Application::updateCamera(float deltaTime) {1954void Application::updateCamera(float deltaTime) {
1955 PerformanceTimer perfTimer("idle/update/updateCamera");
1924 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1956 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1925 PerformanceWarning warn(showWarnings, "Application::updateCamera()");1957 PerformanceWarning warn(showWarnings, "Application::updateCamera()");
1926 1958
@@ -1938,6 +1970,7 @@ void Application::updateCamera(float deltaTime) { · 11 unmodified lines
1938}1970}
1939 1971
1940void Application::updateDialogs(float deltaTime) {1972void Application::updateDialogs(float deltaTime) {
1973 PerformanceTimer perfTimer("idle/update/updateDialogs");
1941 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1974 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1942 PerformanceWarning warn(showWarnings, "Application::updateDialogs()");1975 PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
1943 1976
@@ -1954,6 +1987,7 @@ void Application::updateDialogs(float deltaTime) { · 10 unmodified lines
1954}1987}
1955 1988
1956void Application::updateCursor(float deltaTime) {1989void Application::updateCursor(float deltaTime) {
1990 PerformanceTimer perfTimer("idle/update/updateCursor");
1957 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1991 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1958 PerformanceWarning warn(showWarnings, "Application::updateCursor()");1992 PerformanceWarning warn(showWarnings, "Application::updateCursor()");
1959 1993
@@ -1978,51 +2012,87 @@ void Application::updateCursor(float deltaTime) { · 18 unmodified lines
1978}2012}
1979 2013
1980void Application::update(float deltaTime) {2014void Application::update(float deltaTime) {
2015 //PerformanceTimer perfTimer("idle/update"); // NOTE: we track this above in Application::idle()
2016
1981 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);2017 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1982 PerformanceWarning warn(showWarnings, "Application::update()");2018 PerformanceWarning warn(showWarnings, "Application::update()");
1983 2019
1984 updateLOD();2020 updateLOD();
1985 2021 updateMouseRay(); // check what's under the mouse and update the mouse voxel
1986 // check what's under the mouse and update the mouse voxel
1987 updateMouseRay();
1988
1989 updateFaceshift();2022 updateFaceshift();
1990 updateVisage();2023 updateVisage();
1991 _myAvatar->updateLookAtTargetAvatar();2024
2025 {
2026 PerformanceTimer perfTimer("idle/update/updateLookAtTargetAvatar");
2027 _myAvatar->updateLookAtTargetAvatar();
2028 }
1992 updateMyAvatarLookAtPosition();2029 updateMyAvatarLookAtPosition();
1993 _sixenseManager.update(deltaTime);2030 {
1994 _joystickManager.update();2031 PerformanceTimer perfTimer("idle/update/sixense,joystick,prioVR");
1995 _prioVR.update(deltaTime);2032 _sixenseManager.update(deltaTime);
1996 updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes2033 _joystickManager.update();
2034 _prioVR.update(deltaTime);
2035 }
2036
2037 {
2038 PerformanceTimer perfTimer("idle/update/updateMyAvatar");
2039 updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
2040 }
2041
1997 updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...2042 updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
1998 _avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...2043
2044 {
2045 PerformanceTimer perfTimer("idle/update/_avatarManager");
2046 _avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...
2047 }
1999 updateMetavoxels(deltaTime); // update metavoxels2048 updateMetavoxels(deltaTime); // update metavoxels
2000 updateCamera(deltaTime); // handle various camera tweaks like off axis projection2049 updateCamera(deltaTime); // handle various camera tweaks like off axis projection
2001 updateDialogs(deltaTime); // update various stats dialogs if present2050 updateDialogs(deltaTime); // update various stats dialogs if present
2002 updateCursor(deltaTime); // Handle cursor updates2051 updateCursor(deltaTime); // Handle cursor updates
2003 2052
2004 _particles.update(); // update the particles...2053 {
2005 _particleCollisionSystem.update(); // collide the particles...2054 PerformanceTimer perfTimer("idle/update/_particles");
2055 _particles.update(); // update the particles...
2056 }
2057 {
2058 PerformanceTimer perfTimer("idle/update/_particleCollisionSystem");
2059 _particleCollisionSystem.update(); // collide the particles...
2060 }
2006 2061
2007 _models.update(); // update the models...2062 {
2063 PerformanceTimer perfTimer("idle/update/_models");
2064 _models.update(); // update the models...
2065 }
2008 2066
2009 _overlays.update(deltaTime);2067 {
2068 PerformanceTimer perfTimer("idle/update/_overlays");
2069 _overlays.update(deltaTime);
2070 }
2010 2071
2011 // let external parties know we're updating2072 {
2012 emit simulating(deltaTime);2073 PerformanceTimer perfTimer("idle/update/emit simulating");
2074 // let external parties know we're updating
2075 emit simulating(deltaTime);
2076 }
2013}2077}
2014 2078
2015void Application::updateMyAvatar(float deltaTime) {2079void Application::updateMyAvatar(float deltaTime) {
2080 PerformanceTimer perfTimer("updateMyAvatar");
2016 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);2081 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
2017 PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()");2082 PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()");
2018 2083
2019 _myAvatar->update(deltaTime);2084 {
2020 2085 PerformanceTimer perfTimer("updateMyAvatar/_myAvatar->update()");
2021 // send head/hand data to the avatar mixer and voxel server2086 _myAvatar->update(deltaTime);
2022 QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData);2087 }
2023 packet.append(_myAvatar->toByteArray());
2024 2088
2025 controlledBroadcastToNodes(packet, NodeSet() << NodeType::AvatarMixer);2089 {
2090 // send head/hand data to the avatar mixer and voxel server
2091 PerformanceTimer perfTimer("updateMyAvatar/sendToAvatarMixer");
2092 QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData);
2093 packet.append(_myAvatar->toByteArray());
2094 controlledBroadcastToNodes(packet, NodeSet() << NodeType::AvatarMixer);
2095 }
2026 2096
2027 // Update _viewFrustum with latest camera and view frustum data...2097 // Update _viewFrustum with latest camera and view frustum data...
2028 // NOTE: we get this from the view frustum, to make it simpler, since the2098 // NOTE: we get this from the view frustum, to make it simpler, since the
@@ -2030,25 +2100,121 @@ void Application::updateMyAvatar(float deltaTime) { · 1 unmodified line
2030 // We could optimize this to not actually load the viewFrustum, since we don't2100 // We could optimize this to not actually load the viewFrustum, since we don't
2031 // actually need to calculate the view frustum planes to send these details2101 // actually need to calculate the view frustum planes to send these details
2032 // to the server.2102 // to the server.
2033 loadViewFrustum(_myCamera, _viewFrustum);2103 {
2104 PerformanceTimer perfTimer("updateMyAvatar/loadViewFrustum");
2105 loadViewFrustum(_myCamera, _viewFrustum);
2106 }
2034 2107
2035 // Update my voxel servers with my current voxel query...2108 // Update my voxel servers with my current voxel query...
2036 quint64 now = usecTimestampNow();2109 {
2037 quint64 sinceLastQuery = now - _lastQueriedTime;2110 PerformanceTimer perfTimer("updateMyAvatar/queryOctree");
2038 const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;2111 quint64 now = usecTimestampNow();
2039 bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY;2112 quint64 sinceLastQuery = now - _lastQueriedTime;
2040 bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum);2113 const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
2114 bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY;
2115 bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum);
2041 2116
2042 // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it2117 // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it
2043 if (queryIsDue || viewIsDifferentEnough) {2118 if (queryIsDue || viewIsDifferentEnough) {
2044 _lastQueriedTime = now;2119 _lastQueriedTime = now;
2045 queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);2120 queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
2046 queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);2121 queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
2047 queryOctree(NodeType::ModelServer, PacketTypeModelQuery, _modelServerJurisdictions);2122 queryOctree(NodeType::ModelServer, PacketTypeModelQuery, _modelServerJurisdictions);
2048 _lastQueriedViewFrustum = _viewFrustum;2123 _lastQueriedViewFrustum = _viewFrustum;
2124 }
2125 }
2126
2127 // sent nack packets containing missing sequence numbers of received packets from nodes
2128 {
2129 quint64 now = usecTimestampNow();
2130 quint64 sinceLastNack = now - _lastNackTime;
2131 const quint64 TOO_LONG_SINCE_LAST_NACK = 1 * USECS_PER_SECOND;
2132 if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) {
2133 _lastNackTime = now;
2134 sendNackPackets();
2135 }
2049 }2136 }
2050}2137}
2051 2138
2139int Application::sendNackPackets() {
2140
2141 if (Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
2142 return 0;
2143 }
2144
2145 int packetsSent = 0;
2146 char packet[MAX_PACKET_SIZE];
2147
2148 // iterates thru all nodes in NodeList
2149 foreach(const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
2150
2151 if (node->getActiveSocket() &&
2152 ( node->getType() == NodeType::VoxelServer
2153 || node->getType() == NodeType::ParticleServer
2154 || node->getType() == NodeType::ModelServer)
2155 ) {
2156
2157 QUuid nodeUUID = node->getUUID();
2158
2159 // if there are octree packets from this node that are waiting to be processed,
2160 // don't send a NACK since the missing packets may be among those waiting packets.
2161 if (_octreeProcessor.hasPacketsToProcessFrom(nodeUUID)) {
2162 continue;
2163 }
2164
2165 _octreeSceneStatsLock.lockForRead();
2166
2167 // retreive octree scene stats of this node
2168 if (_octreeServerSceneStats.find(nodeUUID) == _octreeServerSceneStats.end()) {
2169 _octreeSceneStatsLock.unlock();
2170 continue;
2171 }
2172 OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID];
2173
2174 // make copy of missing sequence numbers from stats
2175 const QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers = stats.getMissingSequenceNumbers();
2176
2177 _octreeSceneStatsLock.unlock();
2178
2179 // construct nack packet(s) for this node
2180 int numSequenceNumbersAvailable = missingSequenceNumbers.size();
2181 QSet<OCTREE_PACKET_SEQUENCE>::const_iterator missingSequenceNumbersIterator = missingSequenceNumbers.constBegin();
2182 while (numSequenceNumbersAvailable > 0) {
2183
2184 char* dataAt = packet;
2185 int bytesRemaining = MAX_PACKET_SIZE;
2186
2187 // pack header
2188 int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack);
2189 dataAt += numBytesPacketHeader;
2190 bytesRemaining -= numBytesPacketHeader;
2191
2192 // calculate and pack the number of sequence numbers
2193 int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE);
2194 uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor);
2195 uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt;
2196 *numSequenceNumbersAt = numSequenceNumbers;
2197 dataAt += sizeof(uint16_t);
2198
2199 // pack sequence numbers
2200 for (int i = 0; i < numSequenceNumbers; i++) {
2201 OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt;
2202 *sequenceNumberAt = *missingSequenceNumbersIterator;
2203 dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
2204
2205 missingSequenceNumbersIterator++;
2206 }
2207 numSequenceNumbersAvailable -= numSequenceNumbers;
2208
2209 // send it
2210 NodeList::getInstance()->writeUnverifiedDatagram(packet, dataAt - packet, node);
2211 packetsSent++;
2212 }
2213 }
2214 }
2215 return packetsSent;
2216}
2217
2052void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {2218void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {
2053 2219
2054 // if voxels are disabled, then don't send this at all...2220 // if voxels are disabled, then don't send this at all...
@@ -2104,10 +2270,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 49 unmodified lines
2104 if (rootCode) {2270 if (rootCode) {
2105 VoxelPositionSize rootDetails;2271 VoxelPositionSize rootDetails;
2106 voxelDetailsForCode(rootCode, rootDetails);2272 voxelDetailsForCode(rootCode, rootDetails);
2107 AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);2273 AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
2108 serverBounds.scale(TREE_SCALE);2274 serverBounds.scale(TREE_SCALE);
2109 2275
2110 ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);2276 ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
2111 2277
2112 if (serverFrustumLocation != ViewFrustum::OUTSIDE) {2278 if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
2113 inViewServers++;2279 inViewServers++;
@@ -2170,10 +2336,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 56 unmodified lines
2170 if (rootCode) {2336 if (rootCode) {
2171 VoxelPositionSize rootDetails;2337 VoxelPositionSize rootDetails;
2172 voxelDetailsForCode(rootCode, rootDetails);2338 voxelDetailsForCode(rootCode, rootDetails);
2173 AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);2339 AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
2174 serverBounds.scale(TREE_SCALE);2340 serverBounds.scale(TREE_SCALE);
2175 2341
2176 ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);2342 ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
2177 if (serverFrustumLocation != ViewFrustum::OUTSIDE) {2343 if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
2178 inView = true;2344 inView = true;
2179 } else {2345 } else {
@@ -2273,88 +2439,122 @@ glm::vec3 Application::getSunDirection() { · 93 unmodified lines
2273}2439}
2274 2440
2275void Application::updateShadowMap() {2441void Application::updateShadowMap() {
2442 PerformanceTimer perfTimer("paintGL/updateShadowMap");
2276 QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject();2443 QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject();
2277 fbo->bind();2444 fbo->bind();
2278 glEnable(GL_DEPTH_TEST);2445 glEnable(GL_DEPTH_TEST);
2279 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);2446 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2280 2447
2281 glViewport(0, 0, fbo->width(), fbo->height());
2282
2283 glm::vec3 lightDirection = -getSunDirection();2448 glm::vec3 lightDirection = -getSunDirection();
2284 glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection);2449 glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection);
2285 glm::quat inverseRotation = glm::inverse(rotation);2450 glm::quat inverseRotation = glm::inverse(rotation);
2286 float nearScale = 0.0f;2451
2287 const float MAX_SHADOW_DISTANCE = 2.0f;2452 const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f };
2288 float farScale = (MAX_SHADOW_DISTANCE - _viewFrustum.getNearClip()) /2453 const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f),
2289 (_viewFrustum.getFarClip() - _viewFrustum.getNearClip());2454 glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) };
2455
2456 float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip());
2290 loadViewFrustum(_myCamera, _viewFrustum);2457 loadViewFrustum(_myCamera, _viewFrustum);
2291 glm::vec3 points[] = {2458
2292 glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale),2459 int matrixCount = 1;
2293 glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale),2460 int targetSize = fbo->width();
2294 glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale),2461 float targetScale = 1.0f;
2295 glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale),2462 if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
2296 glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale),2463 matrixCount = CASCADED_SHADOW_MATRIX_COUNT;
2297 glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale),2464 targetSize = fbo->width() / 2;
2298 glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale),2465 targetScale = 0.5f;
2299 glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) };2466 }
2300 glm::vec3 center;2467 for (int i = 0; i < matrixCount; i++) {
2301 for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {2468 const glm::vec2& coord = MAP_COORDS[i];
2302 center += points[i];2469 glViewport(coord.s * fbo->width(), coord.t * fbo->height(), targetSize, targetSize);
2303 }2470
2304 center /= (float)(sizeof(points) / sizeof(points[0]));2471 float nearScale = SHADOW_MATRIX_DISTANCES[i] * frustumScale;
2305 float radius = 0.0f;2472 float farScale = SHADOW_MATRIX_DISTANCES[i + 1] * frustumScale;
2306 for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {2473 glm::vec3 points[] = {
2307 radius = qMax(radius, glm::distance(points[i], center));2474 glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale),
2308 }2475 glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale),
2309 center = inverseRotation * center;2476 glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale),
2310 glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius);2477 glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale),
2311 glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius);2478 glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale),
2312 2479 glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale),
2313 // stretch out our extents in z so that we get all of the avatars2480 glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale),
2314 minima.z -= _viewFrustum.getFarClip() * 0.5f;2481 glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) };
2315 maxima.z += _viewFrustum.getFarClip() * 0.5f;2482 glm::vec3 center;
2316 2483 for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) {
2317 // save the combined matrix for rendering2484 center += points[j];
2318 _shadowMatrix = glm::transpose(glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) *2485 }
2319 glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation));2486 center /= (float)(sizeof(points) / sizeof(points[0]));
2320 2487 float radius = 0.0f;
2321 // update the shadow view frustum2488 for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) {
2322 _shadowViewFrustum.setPosition(rotation * ((minima + maxima) * 0.5f));2489 radius = qMax(radius, glm::distance(points[j], center));
2323 _shadowViewFrustum.setOrientation(rotation);2490 }
2324 _shadowViewFrustum.setOrthographic(true);2491 if (i < 3) {
2325 _shadowViewFrustum.setWidth(maxima.x - minima.x);2492 const float RADIUS_SCALE = 0.5f;
2326 _shadowViewFrustum.setHeight(maxima.y - minima.y);2493 _shadowDistances[i] = -glm::distance(_viewFrustum.getPosition(), center) - radius * RADIUS_SCALE;
2327 _shadowViewFrustum.setNearClip(minima.z);2494 }
2328 _shadowViewFrustum.setFarClip(maxima.z);2495 center = inverseRotation * center;
2329 _shadowViewFrustum.setEyeOffsetPosition(glm::vec3());2496
2330 _shadowViewFrustum.setEyeOffsetOrientation(glm::quat());2497 // to reduce texture "shimmer," move in texel increments
2331 _shadowViewFrustum.calculate();2498 float texelSize = (2.0f * radius) / targetSize;
2499 center = glm::vec3(roundf(center.x / texelSize) * texelSize, roundf(center.y / texelSize) * texelSize,
2500 roundf(center.z / texelSize) * texelSize);
2501
2502 glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius);
2503 glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius);
2504
2505 // stretch out our extents in z so that we get all of the avatars
2506 minima.z -= _viewFrustum.getFarClip() * 0.5f;
2507 maxima.z += _viewFrustum.getFarClip() * 0.5f;
2508
2509 // save the combined matrix for rendering
2510 _shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) *
2511 glm::scale(glm::vec3(targetScale, targetScale, 1.0f)) *
2512 glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) *
2513 glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation));
2514
2515 // update the shadow view frustum
2516 _shadowViewFrustum.setPosition(rotation * ((minima + maxima) * 0.5f));
2517 _shadowViewFrustum.setOrientation(rotation);
2518 _shadowViewFrustum.setOrthographic(true);
2519 _shadowViewFrustum.setWidth(maxima.x - minima.x);
2520 _shadowViewFrustum.setHeight(maxima.y - minima.y);
2521 _shadowViewFrustum.setNearClip(minima.z);
2522 _shadowViewFrustum.setFarClip(maxima.z);
2523 _shadowViewFrustum.setEyeOffsetPosition(glm::vec3());
2524 _shadowViewFrustum.setEyeOffsetOrientation(glm::quat());
2525 _shadowViewFrustum.calculate();
2526
2527 glMatrixMode(GL_PROJECTION);
2528 glPushMatrix();
2529 glLoadIdentity();
2530 glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z);
2332 2531
2333 glMatrixMode(GL_PROJECTION);2532 glMatrixMode(GL_MODELVIEW);
2334 glPushMatrix();2533 glPushMatrix();
2335 glLoadIdentity();2534 glLoadIdentity();
2336 glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z);2535 glm::vec3 axis = glm::axis(inverseRotation);
2536 glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z);
2337 2537
2338 glMatrixMode(GL_MODELVIEW);2538 // store view matrix without translation, which we'll use for precision-sensitive objects
2339 glPushMatrix();2539 updateUntranslatedViewMatrix();
2340 glLoadIdentity();
2341 glm::vec3 axis = glm::axis(inverseRotation);
2342 glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z);
2343 2540
2344 // store view matrix without translation, which we'll use for precision-sensitive objects2541 glEnable(GL_POLYGON_OFFSET_FILL);
2345 updateUntranslatedViewMatrix();2542 glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt
2346 2543
2347 _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE);2544 _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE);
2348 _particles.render(OctreeRenderer::SHADOW_RENDER_MODE);2545 _particles.render(OctreeRenderer::SHADOW_RENDER_MODE);
2349 _models.render(OctreeRenderer::SHADOW_RENDER_MODE);2546 _models.render(OctreeRenderer::SHADOW_RENDER_MODE);
2350 2547
2351 glPopMatrix();2548 glDisable(GL_POLYGON_OFFSET_FILL);
2352 2549
2353 glMatrixMode(GL_PROJECTION);2550 glPopMatrix();
2354 glPopMatrix();
2355 2551
2356 glMatrixMode(GL_MODELVIEW);2552 glMatrixMode(GL_PROJECTION);
2553 glPopMatrix();
2357 2554
2555 glMatrixMode(GL_MODELVIEW);
2556 }
2557
2358 fbo->release();2558 fbo->release();
2359 2559
2360 glViewport(0, 0, _glWidget->width(), _glWidget->height());2560 glViewport(0, 0, _glWidget->width(), _glWidget->height());
@@ -2401,6 +2601,7 @@ QImage Application::renderAvatarBillboard() { · 40 unmodified lines
2401}2601}
2402 2602
2403void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {2603void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
2604 PerformanceTimer perfTimer("paintGL/displaySide");
2404 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");2605 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
2405 // transform by eye offset2606 // transform by eye offset
2406 2607
@@ -2433,9 +2634,27 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 26 unmodified lines
2433 glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z);2634 glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z);
2434 2635
2435 // Setup 3D lights (after the camera transform, so that they are positioned in world space)2636 // Setup 3D lights (after the camera transform, so that they are positioned in world space)
2436 setupWorldLight();2637 {
2638 PerformanceTimer perfTimer("paintGL/displaySide/setupWorldLight");
2639 setupWorldLight();
2640 }
2641
2642 // setup shadow matrices (again, after the camera transform)
2643 int shadowMatrixCount = 0;
2644 if (Menu::getInstance()->isOptionChecked(MenuOption::SimpleShadows)) {
2645 shadowMatrixCount = 1;
2646 } else if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
2647 shadowMatrixCount = CASCADED_SHADOW_MATRIX_COUNT;
2648 }
2649 for (int i = shadowMatrixCount - 1; i >= 0; i--) {
2650 glActiveTexture(GL_TEXTURE0 + i);
2651 glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][0]);
2652 glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][1]);
2653 glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][2]);
2654 }
2437 2655
2438 if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {2656 if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
2657 PerformanceTimer perfTimer("paintGL/displaySide/stars");
2439 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2658 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2440 "Application::displaySide() ... stars...");2659 "Application::displaySide() ... stars...");
2441 if (!_stars.isStarsLoaded()) {2660 if (!_stars.isStarsLoaded()) {
@@ -2464,6 +2683,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 22 unmodified lines
2464 2683
2465 // draw the sky dome2684 // draw the sky dome
2466 if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {2685 if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
2686 PerformanceTimer perfTimer("paintGL/displaySide/atmosphere");
2467 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2687 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2468 "Application::displaySide() ... atmosphere...");2688 "Application::displaySide() ... atmosphere...");
2469 _environment.renderAtmospheres(whichCamera);2689 _environment.renderAtmospheres(whichCamera);
@@ -2483,10 +2703,14 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 13 unmodified lines
2483 glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR);2703 glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR);
2484 2704
2485 // draw the audio reflector overlay2705 // draw the audio reflector overlay
2486 _audioReflector.render();2706 {
2487 2707 PerformanceTimer perfTimer("paintGL/displaySide/audioReflector");
2708 _audioReflector.render();
2709 }
2710
2488 // Draw voxels2711 // Draw voxels
2489 if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {2712 if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
2713 PerformanceTimer perfTimer("paintGL/displaySide/voxels");
2490 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2714 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2491 "Application::displaySide() ... voxels...");2715 "Application::displaySide() ... voxels...");
2492 _voxels.render();2716 _voxels.render();
@@ -2494,12 +2718,14 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
2494 2718
2495 // also, metavoxels2719 // also, metavoxels
2496 if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) {2720 if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) {
2721 PerformanceTimer perfTimer("paintGL/displaySide/metavoxels");
2497 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2722 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2498 "Application::displaySide() ... metavoxels...");2723 "Application::displaySide() ... metavoxels...");
2499 _metavoxels.render();2724 _metavoxels.render();
2500 }2725 }
2501 2726
2502 if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {2727 if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
2728 PerformanceTimer perfTimer("paintGL/displaySide/buckyBalls");
2503 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2729 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2504 "Application::displaySide() ... bucky balls...");2730 "Application::displaySide() ... bucky balls...");
2505 _buckyBalls.render();2731 _buckyBalls.render();
@@ -2507,6 +2733,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
2507 2733
2508 // render particles...2734 // render particles...
2509 if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) {2735 if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) {
2736 PerformanceTimer perfTimer("paintGL/displaySide/particles");
2510 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2737 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2511 "Application::displaySide() ... particles...");2738 "Application::displaySide() ... particles...");
2512 _particles.render();2739 _particles.render();
@@ -2514,6 +2741,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
2514 2741
2515 // render models...2742 // render models...
2516 if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {2743 if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
2744 PerformanceTimer perfTimer("paintGL/displaySide/models");
2517 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2745 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2518 "Application::displaySide() ... models...");2746 "Application::displaySide() ... models...");
2519 _models.render();2747 _models.render();
@@ -2521,6 +2749,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
2521 2749
2522 // render the ambient occlusion effect if enabled2750 // render the ambient occlusion effect if enabled
2523 if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {2751 if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
2752 PerformanceTimer perfTimer("paintGL/displaySide/AmbientOcclusion");
2524 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2753 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2525 "Application::displaySide() ... AmbientOcclusion...");2754 "Application::displaySide() ... AmbientOcclusion...");
2526 _ambientOcclusionEffect.render();2755 _ambientOcclusionEffect.render();
@@ -2534,16 +2763,21 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 7 unmodified lines
2534 }2763 }
2535 2764
2536 bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);2765 bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
2537 _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly);2766 {
2767 PerformanceTimer perfTimer("paintGL/displaySide/renderAvatars");
2768 _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly);
2769 }
2538 2770
2539 if (!selfAvatarOnly) {2771 if (!selfAvatarOnly) {
2540 // Render the world box2772 // Render the world box
2541 if (whichCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {2773 if (whichCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
2774 PerformanceTimer perfTimer("paintGL/displaySide/renderWorldBox");
2542 renderWorldBox();2775 renderWorldBox();
2543 }2776 }
2544 2777
2545 // brad's frustum for debugging2778 // view frustum for debugging
2546 if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum) && whichCamera.getMode() != CAMERA_MODE_MIRROR) {2779 if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum) && whichCamera.getMode() != CAMERA_MODE_MIRROR) {
2780 PerformanceTimer perfTimer("paintGL/displaySide/ViewFrustum");
2547 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2781 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2548 "Application::displaySide() ... renderViewFrustum...");2782 "Application::displaySide() ... renderViewFrustum...");
2549 renderViewFrustum(_viewFrustum);2783 renderViewFrustum(_viewFrustum);
@@ -2551,8 +2785,10 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
2551 2785
2552 // render voxel fades if they exist2786 // render voxel fades if they exist
2553 if (_voxelFades.size() > 0) {2787 if (_voxelFades.size() > 0) {
2788 PerformanceTimer perfTimer("paintGL/displaySide/voxel fades");
2554 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),2789 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
2555 "Application::displaySide() ... voxel fades...");2790 "Application::displaySide() ... voxel fades...");
2791 _voxelFadesLock.lockForWrite();
2556 for(std::vector<VoxelFade>::iterator fade = _voxelFades.begin(); fade != _voxelFades.end();) {2792 for(std::vector<VoxelFade>::iterator fade = _voxelFades.begin(); fade != _voxelFades.end();) {
2557 fade->render();2793 fade->render();
2558 if(fade->isDone()) {2794 if(fade->isDone()) {
@@ -2561,13 +2797,20 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 2 unmodified lines
2561 ++fade;2797 ++fade;
2562 }2798 }
2563 }2799 }
2800 _voxelFadesLock.unlock();
2564 }2801 }
2565 2802
2566 // give external parties a change to hook in2803 // give external parties a change to hook in
2567 emit renderingInWorldInterface();2804 {
2805 PerformanceTimer perfTimer("paintGL/displaySide/inWorldInterface");
2806 emit renderingInWorldInterface();
2807 }
2568 2808
2569 // render JS/scriptable overlays2809 // render JS/scriptable overlays
2570 _overlays.render3D();2810 {
2811 PerformanceTimer perfTimer("paintGL/displaySide/3dOverlays");
2812 _overlays.render3D();
2813 }
2571 }2814 }
2572}2815}
2573 2816
@@ -2597,183 +2840,6 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom · 23 unmodified lines
2597 _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);2840 _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
2598}2841}
2599 2842
2600const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f };
2601
2602void Application::displayOverlay() {
2603 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displayOverlay()");
2604
2605 // Render 2D overlay: I/O level bar graphs and text
2606 glMatrixMode(GL_PROJECTION);
2607 glPushMatrix();
2608
2609 glLoadIdentity();
2610 gluOrtho2D(0, _glWidget->width(), _glWidget->height(), 0);
2611 glDisable(GL_DEPTH_TEST);
2612 glDisable(GL_LIGHTING);
2613
2614 // Display a single screen-size quad to create an alpha blended 'collision' flash
2615 if (_audio.getCollisionFlashesScreen()) {
2616 float collisionSoundMagnitude = _audio.getCollisionSoundMagnitude();
2617 const float VISIBLE_COLLISION_SOUND_MAGNITUDE = 0.5f;
2618 if (collisionSoundMagnitude > VISIBLE_COLLISION_SOUND_MAGNITUDE) {
2619 renderCollisionOverlay(_glWidget->width(), _glWidget->height(), _audio.getCollisionSoundMagnitude());
2620 }
2621 }
2622
2623 // Audio VU Meter and Mute Icon
2624 const int MUTE_ICON_SIZE = 24;
2625 const int AUDIO_METER_INSET = 2;
2626 const int MUTE_ICON_PADDING = 10;
2627 const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - AUDIO_METER_INSET - MUTE_ICON_PADDING;
2628 const int AUDIO_METER_SCALE_WIDTH = AUDIO_METER_WIDTH - 2 * AUDIO_METER_INSET;
2629 const int AUDIO_METER_HEIGHT = 8;
2630 const int AUDIO_METER_GAP = 5;
2631 const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET + AUDIO_METER_GAP;
2632
2633 int audioMeterY;
2634 if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
2635 audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_GAP + MUTE_ICON_PADDING;
2636 } else {
2637 audioMeterY = AUDIO_METER_GAP + MUTE_ICON_PADDING;
2638 }
2639
2640 const float AUDIO_METER_BLUE[] = {0.0, 0.0, 1.0};
2641 const float AUDIO_METER_GREEN[] = {0.0, 1.0, 0.0};
2642 const float AUDIO_METER_RED[] = {1.0, 0.0, 0.0};
2643 const float AUDIO_GREEN_START = 0.25 * AUDIO_METER_SCALE_WIDTH;
2644 const float AUDIO_RED_START = 0.80 * AUDIO_METER_SCALE_WIDTH;
2645 const float CLIPPING_INDICATOR_TIME = 1.0f;
2646 const float AUDIO_METER_AVERAGING = 0.5;
2647 const float LOG2 = log(2.f);
2648 const float METER_LOUDNESS_SCALE = 2.8f / 5.f;
2649 const float LOG2_LOUDNESS_FLOOR = 11.f;
2650 float audioLevel = 0.f;
2651 float loudness = _audio.getLastInputLoudness() + 1.f;
2652
2653 _trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness;
2654 float log2loudness = log(_trailingAudioLoudness) / LOG2;
2655
2656 if (log2loudness <= LOG2_LOUDNESS_FLOOR) {
2657 audioLevel = (log2loudness / LOG2_LOUDNESS_FLOOR) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
2658 } else {
2659 audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.f)) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
2660 }
2661 if (audioLevel > AUDIO_METER_SCALE_WIDTH) {
2662 audioLevel = AUDIO_METER_SCALE_WIDTH;
2663 }
2664 bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));
2665
2666 if ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
2667 const float MAX_MAGNITUDE = 0.7f;
2668 float magnitude = MAX_MAGNITUDE * (1 - _audio.getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
2669 renderCollisionOverlay(_glWidget->width(), _glWidget->height(), magnitude, 1.0f);
2670 }
2671
2672 _audio.renderToolBox(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP,
2673 audioMeterY,
2674 Menu::getInstance()->isOptionChecked(MenuOption::Mirror));
2675
2676 _audio.renderScope(_glWidget->width(), _glWidget->height());
2677
2678 glBegin(GL_QUADS);
2679 if (isClipping) {
2680 glColor3f(1, 0, 0);
2681 } else {
2682 glColor3f(0.475f, 0.475f, 0.475f);
2683 }
2684
2685 audioMeterY += AUDIO_METER_HEIGHT;
2686
2687 glColor3f(0, 0, 0);
2688 // Draw audio meter background Quad
2689 glVertex2i(AUDIO_METER_X, audioMeterY);
2690 glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY);
2691 glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY + AUDIO_METER_HEIGHT);
2692 glVertex2i(AUDIO_METER_X, audioMeterY + AUDIO_METER_HEIGHT);
2693
2694
2695 if (audioLevel > AUDIO_RED_START) {
2696 if (!isClipping) {
2697 glColor3fv(AUDIO_METER_RED);
2698 } else {
2699 glColor3f(1, 1, 1);
2700 }
2701 // Draw Red Quad
2702 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_INSET);
2703 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET);
2704 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
2705 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
2706 audioLevel = AUDIO_RED_START;
2707 }
2708 if (audioLevel > AUDIO_GREEN_START) {
2709 if (!isClipping) {
2710 glColor3fv(AUDIO_METER_GREEN);
2711 } else {
2712 glColor3f(1, 1, 1);
2713 }
2714 // Draw Green Quad
2715 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_INSET);
2716 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET);
2717 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
2718 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
2719 audioLevel = AUDIO_GREEN_START;
2720 }
2721 // Draw Blue Quad
2722 if (!isClipping) {
2723 glColor3fv(AUDIO_METER_BLUE);
2724 } else {
2725 glColor3f(1, 1, 1);
2726 }
2727 // Draw Blue (low level) quad
2728 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_INSET);
2729 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET);
2730 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
2731 glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
2732 glEnd();
2733
2734
2735 if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) {
2736 _myAvatar->renderHeadMouse(_glWidget->width(), _glWidget->height());
2737 }
2738
2739 // Display stats and log text onscreen
2740 glLineWidth(1.0f);
2741 glPointSize(1.0f);
2742
2743 if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
2744 // let's set horizontal offset to give stats some margin to mirror
2745 int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2;
2746 int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount();
2747 // Onscreen text about position, servers, etc
2748 Stats::getInstance()->display(WHITE_TEXT, horizontalOffset, _fps, _packetsPerSecond, _bytesPerSecond, voxelPacketsToProcess);
2749 // Bandwidth meter
2750 if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) {
2751 Stats::drawBackground(0x33333399, _glWidget->width() - 296, _glWidget->height() - 68, 296, 68);
2752 _bandwidthMeter.render(_glWidget->width(), _glWidget->height());
2753 }
2754 }
2755
2756 // Show on-screen msec timer
2757 if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) {
2758 char frameTimer[10];
2759 quint64 mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5);
2760 sprintf(frameTimer, "%d\n", (int)(mSecsNow % 1000));
2761 int timerBottom =
2762 (Menu::getInstance()->isOptionChecked(MenuOption::Stats) &&
2763 Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth))
2764 ? 80 : 20;
2765 drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 0.0f, 0, frameTimer, WHITE_TEXT);
2766 }
2767 _nodeBoundsDisplay.drawOverlay();
2768
2769 // give external parties a change to hook in
2770 emit renderingOverlay();
2771
2772 _overlays.render2D();
2773
2774 glPopMatrix();
2775}
2776
2777glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {2843glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
2778 float horizontalScale = _glWidget->width() / 2.0f;2844 float horizontalScale = _glWidget->width() / 2.0f;
2779 float verticalScale = _glWidget->height() / 2.0f;2845 float verticalScale = _glWidget->height() / 2.0f;
@@ -2845,16 +2911,19 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 65 unmodified lines
2845 glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation();2911 glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation();
2846 glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation();2912 glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation();
2847 2913
2848 // get the eye positions relative to the neck and use them to set the face translation2914 // get the neck position so we can translate the face relative to it
2849 glm::vec3 leftEyePosition, rightEyePosition;
2850 _myAvatar->getHead()->getFaceModel().setTranslation(glm::vec3());
2851 _myAvatar->getHead()->getFaceModel().getEyePositions(leftEyePosition, rightEyePosition);
2852 _myAvatar->getHead()->getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f);
2853
2854 // get the neck position relative to the body and use it to set the skeleton translation
2855 glm::vec3 neckPosition;2915 glm::vec3 neckPosition;
2856 _myAvatar->getSkeletonModel().setTranslation(glm::vec3());2916 _myAvatar->getSkeletonModel().setTranslation(glm::vec3());
2857 _myAvatar->getSkeletonModel().getNeckPosition(neckPosition);2917 _myAvatar->getSkeletonModel().getNeckPosition(neckPosition);
2918
2919 // get the eye position relative to the body
2920 glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();
2921 float eyeHeight = eyePosition.y - _myAvatar->getPosition().y;
2922
2923 // set the translation of the face relative to the neck position
2924 _myAvatar->getHead()->getFaceModel().setTranslation(neckPosition - glm::vec3(0, eyeHeight, 0));
2925
2926 // translate the neck relative to the face
2858 _myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead()->getFaceModel().getTranslation() -2927 _myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead()->getFaceModel().getTranslation() -
2859 neckPosition);2928 neckPosition);
2860 2929
@@ -3122,6 +3191,17 @@ void Application::updateWindowTitle(){ · 261 unmodified lines
3122 QString username = AccountManager::getInstance().getAccountInfo().getUsername();3191 QString username = AccountManager::getInstance().getAccountInfo().getUsername();
3123 QString title = QString() + (!username.isEmpty() ? username + " @ " : QString())3192 QString title = QString() + (!username.isEmpty() ? username + " @ " : QString())
3124 + nodeList->getDomainHandler().getHostname() + buildVersion;3193 + nodeList->getDomainHandler().getHostname() + buildVersion;
3194
3195 AccountManager& accountManager = AccountManager::getInstance();
3196 if (accountManager.getAccountInfo().hasBalance()) {
3197 float creditBalance = accountManager.getAccountInfo().getBalance() / SATOSHIS_PER_CREDIT;
3198
3199 QString creditBalanceString;
3200 creditBalanceString.sprintf("%.8f", creditBalance);
3201
3202 title += " - ₵" + creditBalanceString;
3203 }
3204
3125 qDebug("Application title set to: %s", title.toStdString().c_str());3205 qDebug("Application title set to: %s", title.toStdString().c_str());
3126 _window->setWindowTitle(title);3206 _window->setWindowTitle(title);
3127}3207}
@@ -3161,9 +3241,15 @@ void Application::domainChanged(const QString& domainHostname) { · 33 unmodified lines
3161 _environment.resetToDefault();3241 _environment.resetToDefault();
3162 3242
3163 // reset our node to stats and node to jurisdiction maps... since these must be changing...3243 // reset our node to stats and node to jurisdiction maps... since these must be changing...
3244 _voxelServerJurisdictions.lockForWrite();
3164 _voxelServerJurisdictions.clear();3245 _voxelServerJurisdictions.clear();
3246 _voxelServerJurisdictions.unlock();
3247
3165 _octreeServerSceneStats.clear();3248 _octreeServerSceneStats.clear();
3249
3250 _particleServerJurisdictions.lockForWrite();
3166 _particleServerJurisdictions.clear();3251 _particleServerJurisdictions.clear();
3252 _particleServerJurisdictions.unlock();
3167 3253
3168 // reset the particle renderer3254 // reset the particle renderer
3169 _particles.clear();3255 _particles.clear();
@@ -3199,13 +3285,26 @@ void Application::nodeAdded(SharedNodePointer node) { · 29 unmodified lines
3199}3285}
3200 3286
3201void Application::nodeKilled(SharedNodePointer node) {3287void Application::nodeKilled(SharedNodePointer node) {
3288
3289 // These are here because connecting NodeList::nodeKilled to OctreePacketProcessor::nodeKilled doesn't work:
3290 // OctreePacketProcessor::nodeKilled is not being called when NodeList::nodeKilled is emitted.
3291 // This may have to do with GenericThread::threadRoutine() blocking the QThread event loop
3292
3293 _octreeProcessor.nodeKilled(node);
3294
3295 _voxelEditSender.nodeKilled(node);
3296 _particleEditSender.nodeKilled(node);
3297 _modelEditSender.nodeKilled(node);
3298
3202 if (node->getType() == NodeType::VoxelServer) {3299 if (node->getType() == NodeType::VoxelServer) {
3203 QUuid nodeUUID = node->getUUID();3300 QUuid nodeUUID = node->getUUID();
3204 // see if this is the first we've heard of this node...3301 // see if this is the first we've heard of this node...
3302 _voxelServerJurisdictions.lockForRead();
3205 if (_voxelServerJurisdictions.find(nodeUUID) != _voxelServerJurisdictions.end()) {3303 if (_voxelServerJurisdictions.find(nodeUUID) != _voxelServerJurisdictions.end()) {
3206 unsigned char* rootCode = _voxelServerJurisdictions[nodeUUID].getRootOctalCode();3304 unsigned char* rootCode = _voxelServerJurisdictions[nodeUUID].getRootOctalCode();
3207 VoxelPositionSize rootDetails;3305 VoxelPositionSize rootDetails;
3208 voxelDetailsForCode(rootCode, rootDetails);3306 voxelDetailsForCode(rootCode, rootDetails);
3307 _voxelServerJurisdictions.unlock();
3209 3308
3210 qDebug("voxel server going away...... v[%f, %f, %f, %f]",3309 qDebug("voxel server going away...... v[%f, %f, %f, %f]",
3211 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);3310 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
@@ -3216,12 +3315,16 @@ void Application::nodeKilled(SharedNodePointer node) { · 4 unmodified lines
3216 fade.voxelDetails = rootDetails;3315 fade.voxelDetails = rootDetails;
3217 const float slightly_smaller = 0.99f;3316 const float slightly_smaller = 0.99f;
3218 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;3317 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3318 _voxelFadesLock.lockForWrite();
3219 _voxelFades.push_back(fade);3319 _voxelFades.push_back(fade);
3320 _voxelFadesLock.unlock();
3220 }3321 }
3221 3322
3222 // If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server3323 // If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
3324 _voxelServerJurisdictions.lockForWrite();
3223 _voxelServerJurisdictions.erase(_voxelServerJurisdictions.find(nodeUUID));3325 _voxelServerJurisdictions.erase(_voxelServerJurisdictions.find(nodeUUID));
3224 }3326 }
3327 _voxelServerJurisdictions.unlock();
3225 3328
3226 // also clean up scene stats for that server3329 // also clean up scene stats for that server
3227 _octreeSceneStatsLock.lockForWrite();3330 _octreeSceneStatsLock.lockForWrite();
@@ -3233,10 +3336,12 @@ void Application::nodeKilled(SharedNodePointer node) { · 5 unmodified lines
3233 } else if (node->getType() == NodeType::ParticleServer) {3336 } else if (node->getType() == NodeType::ParticleServer) {
3234 QUuid nodeUUID = node->getUUID();3337 QUuid nodeUUID = node->getUUID();
3235 // see if this is the first we've heard of this node...3338 // see if this is the first we've heard of this node...
3339 _particleServerJurisdictions.lockForRead();
3236 if (_particleServerJurisdictions.find(nodeUUID) != _particleServerJurisdictions.end()) {3340 if (_particleServerJurisdictions.find(nodeUUID) != _particleServerJurisdictions.end()) {
3237 unsigned char* rootCode = _particleServerJurisdictions[nodeUUID].getRootOctalCode();3341 unsigned char* rootCode = _particleServerJurisdictions[nodeUUID].getRootOctalCode();
3238 VoxelPositionSize rootDetails;3342 VoxelPositionSize rootDetails;
3239 voxelDetailsForCode(rootCode, rootDetails);3343 voxelDetailsForCode(rootCode, rootDetails);
3344 _particleServerJurisdictions.unlock();
3240 3345
3241 qDebug("particle server going away...... v[%f, %f, %f, %f]",3346 qDebug("particle server going away...... v[%f, %f, %f, %f]",
3242 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);3347 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
@@ -3247,12 +3352,16 @@ void Application::nodeKilled(SharedNodePointer node) { · 4 unmodified lines
3247 fade.voxelDetails = rootDetails;3352 fade.voxelDetails = rootDetails;
3248 const float slightly_smaller = 0.99f;3353 const float slightly_smaller = 0.99f;
3249 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;3354 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3355 _voxelFadesLock.lockForWrite();
3250 _voxelFades.push_back(fade);3356 _voxelFades.push_back(fade);
3357 _voxelFadesLock.unlock();
3251 }3358 }
3252 3359
3253 // If the particle server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server3360 // If the particle server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
3361 _particleServerJurisdictions.lockForWrite();
3254 _particleServerJurisdictions.erase(_particleServerJurisdictions.find(nodeUUID));3362 _particleServerJurisdictions.erase(_particleServerJurisdictions.find(nodeUUID));
3255 }3363 }
3364 _particleServerJurisdictions.unlock();
3256 3365
3257 // also clean up scene stats for that server3366 // also clean up scene stats for that server
3258 _octreeSceneStatsLock.lockForWrite();3367 _octreeSceneStatsLock.lockForWrite();
@@ -3265,10 +3374,12 @@ void Application::nodeKilled(SharedNodePointer node) { · 6 unmodified lines
3265 3374
3266 QUuid nodeUUID = node->getUUID();3375 QUuid nodeUUID = node->getUUID();
3267 // see if this is the first we've heard of this node...3376 // see if this is the first we've heard of this node...
3377 _modelServerJurisdictions.lockForRead();
3268 if (_modelServerJurisdictions.find(nodeUUID) != _modelServerJurisdictions.end()) {3378 if (_modelServerJurisdictions.find(nodeUUID) != _modelServerJurisdictions.end()) {
3269 unsigned char* rootCode = _modelServerJurisdictions[nodeUUID].getRootOctalCode();3379 unsigned char* rootCode = _modelServerJurisdictions[nodeUUID].getRootOctalCode();
3270 VoxelPositionSize rootDetails;3380 VoxelPositionSize rootDetails;
3271 voxelDetailsForCode(rootCode, rootDetails);3381 voxelDetailsForCode(rootCode, rootDetails);
3382 _modelServerJurisdictions.unlock();
3272 3383
3273 qDebug("model server going away...... v[%f, %f, %f, %f]",3384 qDebug("model server going away...... v[%f, %f, %f, %f]",
3274 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);3385 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
@@ -3279,12 +3390,16 @@ void Application::nodeKilled(SharedNodePointer node) { · 4 unmodified lines
3279 fade.voxelDetails = rootDetails;3390 fade.voxelDetails = rootDetails;
3280 const float slightly_smaller = 0.99f;3391 const float slightly_smaller = 0.99f;
3281 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;3392 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3393 _voxelFadesLock.lockForWrite();
3282 _voxelFades.push_back(fade);3394 _voxelFades.push_back(fade);
3395 _voxelFadesLock.unlock();
3283 }3396 }
3284 3397
3285 // If the model server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server3398 // If the model server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
3399 _modelServerJurisdictions.lockForWrite();
3286 _modelServerJurisdictions.erase(_modelServerJurisdictions.find(nodeUUID));3400 _modelServerJurisdictions.erase(_modelServerJurisdictions.find(nodeUUID));
3287 }3401 }
3402 _modelServerJurisdictions.unlock();
3288 3403
3289 // also clean up scene stats for that server3404 // also clean up scene stats for that server
3290 _octreeSceneStatsLock.lockForWrite();3405 _octreeSceneStatsLock.lockForWrite();
@@ -3354,7 +3469,10 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin · 63 unmodified lines
3354 serverType = "Model";3469 serverType = "Model";
3355 }3470 }
3356 3471
3472 jurisdiction->lockForRead();
3357 if (jurisdiction->find(nodeUUID) == jurisdiction->end()) {3473 if (jurisdiction->find(nodeUUID) == jurisdiction->end()) {
3474 jurisdiction->unlock();
3475
3358 qDebug("stats from new %s server... [%f, %f, %f, %f]",3476 qDebug("stats from new %s server... [%f, %f, %f, %f]",
3359 qPrintable(serverType), rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);3477 qPrintable(serverType), rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
3360 3478
@@ -3364,8 +3482,12 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin · 3 unmodified lines
3364 fade.voxelDetails = rootDetails;3482 fade.voxelDetails = rootDetails;
3365 const float slightly_smaller = 0.99f;3483 const float slightly_smaller = 0.99f;
3366 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;3484 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3485 _voxelFadesLock.lockForWrite();
3367 _voxelFades.push_back(fade);3486 _voxelFades.push_back(fade);
3487 _voxelFadesLock.unlock();
3368 }3488 }
3489 } else {
3490 jurisdiction->unlock();
3369 }3491 }
3370 // store jurisdiction details for later use3492 // store jurisdiction details for later use
3371 // This is bit of fiddling is because JurisdictionMap assumes it is the owner of the values used to construct it3493 // This is bit of fiddling is because JurisdictionMap assumes it is the owner of the values used to construct it
@@ -3373,7 +3495,9 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin · 1 unmodified line
3373 // details from the OctreeSceneStats to construct the JurisdictionMap3495 // details from the OctreeSceneStats to construct the JurisdictionMap
3374 JurisdictionMap jurisdictionMap;3496 JurisdictionMap jurisdictionMap;
3375 jurisdictionMap.copyContents(temp.getJurisdictionRoot(), temp.getJurisdictionEndNodes());3497 jurisdictionMap.copyContents(temp.getJurisdictionRoot(), temp.getJurisdictionEndNodes());
3498 jurisdiction->lockForWrite();
3376 (*jurisdiction)[nodeUUID] = jurisdictionMap;3499 (*jurisdiction)[nodeUUID] = jurisdictionMap;
3500 jurisdiction->unlock();
3377 }3501 }
3378 return statsMessageLength;3502 return statsMessageLength;
3379}3503}
@@ -3416,21 +3540,31 @@ void Application::saveScripts() { · 36 unmodified lines
3416 _settings->endArray();3540 _settings->endArray();
3417}3541}
3418 3542
3419ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) {3543ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor, bool activateMainWindow) {
3420 if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptName) && !_scriptEnginesHash[scriptName]->isFinished()){3544 QUrl scriptUrl(scriptName);
3421 return _scriptEnginesHash[scriptName];3545 const QString& scriptURLString = scriptUrl.toString();
3546 if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor
3547 && !_scriptEnginesHash[scriptURLString]->isFinished()) {
3548
3549 return _scriptEnginesHash[scriptURLString];
3422 }3550 }
3423 3551
3424 // start the script on a new thread...3552 ScriptEngine* scriptEngine;
3425 QUrl scriptUrl(scriptName);3553 if (scriptName.isNull()) {
3426 ScriptEngine* scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface);3554 scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);
3427 _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine);3555 } else {
3556 // start the script on a new thread...
3557 scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface);
3558
3559 if (!scriptEngine->hasScript()) {
3560 qDebug() << "Application::loadScript(), script failed to load...";
3561 QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " failed to load.");
3562 return NULL;
3563 }
3428 3564
3429 if (!scriptEngine->hasScript()) {3565 _scriptEnginesHash.insertMulti(scriptURLString, scriptEngine);
3430 qDebug() << "Application::loadScript(), script failed to load...";3566 _runningScriptsWidget->setRunningScripts(getRunningScripts());
3431 return NULL;
3432 }3567 }
3433 _runningScriptsWidget->setRunningScripts(getRunningScripts());
3434 3568
3435 // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so3569 // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
3436 // we can use the same ones from the application.3570 // we can use the same ones from the application.
@@ -3471,6 +3605,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript · 34 unmodified lines
3471 scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());3605 scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
3472 scriptEngine->registerGlobalObject("AnimationCache", &_animationCache);3606 scriptEngine->registerGlobalObject("AnimationCache", &_animationCache);
3473 scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector);3607 scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector);
3608 scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance());
3474 3609
3475 QThread* workerThread = new QThread(this);3610 QThread* workerThread = new QThread(this);
3476 3611
@@ -3490,7 +3625,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript · 13 unmodified lines
3490 workerThread->start();3625 workerThread->start();
3491 3626
3492 // restore the main window's active state3627 // restore the main window's active state
3493 if (!loadScriptFromEditor) {3628 if (activateMainWindow && !loadScriptFromEditor) {
3494 _window->activateWindow();3629 _window->activateWindow();
3495 }3630 }
3496 bumpSettings();3631 bumpSettings();
@@ -3499,7 +3634,9 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript · 2 unmodified lines
3499}3634}
3500 3635
3501void Application::scriptFinished(const QString& scriptName) {3636void Application::scriptFinished(const QString& scriptName) {
3502 if (_scriptEnginesHash.remove(scriptName)) {3637 QHash<QString, ScriptEngine*>::iterator it = _scriptEnginesHash.find(scriptName);
3638 if (it != _scriptEnginesHash.end()) {
3639 _scriptEnginesHash.erase(it);
3503 _runningScriptsWidget->scriptStopped(scriptName);3640 _runningScriptsWidget->scriptStopped(scriptName);
3504 _runningScriptsWidget->setRunningScripts(getRunningScripts());3641 _runningScriptsWidget->setRunningScripts(getRunningScripts());
3505 bumpSettings();3642 bumpSettings();
@@ -3529,6 +3666,12 @@ void Application::reloadAllScripts() { · 23 unmodified lines
3529 stopAllScripts(true);3666 stopAllScripts(true);
3530}3667}
3531 3668
3669void Application::loadDefaultScripts() {
3670 if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
3671 loadScript(DEFAULT_SCRIPTS_JS_URL);
3672 }
3673}
3674
3532void Application::manageRunningScriptsWidgetVisibility(bool shown) {3675void Application::manageRunningScriptsWidgetVisibility(bool shown) {
3533 if (_runningScriptsWidgetWasVisible && shown) {3676 if (_runningScriptsWidgetWasVisible && shown) {
3534 _runningScriptsWidget->show();3677 _runningScriptsWidget->show();

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t