Showing the changes to interface/src/Application.cpp (1 of 312 files). Show all
Unified · Split
| @@ -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 that | 104 | // 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 | ||
| 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 | |||
| 115 | const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; | 107 | const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; |
| 116 | const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; | 108 | const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; |
| 117 | 109 | ||
| 110 | const QString DEFAULT_SCRIPTS_JS_URL = "http://public.highfidelity.io/scripts/defaultScripts.js"; | ||
| 111 | |||
| 118 | void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { | 112 | void 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 information | 176 | // 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 menu | 202 | // 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 default | 207 | 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 one | 240 | // 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 AccountManager | 256 | // 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 _nodeThread | 298 | // 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 mixer | 304 | // 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 scripts | 371 | // 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 certs | 393 | // 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 | ||
| 388 | Application::~Application() { | 399 | Application::~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 threads | 524 | // 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 render | 556 | // 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 | ||
| 551 | void Application::paintGL() { | 562 | void 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 delay | 572 | _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 out | 590 | 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 position | 601 | // 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 our | 604 | // 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 now | 605 | // main camera, vs, an alternate camera. The alternate camera we support right now |
| 615 | // is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism | 606 | // 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 | ||
| 1105 | void Application::mouseMoveEvent(QMouseEvent* event) { | 1108 | 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 | |||
| 1106 | _controllerScriptingInterface.emitMouseMoveEvent(event); // send events to any registered scripts | 1119 | _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 it | 1121 | // 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 | ||
| 1310 | void Application::idle() { | 1323 | void 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 timing | 1326 | // 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 timing | 1327 | // 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 ran | 1332 | // 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 | ||
| 1398 | void Application::setEnableVRMode(bool enableVRMode) { | ||
| 1399 | resizeGL(_glWidget->width(), _glWidget->height()); | ||
| 1400 | } | ||
| 1378 | 1401 | ||
| 1379 | void Application::setRenderVoxels(bool voxelRender) { | 1402 | void 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 | ||
| 1751 | void Application::updateLOD() { | 1774 | void 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 mode | 1776 | // 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 | ||
| 1760 | void Application::updateMouseRay() { | 1784 | void 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 | ||
| 1792 | void Application::updateFaceshift() { | 1817 | void 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 | ||
| 1806 | void Application::updateVisage() { | 1832 | void 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 | ||
| 1815 | void Application::updateMyAvatarLookAtPosition() { | 1842 | void 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 forward | 1874 | // 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 | ||
| 1880 | void Application::updateThreads(float deltaTime) { | 1909 | void 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 packets | 1914 | // 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 | ||
| 1894 | void Application::updateMetavoxels(float deltaTime) { | 1924 | void 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 | ||
| 1923 | void Application::updateCamera(float deltaTime) { | 1954 | void 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 | ||
| 1940 | void Application::updateDialogs(float deltaTime) { | 1972 | void 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 | ||
| 1956 | void Application::updateCursor(float deltaTime) { | 1989 | void 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 | ||
| 1980 | void Application::update(float deltaTime) { | 2014 | void 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/nodes | 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 | |||
| 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 metavoxels | 2048 | updateMetavoxels(deltaTime); // update metavoxels |
| 2000 | updateCamera(deltaTime); // handle various camera tweaks like off axis projection | 2049 | updateCamera(deltaTime); // handle various camera tweaks like off axis projection |
| 2001 | updateDialogs(deltaTime); // update various stats dialogs if present | 2050 | updateDialogs(deltaTime); // update various stats dialogs if present |
| 2002 | updateCursor(deltaTime); // Handle cursor updates | 2051 | 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 updating | 2072 | { |
| 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 | ||
| 2015 | void Application::updateMyAvatar(float deltaTime) { | 2079 | void 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 server | 2086 | _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 the | 2098 | // 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't | 2100 | // 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 details | 2101 | // 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 it | 2117 | // 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 | ||
| 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 | |||
| 2052 | void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) { | 2218 | void 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 | ||
| 2275 | void Application::updateShadowMap() { | 2441 | void 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 avatars | 2480 | 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 rendering | 2484 | 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 frustum | 2488 | 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 objects | 2541 | 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 | ||
| 2403 | void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { | 2603 | void 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 offset | 2606 | // 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 dome | 2684 | // 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 overlay | 2705 | // draw the audio reflector overlay |
| 2486 | _audioReflector.render(); | 2706 | { |
| 2487 | 2707 | PerformanceTimer perfTimer("paintGL/displaySide/audioReflector"); | |
| 2708 | _audioReflector.render(); | ||
| 2709 | } | ||
| 2710 | |||
| 2488 | // Draw voxels | 2711 | // 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, metavoxels | 2719 | // 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 enabled | 2750 | // 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 box | 2772 | // 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 debugging | 2778 | // 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 exist | 2786 | // 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 in | 2803 | // 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 overlays | 2809 | // 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 | ||
| 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 | |||
| 2777 | glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { | 2843 | glm::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 translation | 2914 | // 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 renderer | 3254 | // 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 | ||
| 3201 | void Application::nodeKilled(SharedNodePointer node) { | 3287 | 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 | |||
| 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 server | 3323 | // 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 server | 3329 | // 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 server | 3360 | // 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 server | 3366 | // 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 server | 3398 | // 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 server | 3404 | // 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 use | 3492 | // 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 it | 3493 | // 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 JurisdictionMap | 3495 | // 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 | ||
| 3419 | ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) { | 3543 | ScriptEngine* 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 so | 3569 | // 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 state | 3627 | // 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 | ||
| 3501 | void Application::scriptFinished(const QString& scriptName) { | 3636 | 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); | ||
| 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 | ||
| 3669 | void Application::loadDefaultScripts() { | ||
| 3670 | if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) { | ||
| 3671 | loadScript(DEFAULT_SCRIPTS_JS_URL); | ||
| 3672 | } | ||
| 3673 | } | ||
| 3674 | |||
| 3532 | void Application::manageRunningScriptsWidgetVisibility(bool shown) { | 3675 | void Application::manageRunningScriptsWidgetVisibility(bool shown) { |
| 3533 | if (_runningScriptsWidgetWasVisible && shown) { | 3676 | if (_runningScriptsWidgetWasVisible && shown) { |
| 3534 | _runningScriptsWidget->show(); | 3677 | _runningScriptsWidget->show(); |