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
7474 #include "devices/TV3DManager.h"
7575 #include "renderer/ProgramObject.h"
7676
77+#include "scripting/AccountScriptingInterface.h"
7778 #include "scripting/AudioDeviceScriptingInterface.h"
7879 #include "scripting/ClipboardScriptingInterface.h"
7980 #include "scripting/MenuScriptingInterface.h"
@@ -103,18 +104,11 @@ const int STARTUP_JITTER_SAMPLES = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 2 · 23 unmodified lines
103104 // Startup optimistically with small jitter buffer that
104105 // will start playback on the second received audio packet.
105106
106−const int MIRROR_VIEW_TOP_PADDING = 5;
107−const int MIRROR_VIEW_LEFT_PADDING = 10;
108−const int MIRROR_VIEW_WIDTH = 265;
109−const int MIRROR_VIEW_HEIGHT = 215;
110−const float MIRROR_FULLSCREEN_DISTANCE = 0.35f;
111−const float MIRROR_REARVIEW_DISTANCE = 0.65f;
112−const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
113−const float MIRROR_FIELD_OF_VIEW = 30.0f;
114−
115107 const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml";
116108 const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";
117109
110+const QString DEFAULT_SCRIPTS_JS_URL = "http://public.highfidelity.io/scripts/defaultScripts.js";
111+
118112 void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
119113 if (message.size() > 0) {
120114 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
141135 _nodeThread(new QThread(this)),
142136 _datagramProcessor(),
143137 _frameCount(0),
144− _fps(120.0f),
138+ _fps(60.0f),
145139 _justStarted(true),
146140 _voxelImporter(NULL),
147141 _importSucceded(false),
@@ -158,6 +152,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 10 unmodified lines
158152 _mouseX(0),
159153 _mouseY(0),
160154 _lastMouseMove(usecTimestampNow()),
155+ _lastMouseMoveType(QEvent::MouseMove),
161156 _mouseHidden(false),
162157 _seenMouseMove(false),
163158 _touchAvgX(0.0f),
@@ -166,14 +161,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 2 unmodified lines
166161 _mousePressed(false),
167162 _audio(STARTUP_JITTER_SAMPLES),
168163 _enableProcessVoxelsThread(true),
169− _voxelProcessor(),
164+ _octreeProcessor(),
170165 _voxelHideShowThread(&_voxels),
171166 _packetsPerSecond(0),
172167 _bytesPerSecond(0),
173168 _nodeBoundsDisplay(this),
174169 _previousScriptLocation(),
175− _runningScriptsWidget(new RunningScriptsWidget(_window)),
176− _runningScriptsWidgetWasVisible(false)
170+ _applicationOverlay(),
171+ _runningScriptsWidget(NULL),
172+ _runningScriptsWidgetWasVisible(false),
173+ _trayIcon(new QSystemTrayIcon(_window)),
174+ _lastNackTime(usecTimestampNow())
177175 {
178176 // read the ApplicationInfo.ini file for Name/Version/Domain information
179177 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
204202 // call Menu getInstance static method to set up the menu
205203 _window->setMenuBar(Menu::getInstance());
206204
205+ _runningScriptsWidget = new RunningScriptsWidget(_window);
206+
207207 unsigned int listenPort = 0; // bind to an ephemeral port by default
208208 const char** constArgv = const_cast<const char**>(argv);
209209 const char* portStr = getCmdOption(argc, constArgv, "--listenPort");
@@ -238,7 +238,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 28 unmodified lines
238238 connect(&nodeList->getDomainHandler(), SIGNAL(connectedToDomain(const QString&)), SLOT(connectedToDomain(const QString&)));
239239
240240 // 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;
242242
243243 QTimer* locationUpdateTimer = new QTimer(this);
244244 connect(locationUpdateTimer, &QTimer::timeout, this, &Application::updateLocationInServer);
@@ -255,6 +255,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 10 unmodified lines
255255
256256 // connect to appropriate slots on AccountManager
257257 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+
258267 connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain);
259268 connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
260269
@@ -289,8 +298,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 28 unmodified lines
289298 // move the silentNodeTimer to the _nodeThread
290299 QTimer* silentNodeTimer = new QTimer();
291300 connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
292− silentNodeTimer->moveToThread(_nodeThread);
293301 silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS);
302+ silentNodeTimer->moveToThread(_nodeThread);
294303
295304 // send the identity packet for our avatar each second to our avatar mixer
296305 QTimer* identityPacketTimer = new QTimer();
@@ -361,7 +370,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 64 unmodified lines
361370 qDebug() << "This is a first run...";
362371 // clear the scripts, and set out script to our default scripts
363372 clearScriptsBeforeRunning();
364− loadScript("http://public.highfidelity.io/scripts/defaultScripts.js");
373+ loadScript(DEFAULT_SCRIPTS_JS_URL);
365374
366375 QMutexLocker locker(&_settingsMutex);
367376 _settings->setValue("firstRun",QVariant(false));
@@ -383,6 +392,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 15 unmodified lines
383392 OAuthWebViewHandler::getInstance();
384393 // make sure the High Fidelity root CA is in our list of trusted certs
385394 OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig();
395+
396+ _trayIcon->show();
386397 }
387398
388399 Application::~Application() {
@@ -412,7 +423,7 @@ Application::~Application() { · 23 unmodified lines
412423 _audio.thread()->quit();
413424 _audio.thread()->wait();
414425
415− _voxelProcessor.terminate();
426+ _octreeProcessor.terminate();
416427 _voxelHideShowThread.terminate();
417428 _voxelEditSender.terminate();
418429 _particleEditSender.terminate();
@@ -511,7 +522,7 @@ void Application::initializeGL() { · 92 unmodified lines
511522 qDebug( "init() complete.");
512523
513524 // create thread for parsing of voxel data independent of the main network and rendering threads
514− _voxelProcessor.initialize(_enableProcessVoxelsThread);
525+ _octreeProcessor.initialize(_enableProcessVoxelsThread);
515526 _voxelEditSender.initialize(_enableProcessVoxelsThread);
516527 _voxelHideShowThread.initialize(_enableProcessVoxelsThread);
517528 _particleEditSender.initialize(_enableProcessVoxelsThread);
@@ -543,26 +554,20 @@ void Application::initializeGL() { · 25 unmodified lines
543554 }
544555
545556 // update before the first render
546− update(0.0f);
557+ update(1.f / _fps);
547558
548559 InfoView::showFirstTime();
549560 }
550561
551562 void Application::paintGL() {
563+ PerformanceTimer perfTimer("paintGL");
564+
552565 PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
553566 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
554567 PerformanceWarning warn(showWarnings, "Application::paintGL()");
555568
556569 glEnable(GL_LINE_SMOOTH);
557570
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−
566571 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
567572 _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay
568573 _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
@@ -577,39 +582,25 @@ void Application::paintGL() { · 8 unmodified lines
577582 _myCamera.setTightness(0.0f);
578583 glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();
579584 float headHeight = eyePosition.y - _myAvatar->getPosition().y;
580− _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale() * _scaleMirror);
585+ _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
581586 _myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0));
582587 _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
588+ }
583589
584− // if the head would intersect the near clip plane, we must push the camera out
585− glm::vec3 relativePosition = glm::inverse(_myCamera.getTargetRotation()) *
586− (eyePosition - _myCamera.getTargetPosition());
587− const float BASE_PUSHBACK_RADIUS = 0.2f;
588− float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;
589− pushback = relativePosition.z + pushbackRadius - _myCamera.getDistance();
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());
590+ if (OculusManager::isConnected()) {
591+ // Oculus in third person causes nausea, so only allow it if option is checked in dev menu
592+ if (!Menu::getInstance()->isOptionChecked(MenuOption::AllowOculusCameraModeChange) || _myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
593+ _myCamera.setDistance(0.0f);
594+ _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
595+ _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
605596 }
606− updateProjectionMatrix(_myCamera, true);
597+ _myCamera.setUpShift(0.0f);
598+ _myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
607599 }
608600
609601 // Update camera position
610602 _myCamera.update( 1.f/_fps );
611603
612−
613604 // Note: whichCamera is used to pick between the normal camera myCamera for our
614605 // main camera, vs, an alternate camera. The alternate camera we support right now
615606 // is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
@@ -635,16 +626,18 @@ void Application::paintGL() { · 19 unmodified lines
635626 whichCamera = _viewFrustumOffsetCamera;
636627 }
637628
638− if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) {
629+ if (Menu::getInstance()->getShadowsEnabled()) {
639630 updateShadowMap();
640631 }
641632
642633 if (OculusManager::isConnected()) {
643634 OculusManager::display(whichCamera);
635+
644636 } else if (TV3DManager::isConnected()) {
645637 _glowEffect.prepare();
646638 TV3DManager::display(whichCamera);
647639 _glowEffect.render();
640+
648641 } else {
649642 _glowEffect.prepare();
650643
@@ -663,7 +656,17 @@ void Application::paintGL() { · 12 unmodified lines
663656 _rearMirrorTools->render(true);
664657 }
665658
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+ }
667670 }
668671
669672 _frameCount++;
@@ -1103,6 +1106,16 @@ void Application::focusOutEvent(QFocusEvent* event) { · 433 unmodified lines
11031106 }
11041107
11051108 void 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+
11061119 _controllerScriptingInterface.emitMouseMoveEvent(event); // send events to any registered scripts
11071120
11081121 // 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
11101123 return;
11111124 }
11121125
1113−
11141126 _lastMouseMove = usecTimestampNow();
1115− if (_mouseHidden) {
1127+
1128+ if (_mouseHidden && showMouse && !OculusManager::isConnected()) {
11161129 getGLWidget()->setCursor(Qt::ArrowCursor);
11171130 _mouseHidden = false;
11181131 _seenMouseMove = true;
@@ -1308,11 +1321,13 @@ void Application::timer() { · 189 unmodified lines
13081321 }
13091322
13101323 void Application::idle() {
1324+ PerformanceTimer perfTimer("idle");
1325+
13111326 // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing
13121327 // details if we're in ExtraDebugging mode. However, the ::update() and it's subcomponents will show their timing
13131328 // details normally.
13141329 bool showWarnings = getLogger()->extraDebugging();
1315− PerformanceWarning warn(showWarnings, "Application::idle()");
1330+ PerformanceWarning warn(showWarnings, "idle()");
13161331
13171332 // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
13181333
@@ -1320,15 +1335,18 @@ void Application::idle() { · 1 unmodified line
13201335 if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
13211336 _lastTimeUpdated.start();
13221337 {
1338+ PerformanceTimer perfTimer("idle/update");
13231339 PerformanceWarning warn(showWarnings, "Application::idle()... update()");
13241340 const float BIGGEST_DELTA_TIME_SECS = 0.25f;
13251341 update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
13261342 }
13271343 {
1344+ PerformanceTimer perfTimer("idle/updateGL");
13281345 PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()");
13291346 _glWidget->updateGL();
13301347 }
13311348 {
1349+ PerformanceTimer perfTimer("idle/rest");
13321350 PerformanceWarning warn(showWarnings, "Application::idle()... rest of it");
13331351 _idleLoopStdev.addValue(timeSinceLastUpdate);
13341352
@@ -1340,14 +1358,16 @@ void Application::idle() { · 5 unmodified lines
13401358 }
13411359
13421360 if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
1361+ PerformanceTimer perfTimer("idle/rest/_buckyBalls");
13431362 _buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData());
13441363 }
13451364
13461365 // After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
13471366 idleTimer->start(2);
1348− }
1349− if (_numChangedSettings > 0) {
1350− saveSettings();
1367+
1368+ if (_numChangedSettings > 0) {
1369+ saveSettings();
1370+ }
13511371 }
13521372 }
13531373 }
@@ -1375,6 +1395,9 @@ void Application::setEnable3DTVMode(bool enable3DTVMode) { · 21 unmodified lines
13751395 resizeGL(_glWidget->width(),_glWidget->height());
13761396 }
13771397
1398+void Application::setEnableVRMode(bool enableVRMode) {
1399+ resizeGL(_glWidget->width(), _glWidget->height());
1400+}
13781401
13791402 void Application::setRenderVoxels(bool voxelRender) {
13801403 _voxelEditSender.setShouldSend(voxelRender);
@@ -1504,10 +1527,10 @@ void Application::importVoxels() { · 123 unmodified lines
15041527 }
15051528
15061529 if (!_voxelImporter->exec()) {
1507− qDebug() << "[DEBUG] Import succeeded." << endl;
1530+ qDebug() << "Import succeeded." << endl;
15081531 _importSucceded = true;
15091532 } else {
1510− qDebug() << "[DEBUG] Import failed." << endl;
1533+ qDebug() << "Import failed." << endl;
15111534 if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) {
15121535 _sharedVoxelSystem.killLocalVoxels();
15131536 _sharedVoxelSystem.changeTree(&_clipboard);
@@ -1749,6 +1772,7 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) { · 235 unmodified lines
17491772 }
17501773
17511774 void Application::updateLOD() {
1775+ PerformanceTimer perfTimer("idle/update/updateLOD");
17521776 // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
17531777 if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
17541778 Menu::getInstance()->autoAdjustLOD(_fps);
@@ -1758,6 +1782,7 @@ void Application::updateLOD() { · 3 unmodified lines
17581782 }
17591783
17601784 void Application::updateMouseRay() {
1785+ PerformanceTimer perfTimer("idle/update/updateMouseRay");
17611786
17621787 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
17631788 PerformanceWarning warn(showWarnings, "Application::updateMouseRay()");
@@ -1790,6 +1815,7 @@ void Application::updateMouseRay() { · 26 unmodified lines
17901815 }
17911816
17921817 void Application::updateFaceshift() {
1818+ PerformanceTimer perfTimer("idle/update/updateFaceshift");
17931819
17941820 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
17951821 PerformanceWarning warn(showWarnings, "Application::updateFaceshift()");
@@ -1804,6 +1830,7 @@ void Application::updateFaceshift() { · 8 unmodified lines
18041830 }
18051831
18061832 void Application::updateVisage() {
1833+ PerformanceTimer perfTimer("idle/update/updateVisage");
18071834
18081835 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
18091836 PerformanceWarning warn(showWarnings, "Application::updateVisage()");
@@ -1813,6 +1840,7 @@ void Application::updateVisage() { · 3 unmodified lines
18131840 }
18141841
18151842 void Application::updateMyAvatarLookAtPosition() {
1843+ PerformanceTimer perfTimer("idle/update/updateMyAvatarLookAtPosition");
18161844
18171845 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
18181846 PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
@@ -1844,7 +1872,8 @@ void Application::updateMyAvatarLookAtPosition() { · 25 unmodified lines
18441872 }
18451873 } else {
18461874 // 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));
18481877 }
18491878 // TODO: Add saccade to mouse pointer when stable, IF not looking at someone (since we know we are looking at it)
18501879 /*
@@ -1878,12 +1907,13 @@ void Application::updateMyAvatarLookAtPosition() { · 27 unmodified lines
18781907 }
18791908
18801909 void Application::updateThreads(float deltaTime) {
1910+ PerformanceTimer perfTimer("idle/update/updateThreads");
18811911 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
18821912 PerformanceWarning warn(showWarnings, "Application::updateThreads()");
18831913
18841914 // parse voxel packets
18851915 if (!_enableProcessVoxelsThread) {
1886− _voxelProcessor.threadRoutine();
1916+ _octreeProcessor.threadRoutine();
18871917 _voxelHideShowThread.threadRoutine();
18881918 _voxelEditSender.threadRoutine();
18891919 _particleEditSender.threadRoutine();
@@ -1892,6 +1922,7 @@ void Application::updateThreads(float deltaTime) { · 2 unmodified lines
18921922 }
18931923
18941924 void Application::updateMetavoxels(float deltaTime) {
1925+ PerformanceTimer perfTimer("idle/update/updateMetavoxels");
18951926 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
18961927 PerformanceWarning warn(showWarnings, "Application::updateMetavoxels()");
18971928
@@ -1921,6 +1952,7 @@ void Application::cameraMenuChanged() { · 23 unmodified lines
19211952 }
19221953
19231954 void Application::updateCamera(float deltaTime) {
1955+ PerformanceTimer perfTimer("idle/update/updateCamera");
19241956 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
19251957 PerformanceWarning warn(showWarnings, "Application::updateCamera()");
19261958
@@ -1938,6 +1970,7 @@ void Application::updateCamera(float deltaTime) { · 11 unmodified lines
19381970 }
19391971
19401972 void Application::updateDialogs(float deltaTime) {
1973+ PerformanceTimer perfTimer("idle/update/updateDialogs");
19411974 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
19421975 PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
19431976
@@ -1954,6 +1987,7 @@ void Application::updateDialogs(float deltaTime) { · 10 unmodified lines
19541987 }
19551988
19561989 void Application::updateCursor(float deltaTime) {
1990+ PerformanceTimer perfTimer("idle/update/updateCursor");
19571991 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
19581992 PerformanceWarning warn(showWarnings, "Application::updateCursor()");
19591993
@@ -1978,51 +2012,87 @@ void Application::updateCursor(float deltaTime) { · 18 unmodified lines
19782012 }
19792013
19802014 void Application::update(float deltaTime) {
2015+ //PerformanceTimer perfTimer("idle/update"); // NOTE: we track this above in Application::idle()
2016+
19812017 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
19822018 PerformanceWarning warn(showWarnings, "Application::update()");
19832019
19842020 updateLOD();
1985−
1986− // check what's under the mouse and update the mouse voxel
1987− updateMouseRay();
1988−
2021+ updateMouseRay(); // check what's under the mouse and update the mouse voxel
19892022 updateFaceshift();
19902023 updateVisage();
1991− _myAvatar->updateLookAtTargetAvatar();
2024+
2025+ {
2026+ PerformanceTimer perfTimer("idle/update/updateLookAtTargetAvatar");
2027+ _myAvatar->updateLookAtTargetAvatar();
2028+ }
19922029 updateMyAvatarLookAtPosition();
1993− _sixenseManager.update(deltaTime);
1994− _joystickManager.update();
1995− _prioVR.update(deltaTime);
1996− updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
2030+ {
2031+ PerformanceTimer perfTimer("idle/update/sixense,joystick,prioVR");
2032+ _sixenseManager.update(deltaTime);
2033+ _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+
19972042 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+ }
19992048 updateMetavoxels(deltaTime); // update metavoxels
20002049 updateCamera(deltaTime); // handle various camera tweaks like off axis projection
20012050 updateDialogs(deltaTime); // update various stats dialogs if present
20022051 updateCursor(deltaTime); // Handle cursor updates
20032052
2004− _particles.update(); // update the particles...
2005− _particleCollisionSystem.update(); // collide the particles...
2053+ {
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+ }
20062061
2007− _models.update(); // update the models...
2062+ {
2063+ PerformanceTimer perfTimer("idle/update/_models");
2064+ _models.update(); // update the models...
2065+ }
20082066
2009− _overlays.update(deltaTime);
2067+ {
2068+ PerformanceTimer perfTimer("idle/update/_overlays");
2069+ _overlays.update(deltaTime);
2070+ }
20102071
2011− // let external parties know we're updating
2012− emit simulating(deltaTime);
2072+ {
2073+ PerformanceTimer perfTimer("idle/update/emit simulating");
2074+ // let external parties know we're updating
2075+ emit simulating(deltaTime);
2076+ }
20132077 }
20142078
20152079 void Application::updateMyAvatar(float deltaTime) {
2080+ PerformanceTimer perfTimer("updateMyAvatar");
20162081 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
20172082 PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()");
20182083
2019− _myAvatar->update(deltaTime);
2020−
2021− // send head/hand data to the avatar mixer and voxel server
2022− QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData);
2023− packet.append(_myAvatar->toByteArray());
2084+ {
2085+ PerformanceTimer perfTimer("updateMyAvatar/_myAvatar->update()");
2086+ _myAvatar->update(deltaTime);
2087+ }
20242088
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+ }
20262096
20272097 // Update _viewFrustum with latest camera and view frustum data...
20282098 // 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
20302100 // We could optimize this to not actually load the viewFrustum, since we don't
20312101 // actually need to calculate the view frustum planes to send these details
20322102 // to the server.
2033− loadViewFrustum(_myCamera, _viewFrustum);
2103+ {
2104+ PerformanceTimer perfTimer("updateMyAvatar/loadViewFrustum");
2105+ loadViewFrustum(_myCamera, _viewFrustum);
2106+ }
20342107
20352108 // Update my voxel servers with my current voxel query...
2036− quint64 now = usecTimestampNow();
2037− quint64 sinceLastQuery = now - _lastQueriedTime;
2038− const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
2039− bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY;
2040− bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum);
2109+ {
2110+ PerformanceTimer perfTimer("updateMyAvatar/queryOctree");
2111+ quint64 now = usecTimestampNow();
2112+ quint64 sinceLastQuery = now - _lastQueriedTime;
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);
20412116
2042− // 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) {
2044− _lastQueriedTime = now;
2045− queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
2046− queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
2047− queryOctree(NodeType::ModelServer, PacketTypeModelQuery, _modelServerJurisdictions);
2048− _lastQueriedViewFrustum = _viewFrustum;
2117+ // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it
2118+ if (queryIsDue || viewIsDifferentEnough) {
2119+ _lastQueriedTime = now;
2120+ queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
2121+ queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
2122+ queryOctree(NodeType::ModelServer, PacketTypeModelQuery, _modelServerJurisdictions);
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+ }
20492136 }
20502137 }
20512138
2139+int 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+
20522218 void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {
20532219
20542220 // 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
21042270 if (rootCode) {
21052271 VoxelPositionSize rootDetails;
21062272 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);
21082274 serverBounds.scale(TREE_SCALE);
21092275
2110− ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);
2276+ ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
21112277
21122278 if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
21132279 inViewServers++;
@@ -2170,10 +2336,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 56 unmodified lines
21702336 if (rootCode) {
21712337 VoxelPositionSize rootDetails;
21722338 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);
21742340 serverBounds.scale(TREE_SCALE);
21752341
2176− ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);
2342+ ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
21772343 if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
21782344 inView = true;
21792345 } else {
@@ -2273,88 +2439,122 @@ glm::vec3 Application::getSunDirection() { · 93 unmodified lines
22732439 }
22742440
22752441 void Application::updateShadowMap() {
2442+ PerformanceTimer perfTimer("paintGL/updateShadowMap");
22762443 QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject();
22772444 fbo->bind();
22782445 glEnable(GL_DEPTH_TEST);
22792446 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
22802447
2281− glViewport(0, 0, fbo->width(), fbo->height());
2282−
22832448 glm::vec3 lightDirection = -getSunDirection();
22842449 glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection);
22852450 glm::quat inverseRotation = glm::inverse(rotation);
2286− float nearScale = 0.0f;
2287− const float MAX_SHADOW_DISTANCE = 2.0f;
2288− float farScale = (MAX_SHADOW_DISTANCE - _viewFrustum.getNearClip()) /
2289− (_viewFrustum.getFarClip() - _viewFrustum.getNearClip());
2451+
2452+ const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f };
2453+ const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f),
2454+ glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) };
2455+
2456+ float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip());
22902457 loadViewFrustum(_myCamera, _viewFrustum);
2291− glm::vec3 points[] = {
2292− glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale),
2293− glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale),
2294− glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale),
2295− glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale),
2296− glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale),
2297− glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale),
2298− glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale),
2299− glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) };
2300− glm::vec3 center;
2301− for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
2302− center += points[i];
2303− }
2304− center /= (float)(sizeof(points) / sizeof(points[0]));
2305− float radius = 0.0f;
2306− for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
2307− radius = qMax(radius, glm::distance(points[i], center));
2308− }
2309− center = inverseRotation * center;
2310− glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius);
2311− glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius);
2312−
2313− // stretch out our extents in z so that we get all of the avatars
2314− minima.z -= _viewFrustum.getFarClip() * 0.5f;
2315− maxima.z += _viewFrustum.getFarClip() * 0.5f;
2316−
2317− // save the combined matrix for rendering
2318− _shadowMatrix = glm::transpose(glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) *
2319− glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation));
2320−
2321− // update the shadow view frustum
2322− _shadowViewFrustum.setPosition(rotation * ((minima + maxima) * 0.5f));
2323− _shadowViewFrustum.setOrientation(rotation);
2324− _shadowViewFrustum.setOrthographic(true);
2325− _shadowViewFrustum.setWidth(maxima.x - minima.x);
2326− _shadowViewFrustum.setHeight(maxima.y - minima.y);
2327− _shadowViewFrustum.setNearClip(minima.z);
2328− _shadowViewFrustum.setFarClip(maxima.z);
2329− _shadowViewFrustum.setEyeOffsetPosition(glm::vec3());
2330− _shadowViewFrustum.setEyeOffsetOrientation(glm::quat());
2331− _shadowViewFrustum.calculate();
2458+
2459+ int matrixCount = 1;
2460+ int targetSize = fbo->width();
2461+ float targetScale = 1.0f;
2462+ if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
2463+ matrixCount = CASCADED_SHADOW_MATRIX_COUNT;
2464+ targetSize = fbo->width() / 2;
2465+ targetScale = 0.5f;
2466+ }
2467+ for (int i = 0; i < matrixCount; i++) {
2468+ const glm::vec2& coord = MAP_COORDS[i];
2469+ glViewport(coord.s * fbo->width(), coord.t * fbo->height(), targetSize, targetSize);
2470+
2471+ float nearScale = SHADOW_MATRIX_DISTANCES[i] * frustumScale;
2472+ float farScale = SHADOW_MATRIX_DISTANCES[i + 1] * frustumScale;
2473+ glm::vec3 points[] = {
2474+ glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale),
2475+ glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale),
2476+ glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale),
2477+ glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale),
2478+ glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale),
2479+ glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale),
2480+ glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale),
2481+ glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) };
2482+ glm::vec3 center;
2483+ for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) {
2484+ center += points[j];
2485+ }
2486+ center /= (float)(sizeof(points) / sizeof(points[0]));
2487+ float radius = 0.0f;
2488+ for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) {
2489+ radius = qMax(radius, glm::distance(points[j], center));
2490+ }
2491+ if (i < 3) {
2492+ const float RADIUS_SCALE = 0.5f;
2493+ _shadowDistances[i] = -glm::distance(_viewFrustum.getPosition(), center) - radius * RADIUS_SCALE;
2494+ }
2495+ center = inverseRotation * center;
2496+
2497+ // to reduce texture "shimmer," move in texel increments
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);
23322531
2333− glMatrixMode(GL_PROJECTION);
2334− glPushMatrix();
2335− glLoadIdentity();
2336− glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z);
2532+ glMatrixMode(GL_MODELVIEW);
2533+ glPushMatrix();
2534+ glLoadIdentity();
2535+ glm::vec3 axis = glm::axis(inverseRotation);
2536+ glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z);
23372537
2338− glMatrixMode(GL_MODELVIEW);
2339− glPushMatrix();
2340− glLoadIdentity();
2341− glm::vec3 axis = glm::axis(inverseRotation);
2342− glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z);
2538+ // store view matrix without translation, which we'll use for precision-sensitive objects
2539+ updateUntranslatedViewMatrix();
23432540
2344− // store view matrix without translation, which we'll use for precision-sensitive objects
2345− updateUntranslatedViewMatrix();
2541+ glEnable(GL_POLYGON_OFFSET_FILL);
2542+ glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt
23462543
2347− _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE);
2348− _particles.render(OctreeRenderer::SHADOW_RENDER_MODE);
2349− _models.render(OctreeRenderer::SHADOW_RENDER_MODE);
2544+ _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE);
2545+ _particles.render(OctreeRenderer::SHADOW_RENDER_MODE);
2546+ _models.render(OctreeRenderer::SHADOW_RENDER_MODE);
23502547
2351− glPopMatrix();
2548+ glDisable(GL_POLYGON_OFFSET_FILL);
23522549
2353− glMatrixMode(GL_PROJECTION);
2354− glPopMatrix();
2550+ glPopMatrix();
23552551
2356− glMatrixMode(GL_MODELVIEW);
2552+ glMatrixMode(GL_PROJECTION);
2553+ glPopMatrix();
23572554
2555+ glMatrixMode(GL_MODELVIEW);
2556+ }
2557+
23582558 fbo->release();
23592559
23602560 glViewport(0, 0, _glWidget->width(), _glWidget->height());
@@ -2401,6 +2601,7 @@ QImage Application::renderAvatarBillboard() { · 40 unmodified lines
24012601 }
24022602
24032603 void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
2604+ PerformanceTimer perfTimer("paintGL/displaySide");
24042605 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
24052606 // transform by eye offset
24062607
@@ -2433,9 +2634,27 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 26 unmodified lines
24332634 glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z);
24342635
24352636 // 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+ }
24372655
24382656 if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
2657+ PerformanceTimer perfTimer("paintGL/displaySide/stars");
24392658 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
24402659 "Application::displaySide() ... stars...");
24412660 if (!_stars.isStarsLoaded()) {
@@ -2464,6 +2683,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 22 unmodified lines
24642683
24652684 // draw the sky dome
24662685 if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
2686+ PerformanceTimer perfTimer("paintGL/displaySide/atmosphere");
24672687 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
24682688 "Application::displaySide() ... atmosphere...");
24692689 _environment.renderAtmospheres(whichCamera);
@@ -2483,10 +2703,14 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 13 unmodified lines
24832703 glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR);
24842704
24852705 // draw the audio reflector overlay
2486− _audioReflector.render();
2487−
2706+ {
2707+ PerformanceTimer perfTimer("paintGL/displaySide/audioReflector");
2708+ _audioReflector.render();
2709+ }
2710+
24882711 // Draw voxels
24892712 if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
2713+ PerformanceTimer perfTimer("paintGL/displaySide/voxels");
24902714 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
24912715 "Application::displaySide() ... voxels...");
24922716 _voxels.render();
@@ -2494,12 +2718,14 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
24942718
24952719 // also, metavoxels
24962720 if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) {
2721+ PerformanceTimer perfTimer("paintGL/displaySide/metavoxels");
24972722 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
24982723 "Application::displaySide() ... metavoxels...");
24992724 _metavoxels.render();
25002725 }
25012726
25022727 if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
2728+ PerformanceTimer perfTimer("paintGL/displaySide/buckyBalls");
25032729 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
25042730 "Application::displaySide() ... bucky balls...");
25052731 _buckyBalls.render();
@@ -2507,6 +2733,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
25072733
25082734 // render particles...
25092735 if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) {
2736+ PerformanceTimer perfTimer("paintGL/displaySide/particles");
25102737 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
25112738 "Application::displaySide() ... particles...");
25122739 _particles.render();
@@ -2514,6 +2741,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
25142741
25152742 // render models...
25162743 if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
2744+ PerformanceTimer perfTimer("paintGL/displaySide/models");
25172745 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
25182746 "Application::displaySide() ... models...");
25192747 _models.render();
@@ -2521,6 +2749,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
25212749
25222750 // render the ambient occlusion effect if enabled
25232751 if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
2752+ PerformanceTimer perfTimer("paintGL/displaySide/AmbientOcclusion");
25242753 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
25252754 "Application::displaySide() ... AmbientOcclusion...");
25262755 _ambientOcclusionEffect.render();
@@ -2534,16 +2763,21 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 7 unmodified lines
25342763 }
25352764
25362765 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+ }
25382770
25392771 if (!selfAvatarOnly) {
25402772 // Render the world box
25412773 if (whichCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
2774+ PerformanceTimer perfTimer("paintGL/displaySide/renderWorldBox");
25422775 renderWorldBox();
25432776 }
25442777
2545− // brad's frustum for debugging
2778+ // view frustum for debugging
25462779 if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum) && whichCamera.getMode() != CAMERA_MODE_MIRROR) {
2780+ PerformanceTimer perfTimer("paintGL/displaySide/ViewFrustum");
25472781 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
25482782 "Application::displaySide() ... renderViewFrustum...");
25492783 renderViewFrustum(_viewFrustum);
@@ -2551,8 +2785,10 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 1 unmodified line
25512785
25522786 // render voxel fades if they exist
25532787 if (_voxelFades.size() > 0) {
2788+ PerformanceTimer perfTimer("paintGL/displaySide/voxel fades");
25542789 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
25552790 "Application::displaySide() ... voxel fades...");
2791+ _voxelFadesLock.lockForWrite();
25562792 for(std::vector<VoxelFade>::iterator fade = _voxelFades.begin(); fade != _voxelFades.end();) {
25572793 fade->render();
25582794 if(fade->isDone()) {
@@ -2561,13 +2797,20 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 2 unmodified lines
25612797 ++fade;
25622798 }
25632799 }
2800+ _voxelFadesLock.unlock();
25642801 }
25652802
25662803 // give external parties a change to hook in
2567− emit renderingInWorldInterface();
2804+ {
2805+ PerformanceTimer perfTimer("paintGL/displaySide/inWorldInterface");
2806+ emit renderingInWorldInterface();
2807+ }
25682808
25692809 // render JS/scriptable overlays
2570− _overlays.render3D();
2810+ {
2811+ PerformanceTimer perfTimer("paintGL/displaySide/3dOverlays");
2812+ _overlays.render3D();
2813+ }
25712814 }
25722815 }
25732816
@@ -2597,183 +2840,6 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom · 23 unmodified lines
25972840 _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
25982841 }
25992842
2600−const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f };
2601−
2602−void 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−
27772843 glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
27782844 float horizontalScale = _glWidget->width() / 2.0f;
27792845 float verticalScale = _glWidget->height() / 2.0f;
@@ -2845,16 +2911,19 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 65 unmodified lines
28452911 glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation();
28462912 glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation();
28472913
2848− // get the eye positions relative to the neck and use them to set the face translation
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
2914+ // get the neck position so we can translate the face relative to it
28552915 glm::vec3 neckPosition;
28562916 _myAvatar->getSkeletonModel().setTranslation(glm::vec3());
28572917 _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
28582927 _myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead()->getFaceModel().getTranslation() -
28592928 neckPosition);
28602929
@@ -3122,6 +3191,17 @@ void Application::updateWindowTitle(){ · 261 unmodified lines
31223191 QString username = AccountManager::getInstance().getAccountInfo().getUsername();
31233192 QString title = QString() + (!username.isEmpty() ? username + " @ " : QString())
31243193 + 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+
31253205 qDebug("Application title set to: %s", title.toStdString().c_str());
31263206 _window->setWindowTitle(title);
31273207 }
@@ -3161,9 +3241,15 @@ void Application::domainChanged(const QString& domainHostname) { · 33 unmodified lines
31613241 _environment.resetToDefault();
31623242
31633243 // reset our node to stats and node to jurisdiction maps... since these must be changing...
3244+ _voxelServerJurisdictions.lockForWrite();
31643245 _voxelServerJurisdictions.clear();
3246+ _voxelServerJurisdictions.unlock();
3247+
31653248 _octreeServerSceneStats.clear();
3249+
3250+ _particleServerJurisdictions.lockForWrite();
31663251 _particleServerJurisdictions.clear();
3252+ _particleServerJurisdictions.unlock();
31673253
31683254 // reset the particle renderer
31693255 _particles.clear();
@@ -3199,13 +3285,26 @@ void Application::nodeAdded(SharedNodePointer node) { · 29 unmodified lines
31993285 }
32003286
32013287 void 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+
32023299 if (node->getType() == NodeType::VoxelServer) {
32033300 QUuid nodeUUID = node->getUUID();
32043301 // see if this is the first we've heard of this node...
3302+ _voxelServerJurisdictions.lockForRead();
32053303 if (_voxelServerJurisdictions.find(nodeUUID) != _voxelServerJurisdictions.end()) {
32063304 unsigned char* rootCode = _voxelServerJurisdictions[nodeUUID].getRootOctalCode();
32073305 VoxelPositionSize rootDetails;
32083306 voxelDetailsForCode(rootCode, rootDetails);
3307+ _voxelServerJurisdictions.unlock();
32093308
32103309 qDebug("voxel server going away...... v[%f, %f, %f, %f]",
32113310 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
@@ -3216,12 +3315,16 @@ void Application::nodeKilled(SharedNodePointer node) { · 4 unmodified lines
32163315 fade.voxelDetails = rootDetails;
32173316 const float slightly_smaller = 0.99f;
32183317 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3318+ _voxelFadesLock.lockForWrite();
32193319 _voxelFades.push_back(fade);
3320+ _voxelFadesLock.unlock();
32203321 }
32213322
32223323 // 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();
32233325 _voxelServerJurisdictions.erase(_voxelServerJurisdictions.find(nodeUUID));
32243326 }
3327+ _voxelServerJurisdictions.unlock();
32253328
32263329 // also clean up scene stats for that server
32273330 _octreeSceneStatsLock.lockForWrite();
@@ -3233,10 +3336,12 @@ void Application::nodeKilled(SharedNodePointer node) { · 5 unmodified lines
32333336 } else if (node->getType() == NodeType::ParticleServer) {
32343337 QUuid nodeUUID = node->getUUID();
32353338 // see if this is the first we've heard of this node...
3339+ _particleServerJurisdictions.lockForRead();
32363340 if (_particleServerJurisdictions.find(nodeUUID) != _particleServerJurisdictions.end()) {
32373341 unsigned char* rootCode = _particleServerJurisdictions[nodeUUID].getRootOctalCode();
32383342 VoxelPositionSize rootDetails;
32393343 voxelDetailsForCode(rootCode, rootDetails);
3344+ _particleServerJurisdictions.unlock();
32403345
32413346 qDebug("particle server going away...... v[%f, %f, %f, %f]",
32423347 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
@@ -3247,12 +3352,16 @@ void Application::nodeKilled(SharedNodePointer node) { · 4 unmodified lines
32473352 fade.voxelDetails = rootDetails;
32483353 const float slightly_smaller = 0.99f;
32493354 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3355+ _voxelFadesLock.lockForWrite();
32503356 _voxelFades.push_back(fade);
3357+ _voxelFadesLock.unlock();
32513358 }
32523359
32533360 // 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();
32543362 _particleServerJurisdictions.erase(_particleServerJurisdictions.find(nodeUUID));
32553363 }
3364+ _particleServerJurisdictions.unlock();
32563365
32573366 // also clean up scene stats for that server
32583367 _octreeSceneStatsLock.lockForWrite();
@@ -3265,10 +3374,12 @@ void Application::nodeKilled(SharedNodePointer node) { · 6 unmodified lines
32653374
32663375 QUuid nodeUUID = node->getUUID();
32673376 // see if this is the first we've heard of this node...
3377+ _modelServerJurisdictions.lockForRead();
32683378 if (_modelServerJurisdictions.find(nodeUUID) != _modelServerJurisdictions.end()) {
32693379 unsigned char* rootCode = _modelServerJurisdictions[nodeUUID].getRootOctalCode();
32703380 VoxelPositionSize rootDetails;
32713381 voxelDetailsForCode(rootCode, rootDetails);
3382+ _modelServerJurisdictions.unlock();
32723383
32733384 qDebug("model server going away...... v[%f, %f, %f, %f]",
32743385 rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
@@ -3279,12 +3390,16 @@ void Application::nodeKilled(SharedNodePointer node) { · 4 unmodified lines
32793390 fade.voxelDetails = rootDetails;
32803391 const float slightly_smaller = 0.99f;
32813392 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3393+ _voxelFadesLock.lockForWrite();
32823394 _voxelFades.push_back(fade);
3395+ _voxelFadesLock.unlock();
32833396 }
32843397
32853398 // 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();
32863400 _modelServerJurisdictions.erase(_modelServerJurisdictions.find(nodeUUID));
32873401 }
3402+ _modelServerJurisdictions.unlock();
32883403
32893404 // also clean up scene stats for that server
32903405 _octreeSceneStatsLock.lockForWrite();
@@ -3354,7 +3469,10 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin · 63 unmodified lines
33543469 serverType = "Model";
33553470 }
33563471
3472+ jurisdiction->lockForRead();
33573473 if (jurisdiction->find(nodeUUID) == jurisdiction->end()) {
3474+ jurisdiction->unlock();
3475+
33583476 qDebug("stats from new %s server... [%f, %f, %f, %f]",
33593477 qPrintable(serverType), rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
33603478
@@ -3364,8 +3482,12 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin · 3 unmodified lines
33643482 fade.voxelDetails = rootDetails;
33653483 const float slightly_smaller = 0.99f;
33663484 fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
3485+ _voxelFadesLock.lockForWrite();
33673486 _voxelFades.push_back(fade);
3487+ _voxelFadesLock.unlock();
33683488 }
3489+ } else {
3490+ jurisdiction->unlock();
33693491 }
33703492 // store jurisdiction details for later use
33713493 // 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
33733495 // details from the OctreeSceneStats to construct the JurisdictionMap
33743496 JurisdictionMap jurisdictionMap;
33753497 jurisdictionMap.copyContents(temp.getJurisdictionRoot(), temp.getJurisdictionEndNodes());
3498+ jurisdiction->lockForWrite();
33763499 (*jurisdiction)[nodeUUID] = jurisdictionMap;
3500+ jurisdiction->unlock();
33773501 }
33783502 return statsMessageLength;
33793503 }
@@ -3416,21 +3540,31 @@ void Application::saveScripts() { · 36 unmodified lines
34163540 _settings->endArray();
34173541 }
34183542
3419−ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) {
3420− if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptName) && !_scriptEnginesHash[scriptName]->isFinished()){
3421− return _scriptEnginesHash[scriptName];
3543+ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor, bool activateMainWindow) {
3544+ QUrl scriptUrl(scriptName);
3545+ const QString& scriptURLString = scriptUrl.toString();
3546+ if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor
3547+ && !_scriptEnginesHash[scriptURLString]->isFinished()) {
3548+
3549+ return _scriptEnginesHash[scriptURLString];
34223550 }
34233551
3424− // start the script on a new thread...
3425− QUrl scriptUrl(scriptName);
3426− ScriptEngine* scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface);
3427− _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine);
3552+ ScriptEngine* scriptEngine;
3553+ if (scriptName.isNull()) {
3554+ scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);
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+ }
34283564
3429− if (!scriptEngine->hasScript()) {
3430− qDebug() << "Application::loadScript(), script failed to load...";
3431− return NULL;
3565+ _scriptEnginesHash.insertMulti(scriptURLString, scriptEngine);
3566+ _runningScriptsWidget->setRunningScripts(getRunningScripts());
34323567 }
3433− _runningScriptsWidget->setRunningScripts(getRunningScripts());
34343568
34353569 // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
34363570 // we can use the same ones from the application.
@@ -3471,6 +3605,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript · 34 unmodified lines
34713605 scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
34723606 scriptEngine->registerGlobalObject("AnimationCache", &_animationCache);
34733607 scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector);
3608+ scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance());
34743609
34753610 QThread* workerThread = new QThread(this);
34763611
@@ -3490,7 +3625,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript · 13 unmodified lines
34903625 workerThread->start();
34913626
34923627 // restore the main window's active state
3493− if (!loadScriptFromEditor) {
3628+ if (activateMainWindow && !loadScriptFromEditor) {
34943629 _window->activateWindow();
34953630 }
34963631 bumpSettings();
@@ -3499,7 +3634,9 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript · 2 unmodified lines
34993634 }
35003635
35013636 void 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);
35033640 _runningScriptsWidget->scriptStopped(scriptName);
35043641 _runningScriptsWidget->setRunningScripts(getRunningScripts());
35053642 bumpSettings();
@@ -3529,6 +3666,12 @@ void Application::reloadAllScripts() { · 23 unmodified lines
35293666 stopAllScripts(true);
35303667 }
35313668
3669+void Application::loadDefaultScripts() {
3670+ if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
3671+ loadScript(DEFAULT_SCRIPTS_JS_URL);
3672+ }
3673+}
3674+
35323675 void Application::manageRunningScriptsWidgetVisibility(bool shown) {
35333676 if (_runningScriptsWidgetWasVisible && shown) {
35343677 _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