Showing the changes to interface/src/Application.cpp (1 of 165 files). Show all
Unified · Split
| @@ -117,8 +117,11 @@ · 116 unmodified lines | ||
| 117 | 117 | #include "devices/TV3DManager.h" |
| 118 | 118 | |
| 119 | 119 | #include "gpu/Batch.h" |
| 120 | +#include "gpu/Context.h" | |
| 120 | 121 | #include "gpu/GLBackend.h" |
| 121 | 122 | |
| 123 | +#include "RenderDeferredTask.h" | |
| 124 | + | |
| 122 | 125 | #include "scripting/AccountScriptingInterface.h" |
| 123 | 126 | #include "scripting/AudioDeviceScriptingInterface.h" |
| 124 | 127 | #include "scripting/ClipboardScriptingInterface.h" |
| @@ -143,6 +146,7 @@ · 18 unmodified lines | ||
| 143 | 146 | #include "ui/Stats.h" |
| 144 | 147 | #include "ui/AddressBarDialog.h" |
| 145 | 148 | |
| 149 | + | |
| 146 | 150 | // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU |
| 147 | 151 | #if defined(Q_OS_WIN) |
| 148 | 152 | extern "C" { |
| @@ -250,12 +254,12 @@ bool setupEssentials(int& argc, char** argv) { · 101 unmodified lines | ||
| 250 | 254 | } |
| 251 | 255 | // Set build version |
| 252 | 256 | QCoreApplication::setApplicationVersion(BUILD_VERSION); |
| 253 | − | |
| 257 | + | |
| 254 | 258 | DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); |
| 255 | 259 | DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>(); |
| 256 | 260 | |
| 257 | 261 | Setting::init(); |
| 258 | − | |
| 262 | + | |
| 259 | 263 | // Set dependencies |
| 260 | 264 | auto addressManager = DependencyManager::set<AddressManager>(); |
| 261 | 265 | auto nodeList = DependencyManager::set<NodeList>(NodeType::Agent, listenPort); |
| @@ -289,6 +293,7 @@ bool setupEssentials(int& argc, char** argv) { · 27 unmodified lines | ||
| 289 | 293 | auto discoverabilityManager = DependencyManager::set<DiscoverabilityManager>(); |
| 290 | 294 | auto sceneScriptingInterface = DependencyManager::set<SceneScriptingInterface>(); |
| 291 | 295 | auto offscreenUi = DependencyManager::set<OffscreenUi>(); |
| 296 | + auto pathUtils = DependencyManager::set<PathUtils>(); | |
| 292 | 297 | |
| 293 | 298 | return true; |
| 294 | 299 | } |
| @@ -355,9 +360,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 60 unmodified lines | ||
| 355 | 360 | |
| 356 | 361 | QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf"); |
| 357 | 362 | _window->setWindowTitle("Interface"); |
| 358 | − | |
| 363 | + | |
| 359 | 364 | Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us |
| 360 | − | |
| 365 | + | |
| 361 | 366 | auto nodeList = DependencyManager::get<NodeList>(); |
| 362 | 367 | |
| 363 | 368 | _myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); |
| @@ -369,7 +374,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 5 unmodified lines | ||
| 369 | 374 | _bookmarks = new Bookmarks(); // Before setting up the menu |
| 370 | 375 | |
| 371 | 376 | _runningScriptsWidget = new RunningScriptsWidget(_window); |
| 372 | − | |
| 377 | + _renderEngine->addTask(render::TaskPointer(new RenderDeferredTask())); | |
| 378 | + _renderEngine->registerScene(_main3DScene); | |
| 379 | + | |
| 373 | 380 | // start the nodeThread so its event loop is running |
| 374 | 381 | QThread* nodeThread = new QThread(this); |
| 375 | 382 | nodeThread->setObjectName("Datagram Processor Thread"); |
| @@ -377,14 +384,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 1 unmodified line | ||
| 377 | 384 | |
| 378 | 385 | // make sure the node thread is given highest priority |
| 379 | 386 | nodeThread->setPriority(QThread::TimeCriticalPriority); |
| 380 | − | |
| 387 | + | |
| 381 | 388 | _datagramProcessor = new DatagramProcessor(nodeList.data()); |
| 382 | − | |
| 389 | + | |
| 383 | 390 | // have the NodeList use deleteLater from DM customDeleter |
| 384 | 391 | nodeList->setCustomDeleter([](Dependency* dependency) { |
| 385 | 392 | static_cast<NodeList*>(dependency)->deleteLater(); |
| 386 | 393 | }); |
| 387 | − | |
| 394 | + | |
| 388 | 395 | // put the NodeList and datagram processing on the node thread |
| 389 | 396 | nodeList->moveToThread(nodeThread); |
| 390 | 397 | |
| @@ -392,7 +399,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 1 unmodified line | ||
| 392 | 399 | // emit checkBackgroundDownloads to cause the GeometryCache to check it's queue for requested background |
| 393 | 400 | // downloads. |
| 394 | 401 | QSharedPointer<GeometryCache> geometryCacheP = DependencyManager::get<GeometryCache>(); |
| 395 | − ResourceCache *geometryCache = geometryCacheP.data(); | |
| 402 | + ResourceCache* geometryCache = geometryCacheP.data(); | |
| 396 | 403 | connect(this, &Application::checkBackgroundDownloads, geometryCache, &ResourceCache::checkAsynchronousGets); |
| 397 | 404 | |
| 398 | 405 | // connect the DataProcessor processDatagrams slot to the QUDPSocket readyRead() signal |
| @@ -401,20 +408,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 2 unmodified lines | ||
| 401 | 408 | // put the audio processing on a separate thread |
| 402 | 409 | QThread* audioThread = new QThread(); |
| 403 | 410 | audioThread->setObjectName("Audio Thread"); |
| 404 | − | |
| 411 | + | |
| 405 | 412 | auto audioIO = DependencyManager::get<AudioClient>(); |
| 406 | − | |
| 413 | + | |
| 407 | 414 | audioIO->setPositionGetter(getPositionForAudio); |
| 408 | 415 | audioIO->setOrientationGetter(getOrientationForAudio); |
| 409 | − | |
| 416 | + | |
| 410 | 417 | audioIO->moveToThread(audioThread); |
| 411 | 418 | connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start); |
| 412 | 419 | connect(audioIO.data(), &AudioClient::destroyed, audioThread, &QThread::quit); |
| 413 | 420 | connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater); |
| 414 | 421 | connect(audioIO.data(), &AudioClient::muteToggled, this, &Application::audioMuteToggled); |
| 422 | + connect(audioIO.data(), &AudioClient::receivedFirstPacket, | |
| 423 | + &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::receivedFirstPacket); | |
| 415 | 424 | |
| 416 | 425 | audioThread->start(); |
| 417 | − | |
| 426 | + | |
| 418 | 427 | const DomainHandler& domainHandler = nodeList->getDomainHandler(); |
| 419 | 428 | |
| 420 | 429 | connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); |
| @@ -433,7 +442,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 12 unmodified lines | ||
| 433 | 442 | auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>(); |
| 434 | 443 | connect(locationUpdateTimer, &QTimer::timeout, discoverabilityManager.data(), &DiscoverabilityManager::updateLocation); |
| 435 | 444 | locationUpdateTimer->start(DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS); |
| 436 | − | |
| 445 | + | |
| 437 | 446 | // if we get a domain change, immediately attempt update location in metaverse server |
| 438 | 447 | connect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain, |
| 439 | 448 | discoverabilityManager.data(), &DiscoverabilityManager::updateLocation); |
| @@ -467,13 +476,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 27 unmodified lines | ||
| 467 | 476 | |
| 468 | 477 | // once the event loop has started, check and signal for an access token |
| 469 | 478 | QMetaObject::invokeMethod(&accountManager, "checkAndSignalForAccessToken", Qt::QueuedConnection); |
| 470 | − | |
| 479 | + | |
| 471 | 480 | auto addressManager = DependencyManager::get<AddressManager>(); |
| 472 | − | |
| 481 | + | |
| 473 | 482 | // use our MyAvatar position and quat for address manager path |
| 474 | 483 | addressManager->setPositionGetter(getPositionForPath); |
| 475 | 484 | addressManager->setOrientationGetter(getOrientationForPath); |
| 476 | − | |
| 485 | + | |
| 477 | 486 | connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); |
| 478 | 487 | connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); |
| 479 | 488 | |
| @@ -505,7 +514,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 25 unmodified lines | ||
| 505 | 514 | cache->setMaximumCacheSize(MAXIMUM_CACHE_SIZE); |
| 506 | 515 | cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache"); |
| 507 | 516 | networkAccessManager.setCache(cache); |
| 508 | − | |
| 517 | + | |
| 509 | 518 | ResourceCache::setRequestLimit(3); |
| 510 | 519 | |
| 511 | 520 | _window->setCentralWidget(_glWidget); |
| @@ -557,11 +566,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 45 unmodified lines | ||
| 557 | 566 | connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)), |
| 558 | 567 | bandwidthRecorder.data(), SLOT(updateInboundData(const quint8, const int))); |
| 559 | 568 | |
| 560 | − connect(&_myAvatar->getSkeletonModel(), &SkeletonModel::skeletonLoaded, | |
| 569 | + connect(&_myAvatar->getSkeletonModel(), &SkeletonModel::skeletonLoaded, | |
| 561 | 570 | this, &Application::checkSkeleton, Qt::QueuedConnection); |
| 562 | 571 | |
| 563 | 572 | // Setup the userInputMapper with the actions |
| 564 | − // Setup the keyboardMouseDevice and the user input mapper with the default bindings | |
| 573 | + // Setup the keyboardMouseDevice and the user input mapper with the default bindings | |
| 565 | 574 | _keyboardMouseDevice.registerToUserInputMapper(_userInputMapper); |
| 566 | 575 | _keyboardMouseDevice.assignDefaultInputMapping(_userInputMapper); |
| 567 | 576 | |
| @@ -577,7 +586,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 9 unmodified lines | ||
| 577 | 586 | // do this as late as possible so that all required subsystems are initialized |
| 578 | 587 | loadScripts(); |
| 579 | 588 | } |
| 580 | − | |
| 589 | + | |
| 581 | 590 | loadSettings(); |
| 582 | 591 | int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now |
| 583 | 592 | connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings); |
| @@ -587,12 +596,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 3 unmodified lines | ||
| 587 | 596 | _settingsTimer.setSingleShot(false); |
| 588 | 597 | _settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); |
| 589 | 598 | _settingsThread.start(); |
| 590 | − | |
| 599 | + | |
| 591 | 600 | _trayIcon->show(); |
| 592 | − | |
| 601 | + | |
| 593 | 602 | // set the local loopback interface for local sounds from audio scripts |
| 594 | 603 | AudioScriptingInterface::getInstance().setLocalAudioInterface(audioIO.data()); |
| 595 | − | |
| 604 | + | |
| 596 | 605 | #ifdef HAVE_RTMIDI |
| 597 | 606 | // setup the MIDIManager |
| 598 | 607 | MIDIManager& midiManagerInstance = MIDIManager::getInstance(); |
| @@ -600,7 +609,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 1 unmodified line | ||
| 600 | 609 | #endif |
| 601 | 610 | |
| 602 | 611 | this->installEventFilter(this); |
| 603 | − // The offscreen UI needs to intercept the mouse and keyboard | |
| 612 | + // The offscreen UI needs to intercept the mouse and keyboard | |
| 604 | 613 | // events coming from the onscreen window |
| 605 | 614 | _glWidget->installEventFilter(DependencyManager::get<OffscreenUi>().data()); |
| 606 | 615 | |
| @@ -618,7 +627,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 11 unmodified lines | ||
| 618 | 627 | |
| 619 | 628 | void Application::aboutToQuit() { |
| 620 | 629 | emit beforeAboutToQuit(); |
| 621 | − | |
| 630 | + | |
| 622 | 631 | _aboutToQuit = true; |
| 623 | 632 | cleanupBeforeQuit(); |
| 624 | 633 | } |
| @@ -630,7 +639,7 @@ void Application::cleanupBeforeQuit() { · 5 unmodified lines | ||
| 630 | 639 | _datagramProcessor->shutdown(); // tell the datagram processor we're shutting down, so it can short circuit |
| 631 | 640 | _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts |
| 632 | 641 | ScriptEngine::stopAllScripts(this); // stop all currently running global scripts |
| 633 | − | |
| 642 | + | |
| 634 | 643 | // first stop all timers directly or by invokeMethod |
| 635 | 644 | // depending on what thread they run in |
| 636 | 645 | locationUpdateTimer->stop(); |
| @@ -657,11 +666,11 @@ void Application::cleanupBeforeQuit() { · 20 unmodified lines | ||
| 657 | 666 | |
| 658 | 667 | // let the avatar mixer know we're out |
| 659 | 668 | MyAvatar::sendKillAvatar(); |
| 660 | − | |
| 669 | + | |
| 661 | 670 | // stop the AudioClient |
| 662 | 671 | QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), |
| 663 | 672 | "stop", Qt::BlockingQueuedConnection); |
| 664 | − | |
| 673 | + | |
| 665 | 674 | // destroy the AudioClient so it and its thread have a chance to go down safely |
| 666 | 675 | DependencyManager::destroy<AudioClient>(); |
| 667 | 676 | |
| @@ -670,12 +679,12 @@ void Application::cleanupBeforeQuit() { · 2 unmodified lines | ||
| 670 | 679 | #endif |
| 671 | 680 | } |
| 672 | 681 | |
| 673 | −Application::~Application() { | |
| 682 | +Application::~Application() { | |
| 674 | 683 | EntityTree* tree = _entities.getTree(); |
| 675 | 684 | tree->lockForWrite(); |
| 676 | 685 | _entities.getTree()->setSimulation(NULL); |
| 677 | 686 | tree->unlock(); |
| 678 | − | |
| 687 | + | |
| 679 | 688 | _octreeProcessor.terminate(); |
| 680 | 689 | _entityEditSender.terminate(); |
| 681 | 690 | |
| @@ -685,7 +694,7 @@ Application::~Application() { · 3 unmodified lines | ||
| 685 | 694 | _myAvatar = NULL; |
| 686 | 695 | |
| 687 | 696 | ModelEntityItem::cleanupLoadedAnimations(); |
| 688 | − | |
| 697 | + | |
| 689 | 698 | // stop the glWidget frame timer so it doesn't call paintGL |
| 690 | 699 | _glWidget->stopFrameTimer(); |
| 691 | 700 | |
| @@ -700,10 +709,10 @@ Application::~Application() { · 8 unmodified lines | ||
| 700 | 709 | DependencyManager::destroy<GeometryCache>(); |
| 701 | 710 | DependencyManager::destroy<ScriptCache>(); |
| 702 | 711 | DependencyManager::destroy<SoundCache>(); |
| 703 | − | |
| 712 | + | |
| 704 | 713 | QThread* nodeThread = DependencyManager::get<NodeList>()->thread(); |
| 705 | 714 | DependencyManager::destroy<NodeList>(); |
| 706 | − | |
| 715 | + | |
| 707 | 716 | // ask the node thread to quit and wait until it is done |
| 708 | 717 | nodeThread->quit(); |
| 709 | 718 | nodeThread->wait(); |
| @@ -757,8 +766,8 @@ void Application::initializeGL() { · 47 unmodified lines | ||
| 757 | 766 | initDisplay(); |
| 758 | 767 | qCDebug(interfaceapp, "Initialized Display."); |
| 759 | 768 | |
| 760 | − // The UI can't be created until the primary OpenGL | |
| 761 | − // context is created, because it needs to share | |
| 769 | + // The UI can't be created until the primary OpenGL | |
| 770 | + // context is created, because it needs to share | |
| 762 | 771 | // texture resources |
| 763 | 772 | initializeUi(); |
| 764 | 773 | qCDebug(interfaceapp, "Initialized Offscreen UI."); |
| @@ -837,6 +846,13 @@ void Application::initializeUi() { · 72 unmodified lines | ||
| 837 | 846 | void Application::paintGL() { |
| 838 | 847 | PROFILE_RANGE(__FUNCTION__); |
| 839 | 848 | _glWidget->makeCurrent(); |
| 849 | + | |
| 850 | + auto lodManager = DependencyManager::get<LODManager>(); | |
| 851 | + gpu::Context context(new gpu::GLBackend()); | |
| 852 | + RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), | |
| 853 | + lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, | |
| 854 | + RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); | |
| 855 | + | |
| 840 | 856 | PerformanceTimer perfTimer("paintGL"); |
| 841 | 857 | //Need accurate frame timing for the oculus rift |
| 842 | 858 | if (OculusManager::isConnected()) { |
| @@ -850,7 +866,7 @@ void Application::paintGL() { · 7 unmodified lines | ||
| 850 | 866 | |
| 851 | 867 | { |
| 852 | 868 | PerformanceTimer perfTimer("renderOverlay"); |
| 853 | − _applicationOverlay.renderOverlay(); | |
| 869 | + _applicationOverlay.renderOverlay(&renderArgs); | |
| 854 | 870 | } |
| 855 | 871 | |
| 856 | 872 | glEnable(GL_LINE_SMOOTH); |
| @@ -899,22 +915,23 @@ void Application::paintGL() { · 42 unmodified lines | ||
| 899 | 915 | loadViewFrustum(_myCamera, _viewFrustum); |
| 900 | 916 | |
| 901 | 917 | if (getShadowsEnabled()) { |
| 902 | − updateShadowMap(); | |
| 918 | + renderArgs._renderMode = RenderArgs::SHADOW_RENDER_MODE; | |
| 919 | + updateShadowMap(&renderArgs); | |
| 903 | 920 | } |
| 904 | 921 | |
| 922 | + renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; | |
| 923 | + | |
| 905 | 924 | if (OculusManager::isConnected()) { |
| 906 | 925 | //When in mirror mode, use camera rotation. Otherwise, use body rotation |
| 907 | 926 | if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { |
| 908 | − OculusManager::display(_glWidget, _myCamera.getRotation(), _myCamera.getPosition(), _myCamera); | |
| 927 | + OculusManager::display(_glWidget, &renderArgs, _myCamera.getRotation(), _myCamera.getPosition(), _myCamera); | |
| 909 | 928 | } else { |
| 910 | − OculusManager::display(_glWidget, _myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera); | |
| 929 | + OculusManager::display(_glWidget, &renderArgs, _myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera); | |
| 911 | 930 | } |
| 912 | 931 | } else if (TV3DManager::isConnected()) { |
| 913 | − | |
| 914 | − TV3DManager::display(_myCamera); | |
| 915 | − | |
| 932 | + TV3DManager::display(&renderArgs, _myCamera); | |
| 916 | 933 | } else { |
| 917 | − DependencyManager::get<GlowEffect>()->prepare(); | |
| 934 | + DependencyManager::get<GlowEffect>()->prepare(&renderArgs); | |
| 918 | 935 | |
| 919 | 936 | // Viewport is assigned to the size of the framebuffer |
| 920 | 937 | QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize(); |
| @@ -923,16 +940,16 @@ void Application::paintGL() { · 2 unmodified lines | ||
| 923 | 940 | glMatrixMode(GL_MODELVIEW); |
| 924 | 941 | glPushMatrix(); |
| 925 | 942 | glLoadIdentity(); |
| 926 | − displaySide(_myCamera); | |
| 943 | + displaySide(&renderArgs, _myCamera); | |
| 927 | 944 | glPopMatrix(); |
| 928 | 945 | |
| 929 | 946 | if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { |
| 930 | − _rearMirrorTools->render(true, _glWidget->mapFromGlobal(QCursor::pos())); | |
| 947 | + _rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos())); | |
| 931 | 948 | } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { |
| 932 | − renderRearViewMirror(_mirrorViewRect); | |
| 949 | + renderRearViewMirror(&renderArgs, _mirrorViewRect); | |
| 933 | 950 | } |
| 934 | 951 | |
| 935 | − auto finalFbo = DependencyManager::get<GlowEffect>()->render(); | |
| 952 | + auto finalFbo = DependencyManager::get<GlowEffect>()->render(&renderArgs); | |
| 936 | 953 | |
| 937 | 954 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); |
| 938 | 955 | glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); |
| @@ -946,12 +963,13 @@ void Application::paintGL() { · 7 unmodified lines | ||
| 946 | 963 | |
| 947 | 964 | if (!OculusManager::isConnected() || OculusManager::allowSwap()) { |
| 948 | 965 | _glWidget->swapBuffers(); |
| 949 | − } | |
| 966 | + } | |
| 950 | 967 | |
| 951 | 968 | if (OculusManager::isConnected()) { |
| 952 | 969 | OculusManager::endFrameTiming(); |
| 953 | 970 | } |
| 954 | 971 | _frameCount++; |
| 972 | + Stats::getInstance()->setRenderDetails(renderArgs._details); | |
| 955 | 973 | } |
| 956 | 974 | |
| 957 | 975 | void Application::runTests() { |
| @@ -1036,7 +1054,7 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) · 78 unmodified lines | ||
| 1036 | 1054 | // Tell our viewFrustum about this change, using the application camera |
| 1037 | 1055 | if (updateViewFrustum) { |
| 1038 | 1056 | loadViewFrustum(camera, _viewFrustum); |
| 1039 | − } | |
| 1057 | + } | |
| 1040 | 1058 | |
| 1041 | 1059 | glMatrixMode(GL_MODELVIEW); |
| 1042 | 1060 | } |
| @@ -1104,11 +1122,11 @@ bool Application::event(QEvent* event) { · 61 unmodified lines | ||
| 1104 | 1122 | |
| 1105 | 1123 | // handle custom URL |
| 1106 | 1124 | if (event->type() == QEvent::FileOpen) { |
| 1107 | − | |
| 1125 | + | |
| 1108 | 1126 | QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event); |
| 1109 | 1127 | |
| 1110 | 1128 | QUrl url = fileEvent->url(); |
| 1111 | − | |
| 1129 | + | |
| 1112 | 1130 | if (!url.isEmpty()) { |
| 1113 | 1131 | QString urlString = url.toString(); |
| 1114 | 1132 | if (canAcceptURL(urlString)) { |
| @@ -1117,7 +1135,7 @@ bool Application::event(QEvent* event) { · 2 unmodified lines | ||
| 1117 | 1135 | } |
| 1118 | 1136 | return false; |
| 1119 | 1137 | } |
| 1120 | − | |
| 1138 | + | |
| 1121 | 1139 | if (HFActionEvent::types().contains(event->type())) { |
| 1122 | 1140 | _controllerScriptingInterface.handleMetaEvent(static_cast<HFMetaEvent*>(event)); |
| 1123 | 1141 | } |
| @@ -1183,7 +1201,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 59 unmodified lines | ||
| 1183 | 1201 | Menu::getInstance()->triggerOption(MenuOption::AddressBar); |
| 1184 | 1202 | } else if (isShifted) { |
| 1185 | 1203 | Menu::getInstance()->triggerOption(MenuOption::LodTools); |
| 1186 | − } | |
| 1204 | + } | |
| 1187 | 1205 | break; |
| 1188 | 1206 | |
| 1189 | 1207 | case Qt::Key_F: { |
| @@ -1224,7 +1242,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 34 unmodified lines | ||
| 1224 | 1242 | case Qt::Key_Backslash: |
| 1225 | 1243 | Menu::getInstance()->triggerOption(MenuOption::Chat); |
| 1226 | 1244 | break; |
| 1227 | − | |
| 1245 | + | |
| 1228 | 1246 | case Qt::Key_Up: |
| 1229 | 1247 | if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { |
| 1230 | 1248 | if (!isShifted) { |
| @@ -1353,18 +1371,18 @@ void Application::keyPressEvent(QKeyEvent* event) { · 122 unmodified lines | ||
| 1353 | 1371 | computePickRay(getTrueMouseX(), getTrueMouseY())); |
| 1354 | 1372 | sendEvent(this, &startActionEvent); |
| 1355 | 1373 | } |
| 1356 | − | |
| 1374 | + | |
| 1357 | 1375 | break; |
| 1358 | 1376 | } |
| 1359 | 1377 | case Qt::Key_Escape: { |
| 1360 | 1378 | OculusManager::abandonCalibration(); |
| 1361 | − | |
| 1379 | + | |
| 1362 | 1380 | if (!event->isAutoRepeat()) { |
| 1363 | 1381 | // this starts the HFCancelEvent |
| 1364 | 1382 | HFBackEvent startBackEvent(HFBackEvent::startType()); |
| 1365 | 1383 | sendEvent(this, &startBackEvent); |
| 1366 | 1384 | } |
| 1367 | − | |
| 1385 | + | |
| 1368 | 1386 | break; |
| 1369 | 1387 | } |
| 1370 | 1388 | |
| @@ -1426,7 +1444,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) { · 55 unmodified lines | ||
| 1426 | 1444 | |
| 1427 | 1445 | void Application::focusOutEvent(QFocusEvent* event) { |
| 1428 | 1446 | _keyboardMouseDevice.focusOutEvent(event); |
| 1429 | − | |
| 1447 | + | |
| 1430 | 1448 | // synthesize events for keys currently pressed, since we may not get their release events |
| 1431 | 1449 | foreach (int key, _keysPressed) { |
| 1432 | 1450 | QKeyEvent event(QEvent::KeyRelease, key, Qt::NoModifier); |
| @@ -1441,12 +1459,12 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { · 8 unmodified lines | ||
| 1441 | 1459 | if (!_lastMouseMoveWasSimulated) { |
| 1442 | 1460 | _lastMouseMove = usecTimestampNow(); |
| 1443 | 1461 | } |
| 1444 | − | |
| 1462 | + | |
| 1445 | 1463 | if (_aboutToQuit) { |
| 1446 | 1464 | return; |
| 1447 | 1465 | } |
| 1448 | − | |
| 1449 | − if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) | |
| 1466 | + | |
| 1467 | + if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) | |
| 1450 | 1468 | && !Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { |
| 1451 | 1469 | // Show/hide menu bar in fullscreen |
| 1452 | 1470 | if (event->globalY() > _menuBarHeight) { |
| @@ -1459,7 +1477,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { · 6 unmodified lines | ||
| 1459 | 1477 | } |
| 1460 | 1478 | |
| 1461 | 1479 | _entities.mouseMoveEvent(event, deviceID); |
| 1462 | − | |
| 1480 | + | |
| 1463 | 1481 | _controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts |
| 1464 | 1482 | // if one of our scripts have asked to capture this event, then stop processing it |
| 1465 | 1483 | if (_controllerScriptingInterface.isMouseCaptured()) { |
| @@ -1467,7 +1485,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { · 1 unmodified line | ||
| 1467 | 1485 | } |
| 1468 | 1486 | |
| 1469 | 1487 | _keyboardMouseDevice.mouseMoveEvent(event, deviceID); |
| 1470 | − | |
| 1488 | + | |
| 1471 | 1489 | } |
| 1472 | 1490 | |
| 1473 | 1491 | void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { |
| @@ -1493,7 +1511,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { · 19 unmodified lines | ||
| 1493 | 1511 | _mouseDragStartedX = getTrueMouseX(); |
| 1494 | 1512 | _mouseDragStartedY = getTrueMouseY(); |
| 1495 | 1513 | _mousePressed = true; |
| 1496 | − | |
| 1514 | + | |
| 1497 | 1515 | if (mouseOnScreen()) { |
| 1498 | 1516 | if (DependencyManager::get<AudioToolBox>()->mousePressEvent(getMouseX(), getMouseY())) { |
| 1499 | 1517 | // stop propagation |
| @@ -1510,7 +1528,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { · 10 unmodified lines | ||
| 1510 | 1528 | return; |
| 1511 | 1529 | } |
| 1512 | 1530 | } |
| 1513 | − | |
| 1531 | + | |
| 1514 | 1532 | // nobody handled this - make it an action event on the _window object |
| 1515 | 1533 | HFActionEvent actionEvent(HFActionEvent::startType(), |
| 1516 | 1534 | computePickRay(event->x(), event->y())); |
| @@ -1558,14 +1576,14 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { · 41 unmodified lines | ||
| 1558 | 1576 | |
| 1559 | 1577 | if (event->button() == Qt::LeftButton) { |
| 1560 | 1578 | _mousePressed = false; |
| 1561 | − | |
| 1579 | + | |
| 1562 | 1580 | if (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && mouseOnScreen()) { |
| 1563 | 1581 | // let's set horizontal offset to give stats some margin to mirror |
| 1564 | 1582 | int horizontalOffset = MIRROR_VIEW_WIDTH; |
| 1565 | 1583 | Stats::getInstance()->checkClick(getMouseX(), getMouseY(), |
| 1566 | 1584 | getMouseDragStartedX(), getMouseDragStartedY(), horizontalOffset); |
| 1567 | 1585 | } |
| 1568 | − | |
| 1586 | + | |
| 1569 | 1587 | // fire an action end event |
| 1570 | 1588 | HFActionEvent actionEvent(HFActionEvent::endType(), |
| 1571 | 1589 | computePickRay(event->x(), event->y())); |
| @@ -1674,7 +1692,7 @@ void Application::dropEvent(QDropEvent *event) { · 102 unmodified lines | ||
| 1674 | 1692 | } |
| 1675 | 1693 | } |
| 1676 | 1694 | } |
| 1677 | − | |
| 1695 | + | |
| 1678 | 1696 | if (atLeastOneFileAccepted) { |
| 1679 | 1697 | event->acceptProposedAction(); |
| 1680 | 1698 | } |
| @@ -1694,7 +1712,7 @@ void Application::dragEnterEvent(QDragEnterEvent* event) { · 13 unmodified lines | ||
| 1694 | 1712 | bool Application::acceptSnapshot(const QString& urlString) { |
| 1695 | 1713 | QUrl url(urlString); |
| 1696 | 1714 | QString snapshotPath = url.toLocalFile(); |
| 1697 | − | |
| 1715 | + | |
| 1698 | 1716 | SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); |
| 1699 | 1717 | if (snapshotData) { |
| 1700 | 1718 | if (!snapshotData->getURL().toString().isEmpty()) { |
| @@ -1704,7 +1722,7 @@ bool Application::acceptSnapshot(const QString& urlString) { · 3 unmodified lines | ||
| 1704 | 1722 | QMessageBox msgBox; |
| 1705 | 1723 | msgBox.setText("No location details were found in the file " |
| 1706 | 1724 | + snapshotPath + ", try dragging in an authentic Hifi snapshot."); |
| 1707 | − | |
| 1725 | + | |
| 1708 | 1726 | msgBox.setStandardButtons(QMessageBox::Ok); |
| 1709 | 1727 | msgBox.exec(); |
| 1710 | 1728 | } |
| @@ -1737,7 +1755,7 @@ void Application::checkFPS() { · 26 unmodified lines | ||
| 1737 | 1755 | |
| 1738 | 1756 | void Application::idle() { |
| 1739 | 1757 | PerformanceTimer perfTimer("idle"); |
| 1740 | − | |
| 1758 | + | |
| 1741 | 1759 | if (_aboutToQuit) { |
| 1742 | 1760 | return; // bail early, nothing to do here. |
| 1743 | 1761 | } |
| @@ -1925,7 +1943,7 @@ int Application::getMouseDragStartedY() const { · 181 unmodified lines | ||
| 1925 | 1943 | FaceTracker* Application::getActiveFaceTracker() { |
| 1926 | 1944 | auto faceshift = DependencyManager::get<Faceshift>(); |
| 1927 | 1945 | auto dde = DependencyManager::get<DdeFaceTracker>(); |
| 1928 | − | |
| 1946 | + | |
| 1929 | 1947 | return (dde->isActive() ? static_cast<FaceTracker*>(dde.data()) : |
| 1930 | 1948 | (faceshift->isActive() ? static_cast<FaceTracker*>(faceshift.data()) : NULL)); |
| 1931 | 1949 | } |
| @@ -2058,14 +2076,14 @@ void Application::saveSettings() { · 126 unmodified lines | ||
| 2058 | 2076 | |
| 2059 | 2077 | bool Application::importEntities(const QString& urlOrFilename) { |
| 2060 | 2078 | _entityClipboard.eraseAllOctreeElements(); |
| 2061 | − | |
| 2079 | + | |
| 2062 | 2080 | QUrl url(urlOrFilename); |
| 2063 | − | |
| 2081 | + | |
| 2064 | 2082 | // if the URL appears to be invalid or relative, then it is probably a local file |
| 2065 | 2083 | if (!url.isValid() || url.isRelative()) { |
| 2066 | 2084 | url = QUrl::fromLocalFile(urlOrFilename); |
| 2067 | 2085 | } |
| 2068 | − | |
| 2086 | + | |
| 2069 | 2087 | bool success = _entityClipboard.readFromURL(url.toString()); |
| 2070 | 2088 | if (success) { |
| 2071 | 2089 | _entityClipboard.reaverageOctreeElements(); |
| @@ -2089,7 +2107,7 @@ void Application::initDisplay() { · 17 unmodified lines | ||
| 2089 | 2107 | void Application::init() { |
| 2090 | 2108 | // Make sure Login state is up to date |
| 2091 | 2109 | DependencyManager::get<DialogsManager>()->toggleLoginDialog(); |
| 2092 | − | |
| 2110 | + | |
| 2093 | 2111 | _environment.init(); |
| 2094 | 2112 | |
| 2095 | 2113 | DependencyManager::get<DeferredLightingEffect>()->init(this); |
| @@ -2117,7 +2135,7 @@ void Application::init() { · 21 unmodified lines | ||
| 2117 | 2135 | |
| 2118 | 2136 | _timerStart.start(); |
| 2119 | 2137 | _lastTimeUpdated.start(); |
| 2120 | − | |
| 2138 | + | |
| 2121 | 2139 | // when --url in command line, teleport to location |
| 2122 | 2140 | const QString HIFI_URL_COMMAND_LINE_KEY = "--url"; |
| 2123 | 2141 | int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY); |
| @@ -2125,11 +2143,11 @@ void Application::init() { · 1 unmodified line | ||
| 2125 | 2143 | if (urlIndex != -1) { |
| 2126 | 2144 | addressLookupString = arguments().value(urlIndex + 1); |
| 2127 | 2145 | } |
| 2128 | − | |
| 2146 | + | |
| 2129 | 2147 | DependencyManager::get<AddressManager>()->loadSettings(addressLookupString); |
| 2130 | − | |
| 2148 | + | |
| 2131 | 2149 | qCDebug(interfaceapp) << "Loaded settings"; |
| 2132 | − | |
| 2150 | + | |
| 2133 | 2151 | #ifdef __APPLE__ |
| 2134 | 2152 | if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseEnabled)) { |
| 2135 | 2153 | // on OS X we only setup sixense if the user wants it on - this allows running without the hid_init crash |
| @@ -2237,7 +2255,7 @@ void Application::updateMouseRay() { · 101 unmodified lines | ||
| 2237 | 2255 | PickRay pickRay = computePickRay(getTrueMouseX(), getTrueMouseY()); |
| 2238 | 2256 | _mouseRayOrigin = pickRay.origin; |
| 2239 | 2257 | _mouseRayDirection = pickRay.direction; |
| 2240 | − | |
| 2258 | + | |
| 2241 | 2259 | // adjust for mirroring |
| 2242 | 2260 | if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { |
| 2243 | 2261 | glm::vec3 mouseRayOffset = _mouseRayOrigin - _viewFrustum.getPosition(); |
| @@ -2269,28 +2287,27 @@ void Application::updateMyAvatarLookAtPosition() { · 25 unmodified lines | ||
| 2269 | 2287 | lookAtSpot = OculusManager::getRightEyePosition(); |
| 2270 | 2288 | } |
| 2271 | 2289 | } |
| 2272 | − | |
| 2290 | + | |
| 2273 | 2291 | } else { |
| 2274 | − AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().toStrongRef(); | |
| 2275 | − if (lookingAt && _myAvatar != lookingAt.data()) { | |
| 2276 | − | |
| 2292 | + AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().lock(); | |
| 2293 | + if (lookingAt && _myAvatar != lookingAt.get()) { | |
| 2277 | 2294 | isLookingAtSomeone = true; |
| 2278 | 2295 | // If I am looking at someone else, look directly at one of their eyes |
| 2279 | 2296 | if (tracker && !tracker->isMuted()) { |
| 2280 | 2297 | // If a face tracker is active, look at the eye for the side my gaze is biased toward |
| 2281 | 2298 | if (tracker->getEstimatedEyeYaw() > _myAvatar->getHead()->getFinalYaw()) { |
| 2282 | 2299 | // Look at their right eye |
| 2283 | − lookAtSpot = static_cast<Avatar*>(lookingAt.data())->getHead()->getRightEyePosition(); | |
| 2300 | + lookAtSpot = static_cast<Avatar*>(lookingAt.get())->getHead()->getRightEyePosition(); | |
| 2284 | 2301 | } else { |
| 2285 | 2302 | // Look at their left eye |
| 2286 | − lookAtSpot = static_cast<Avatar*>(lookingAt.data())->getHead()->getLeftEyePosition(); | |
| 2303 | + lookAtSpot = static_cast<Avatar*>(lookingAt.get())->getHead()->getLeftEyePosition(); | |
| 2287 | 2304 | } |
| 2288 | 2305 | } else { |
| 2289 | 2306 | // Need to add randomly looking back and forth between left and right eye for case with no tracker |
| 2290 | 2307 | if (_myAvatar->isLookingAtLeftEye()) { |
| 2291 | − lookAtSpot = static_cast<Avatar*>(lookingAt.data())->getHead()->getLeftEyePosition(); | |
| 2308 | + lookAtSpot = static_cast<Avatar*>(lookingAt.get())->getHead()->getLeftEyePosition(); | |
| 2292 | 2309 | } else { |
| 2293 | − lookAtSpot = static_cast<Avatar*>(lookingAt.data())->getHead()->getRightEyePosition(); | |
| 2310 | + lookAtSpot = static_cast<Avatar*>(lookingAt.get())->getHead()->getRightEyePosition(); | |
| 2294 | 2311 | } |
| 2295 | 2312 | } |
| 2296 | 2313 | } else { |
| @@ -2360,7 +2377,7 @@ void Application::updateDialogs(float deltaTime) { · 63 unmodified lines | ||
| 2360 | 2377 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| 2361 | 2378 | PerformanceWarning warn(showWarnings, "Application::updateDialogs()"); |
| 2362 | 2379 | auto dialogsManager = DependencyManager::get<DialogsManager>(); |
| 2363 | − | |
| 2380 | + | |
| 2364 | 2381 | // Update bandwidth dialog, if any |
| 2365 | 2382 | BandwidthDialog* bandwidthDialog = dialogsManager->getBandwidthDialog(); |
| 2366 | 2383 | if (bandwidthDialog) { |
| @@ -2555,7 +2572,7 @@ void Application::update(float deltaTime) { · 188 unmodified lines | ||
| 2555 | 2572 | } |
| 2556 | 2573 | } |
| 2557 | 2574 | |
| 2558 | − // send packet containing downstream audio stats to the AudioMixer | |
| 2575 | + // send packet containing downstream audio stats to the AudioMixer | |
| 2559 | 2576 | { |
| 2560 | 2577 | quint64 sinceLastNack = now - _lastSendDownstreamAudioStats; |
| 2561 | 2578 | if (sinceLastNack > TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS) { |
| @@ -2577,64 +2594,64 @@ int Application::sendNackPackets() { · 15 unmodified lines | ||
| 2577 | 2594 | |
| 2578 | 2595 | // iterates thru all nodes in NodeList |
| 2579 | 2596 | auto nodeList = DependencyManager::get<NodeList>(); |
| 2580 | − | |
| 2597 | + | |
| 2581 | 2598 | nodeList->eachNode([&](const SharedNodePointer& node){ |
| 2582 | − | |
| 2599 | + | |
| 2583 | 2600 | if (node->getActiveSocket() && node->getType() == NodeType::EntityServer) { |
| 2584 | − | |
| 2601 | + | |
| 2585 | 2602 | QUuid nodeUUID = node->getUUID(); |
| 2586 | − | |
| 2603 | + | |
| 2587 | 2604 | // if there are octree packets from this node that are waiting to be processed, |
| 2588 | 2605 | // don't send a NACK since the missing packets may be among those waiting packets. |
| 2589 | 2606 | if (_octreeProcessor.hasPacketsToProcessFrom(nodeUUID)) { |
| 2590 | 2607 | return; |
| 2591 | 2608 | } |
| 2592 | − | |
| 2609 | + | |
| 2593 | 2610 | _octreeSceneStatsLock.lockForRead(); |
| 2594 | − | |
| 2611 | + | |
| 2595 | 2612 | // retreive octree scene stats of this node |
| 2596 | 2613 | if (_octreeServerSceneStats.find(nodeUUID) == _octreeServerSceneStats.end()) { |
| 2597 | 2614 | _octreeSceneStatsLock.unlock(); |
| 2598 | 2615 | return; |
| 2599 | 2616 | } |
| 2600 | − | |
| 2617 | + | |
| 2601 | 2618 | // get sequence number stats of node, prune its missing set, and make a copy of the missing set |
| 2602 | 2619 | SequenceNumberStats& sequenceNumberStats = _octreeServerSceneStats[nodeUUID].getIncomingOctreeSequenceNumberStats(); |
| 2603 | 2620 | sequenceNumberStats.pruneMissingSet(); |
| 2604 | 2621 | const QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers = sequenceNumberStats.getMissingSet(); |
| 2605 | − | |
| 2622 | + | |
| 2606 | 2623 | _octreeSceneStatsLock.unlock(); |
| 2607 | − | |
| 2624 | + | |
| 2608 | 2625 | // construct nack packet(s) for this node |
| 2609 | 2626 | int numSequenceNumbersAvailable = missingSequenceNumbers.size(); |
| 2610 | 2627 | QSet<OCTREE_PACKET_SEQUENCE>::const_iterator missingSequenceNumbersIterator = missingSequenceNumbers.constBegin(); |
| 2611 | 2628 | while (numSequenceNumbersAvailable > 0) { |
| 2612 | − | |
| 2629 | + | |
| 2613 | 2630 | char* dataAt = packet; |
| 2614 | 2631 | int bytesRemaining = MAX_PACKET_SIZE; |
| 2615 | − | |
| 2632 | + | |
| 2616 | 2633 | // pack header |
| 2617 | 2634 | int numBytesPacketHeader = nodeList->populatePacketHeader(packet, PacketTypeOctreeDataNack); |
| 2618 | 2635 | dataAt += numBytesPacketHeader; |
| 2619 | 2636 | bytesRemaining -= numBytesPacketHeader; |
| 2620 | − | |
| 2637 | + | |
| 2621 | 2638 | // calculate and pack the number of sequence numbers |
| 2622 | 2639 | int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE); |
| 2623 | 2640 | uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor); |
| 2624 | 2641 | uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; |
| 2625 | 2642 | *numSequenceNumbersAt = numSequenceNumbers; |
| 2626 | 2643 | dataAt += sizeof(uint16_t); |
| 2627 | − | |
| 2644 | + | |
| 2628 | 2645 | // pack sequence numbers |
| 2629 | 2646 | for (int i = 0; i < numSequenceNumbers; i++) { |
| 2630 | 2647 | OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; |
| 2631 | 2648 | *sequenceNumberAt = *missingSequenceNumbersIterator; |
| 2632 | 2649 | dataAt += sizeof(OCTREE_PACKET_SEQUENCE); |
| 2633 | − | |
| 2650 | + | |
| 2634 | 2651 | missingSequenceNumbersIterator++; |
| 2635 | 2652 | } |
| 2636 | 2653 | numSequenceNumbersAvailable -= numSequenceNumbers; |
| 2637 | − | |
| 2654 | + | |
| 2638 | 2655 | // send it |
| 2639 | 2656 | nodeList->writeUnverifiedDatagram(packet, dataAt - packet, node); |
| 2640 | 2657 | packetsSent++; |
| @@ -2676,7 +2693,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 35 unmodified lines | ||
| 2676 | 2693 | int unknownJurisdictionServers = 0; |
| 2677 | 2694 | |
| 2678 | 2695 | auto nodeList = DependencyManager::get<NodeList>(); |
| 2679 | − | |
| 2696 | + | |
| 2680 | 2697 | nodeList->eachNode([&](const SharedNodePointer& node) { |
| 2681 | 2698 | // only send to the NodeTypes that are serverType |
| 2682 | 2699 | if (node->getActiveSocket() && node->getType() == serverType) { |
| @@ -2736,17 +2753,17 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 53 unmodified lines | ||
| 2736 | 2753 | if (wantExtraDebugging) { |
| 2737 | 2754 | qCDebug(interfaceapp, "perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer); |
| 2738 | 2755 | } |
| 2739 | − | |
| 2756 | + | |
| 2740 | 2757 | nodeList->eachNode([&](const SharedNodePointer& node){ |
| 2741 | 2758 | // only send to the NodeTypes that are serverType |
| 2742 | 2759 | if (node->getActiveSocket() && node->getType() == serverType) { |
| 2743 | − | |
| 2760 | + | |
| 2744 | 2761 | // get the server bounds for this server |
| 2745 | 2762 | QUuid nodeUUID = node->getUUID(); |
| 2746 | − | |
| 2763 | + | |
| 2747 | 2764 | bool inView = false; |
| 2748 | 2765 | bool unknownView = false; |
| 2749 | − | |
| 2766 | + | |
| 2750 | 2767 | // if we haven't heard from this voxel server, go ahead and send it a query, so we |
| 2751 | 2768 | // can get the jurisdiction... |
| 2752 | 2769 | if (jurisdictions.find(nodeUUID) == jurisdictions.end()) { |
| @@ -2756,9 +2773,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 3 unmodified lines | ||
| 2756 | 2773 | } |
| 2757 | 2774 | } else { |
| 2758 | 2775 | const JurisdictionMap& map = (jurisdictions)[nodeUUID]; |
| 2759 | − | |
| 2776 | + | |
| 2760 | 2777 | unsigned char* rootCode = map.getRootOctalCode(); |
| 2761 | − | |
| 2778 | + | |
| 2762 | 2779 | if (rootCode) { |
| 2763 | 2780 | VoxelPositionSize rootDetails; |
| 2764 | 2781 | voxelDetailsForCode(rootCode, rootDetails); |
| @@ -2768,7 +2785,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 3 unmodified lines | ||
| 2768 | 2785 | rootDetails.s * TREE_SCALE); |
| 2769 | 2786 | |
| 2770 | 2787 | |
| 2771 | − | |
| 2788 | + | |
| 2772 | 2789 | ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); |
| 2773 | 2790 | if (serverFrustumLocation != ViewFrustum::OUTSIDE) { |
| 2774 | 2791 | inView = true; |
| @@ -2781,7 +2798,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 6 unmodified lines | ||
| 2781 | 2798 | } |
| 2782 | 2799 | } |
| 2783 | 2800 | } |
| 2784 | − | |
| 2801 | + | |
| 2785 | 2802 | if (inView) { |
| 2786 | 2803 | _octreeQuery.setMaxQueryPacketsPerSecond(perServerPPS); |
| 2787 | 2804 | } else if (unknownView) { |
| @@ -2789,7 +2806,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 1 unmodified line | ||
| 2789 | 2806 | qCDebug(interfaceapp) << "no known jurisdiction for node " << *node << ", give it budget of " |
| 2790 | 2807 | << perUnknownServer << " to send us jurisdiction."; |
| 2791 | 2808 | } |
| 2792 | − | |
| 2809 | + | |
| 2793 | 2810 | // set the query's position/orientation to be degenerate in a manner that will get the scene quickly |
| 2794 | 2811 | // If there's only one server, then don't do this, and just let the normal voxel query pass through |
| 2795 | 2812 | // as expected... this way, we will actually get a valid scene if there is one to be seen |
| @@ -2816,12 +2833,12 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 20 unmodified lines | ||
| 2816 | 2833 | |
| 2817 | 2834 | // insert packet type/version and node UUID |
| 2818 | 2835 | endOfQueryPacket += nodeList->populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType); |
| 2819 | − | |
| 2836 | + | |
| 2820 | 2837 | // encode the query data... |
| 2821 | 2838 | endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket); |
| 2822 | − | |
| 2839 | + | |
| 2823 | 2840 | int packetLength = endOfQueryPacket - queryPacket; |
| 2824 | − | |
| 2841 | + | |
| 2825 | 2842 | // make sure we still have an active socket |
| 2826 | 2843 | nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node); |
| 2827 | 2844 | } |
| @@ -2838,7 +2855,7 @@ bool Application::isHMDMode() const { · 10 unmodified lines | ||
| 2838 | 2855 | |
| 2839 | 2856 | QRect Application::getDesirableApplicationGeometry() { |
| 2840 | 2857 | QRect applicationGeometry = getWindow()->geometry(); |
| 2841 | − | |
| 2858 | + | |
| 2842 | 2859 | // If our parent window is on the HMD, then don't use its geometry, instead use |
| 2843 | 2860 | // the "main screen" geometry. |
| 2844 | 2861 | HMDToolsDialog* hmdTools = DependencyManager::get<DialogsManager>()->getHMDToolsDialog(); |
| @@ -2886,7 +2903,7 @@ glm::vec3 Application::getSunDirection() { · 41 unmodified lines | ||
| 2886 | 2903 | // FIXME, preprocessor guard this check to occur only in DEBUG builds |
| 2887 | 2904 | static QThread * activeRenderingThread = nullptr; |
| 2888 | 2905 | |
| 2889 | −void Application::updateShadowMap() { | |
| 2906 | +void Application::updateShadowMap(RenderArgs* renderArgs) { | |
| 2890 | 2907 | activeRenderingThread = QThread::currentThread(); |
| 2891 | 2908 | |
| 2892 | 2909 | PerformanceTimer perfTimer("shadowMap"); |
| @@ -2899,14 +2916,14 @@ void Application::updateShadowMap() { · 6 unmodified lines | ||
| 2899 | 2916 | glm::vec3 lightDirection = getSunDirection(); |
| 2900 | 2917 | glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); |
| 2901 | 2918 | glm::quat inverseRotation = glm::inverse(rotation); |
| 2902 | − | |
| 2919 | + | |
| 2903 | 2920 | const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; |
| 2904 | 2921 | const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), |
| 2905 | 2922 | glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; |
| 2906 | − | |
| 2923 | + | |
| 2907 | 2924 | float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); |
| 2908 | 2925 | loadViewFrustum(_myCamera, _viewFrustum); |
| 2909 | − | |
| 2926 | + | |
| 2910 | 2927 | int matrixCount = 1; |
| 2911 | 2928 | //int targetSize = fbo->width(); |
| 2912 | 2929 | int sourceSize = shadowFramebuffer->getWidth(); |
| @@ -2948,12 +2965,12 @@ void Application::updateShadowMap() { · 35 unmodified lines | ||
| 2948 | 2965 | _shadowDistances[i] = -glm::distance(_viewFrustum.getPosition(), center) - radius * RADIUS_SCALE; |
| 2949 | 2966 | } |
| 2950 | 2967 | center = inverseRotation * center; |
| 2951 | − | |
| 2968 | + | |
| 2952 | 2969 | // to reduce texture "shimmer," move in texel increments |
| 2953 | 2970 | float texelSize = (2.0f * radius) / targetSize; |
| 2954 | 2971 | center = glm::vec3(roundf(center.x / texelSize) * texelSize, roundf(center.y / texelSize) * texelSize, |
| 2955 | 2972 | roundf(center.z / texelSize) * texelSize); |
| 2956 | − | |
| 2973 | + | |
| 2957 | 2974 | glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius); |
| 2958 | 2975 | glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); |
| 2959 | 2976 | |
| @@ -2992,7 +3009,7 @@ void Application::updateShadowMap() { · 32 unmodified lines | ||
| 2992 | 3009 | |
| 2993 | 3010 | // store view matrix without translation, which we'll use for precision-sensitive objects |
| 2994 | 3011 | updateUntranslatedViewMatrix(); |
| 2995 | − | |
| 3012 | + | |
| 2996 | 3013 | // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation |
| 2997 | 3014 | // the viewTransofmr object is updatded with the correct values and saved, |
| 2998 | 3015 | // this is what is used for rendering the Entities and avatars |
| @@ -3005,25 +3022,9 @@ void Application::updateShadowMap() { · 6 unmodified lines | ||
| 3005 | 3022 | glEnable(GL_POLYGON_OFFSET_FILL); |
| 3006 | 3023 | glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt |
| 3007 | 3024 | |
| 3008 | − { | |
| 3009 | − PerformanceTimer perfTimer("avatarManager"); | |
| 3010 | − DependencyManager::get<AvatarManager>()->renderAvatars(RenderArgs::SHADOW_RENDER_MODE); | |
| 3011 | − } | |
| 3012 | − | |
| 3013 | 3025 | { |
| 3014 | 3026 | PerformanceTimer perfTimer("entities"); |
| 3015 | − _entities.render(RenderArgs::SHADOW_RENDER_MODE); | |
| 3016 | − } | |
| 3017 | − | |
| 3018 | − // render JS/scriptable overlays | |
| 3019 | − { | |
| 3020 | − PerformanceTimer perfTimer("3dOverlays"); | |
| 3021 | − _overlays.renderWorld(false, RenderArgs::SHADOW_RENDER_MODE); | |
| 3022 | − } | |
| 3023 | − | |
| 3024 | − { | |
| 3025 | − PerformanceTimer perfTimer("3dOverlaysFront"); | |
| 3026 | − _overlays.renderWorld(true, RenderArgs::SHADOW_RENDER_MODE); | |
| 3027 | + _entities.render(renderArgs); | |
| 3027 | 3028 | } |
| 3028 | 3029 | |
| 3029 | 3030 | glDisable(GL_POLYGON_OFFSET_FILL); |
| @@ -3035,9 +3036,9 @@ void Application::updateShadowMap() { · 5 unmodified lines | ||
| 3035 | 3036 | |
| 3036 | 3037 | glMatrixMode(GL_MODELVIEW); |
| 3037 | 3038 | } |
| 3038 | − | |
| 3039 | + | |
| 3039 | 3040 | // fbo->release(); |
| 3040 | − | |
| 3041 | + | |
| 3041 | 3042 | glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); |
| 3042 | 3043 | activeRenderingThread = nullptr; |
| 3043 | 3044 | } |
| @@ -3069,11 +3070,11 @@ bool Application::shouldRenderMesh(float largestDimension, float distanceToCamer · 25 unmodified lines | ||
| 3069 | 3070 | return DependencyManager::get<LODManager>()->shouldRenderMesh(largestDimension, distanceToCamera); |
| 3070 | 3071 | } |
| 3071 | 3072 | |
| 3072 | −float Application::getSizeScale() const { | |
| 3073 | +float Application::getSizeScale() const { | |
| 3073 | 3074 | return DependencyManager::get<LODManager>()->getOctreeSizeScale(); |
| 3074 | 3075 | } |
| 3075 | 3076 | |
| 3076 | −int Application::getBoundaryLevelAdjust() const { | |
| 3077 | +int Application::getBoundaryLevelAdjust() const { | |
| 3077 | 3078 | return DependencyManager::get<LODManager>()->getBoundaryLevelAdjust(); |
| 3078 | 3079 | } |
| 3079 | 3080 | |
| @@ -3094,30 +3095,31 @@ PickRay Application::computePickRay(float x, float y) const { · 14 unmodified lines | ||
| 3094 | 3095 | return result; |
| 3095 | 3096 | } |
| 3096 | 3097 | |
| 3097 | −QImage Application::renderAvatarBillboard() { | |
| 3098 | +QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { | |
| 3098 | 3099 | auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer(); |
| 3099 | 3100 | glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); |
| 3100 | − | |
| 3101 | + | |
| 3101 | 3102 | // clear the alpha channel so the background is transparent |
| 3102 | 3103 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); |
| 3103 | 3104 | glClearColor(0.0, 0.0, 0.0, 0.0); |
| 3104 | 3105 | glClear(GL_COLOR_BUFFER_BIT); |
| 3105 | 3106 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); |
| 3106 | − | |
| 3107 | + | |
| 3107 | 3108 | // the "glow" here causes an alpha of one |
| 3108 | − Glower glower; | |
| 3109 | − | |
| 3109 | + Glower glower(renderArgs); | |
| 3110 | + | |
| 3110 | 3111 | const int BILLBOARD_SIZE = 64; |
| 3111 | − renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, | |
| 3112 | + // TODO: Pass a RenderArgs to renderAvatarBillboard | |
| 3113 | + renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, | |
| 3112 | 3114 | BILLBOARD_SIZE, BILLBOARD_SIZE), |
| 3113 | 3115 | true); |
| 3114 | − | |
| 3116 | + | |
| 3115 | 3117 | QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); |
| 3116 | 3118 | glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); |
| 3117 | 3119 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| 3118 | − | |
| 3120 | + | |
| 3119 | 3121 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
| 3120 | − | |
| 3122 | + | |
| 3121 | 3123 | return image; |
| 3122 | 3124 | } |
| 3123 | 3125 | |
| @@ -3161,7 +3163,143 @@ const ViewFrustum* Application::getDisplayViewFrustum() const { · 37 unmodified lines | ||
| 3161 | 3163 | return &_displayViewFrustum; |
| 3162 | 3164 | } |
| 3163 | 3165 | |
| 3164 | −void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billboard, RenderArgs::RenderSide renderSide) { | |
| 3166 | +// WorldBox Render Data & rendering functions | |
| 3167 | + | |
| 3168 | +class WorldBoxRenderData { | |
| 3169 | +public: | |
| 3170 | + typedef render::Payload<WorldBoxRenderData> Payload; | |
| 3171 | + typedef Payload::DataPointer Pointer; | |
| 3172 | + | |
| 3173 | + int _val = 0; | |
| 3174 | + static render::ItemID _item; // unique WorldBoxRenderData | |
| 3175 | +}; | |
| 3176 | + | |
| 3177 | +render::ItemID WorldBoxRenderData::_item = 0; | |
| 3178 | + | |
| 3179 | +namespace render { | |
| 3180 | + template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); } | |
| 3181 | + template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } | |
| 3182 | + template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { | |
| 3183 | + if (args->_renderMode != RenderArgs::MIRROR_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { | |
| 3184 | + PerformanceTimer perfTimer("worldBox"); | |
| 3185 | + | |
| 3186 | + auto& batch = *args->_batch; | |
| 3187 | + DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch); | |
| 3188 | + renderWorldBox(batch); | |
| 3189 | + } | |
| 3190 | + } | |
| 3191 | +} | |
| 3192 | + | |
| 3193 | +// Background Render Data & rendering functions | |
| 3194 | +class BackgroundRenderData { | |
| 3195 | +public: | |
| 3196 | + typedef render::Payload<BackgroundRenderData> Payload; | |
| 3197 | + typedef Payload::DataPointer Pointer; | |
| 3198 | + | |
| 3199 | + Stars _stars; | |
| 3200 | + Environment* _environment; | |
| 3201 | + | |
| 3202 | + BackgroundRenderData(Environment* environment) : _environment(environment) { | |
| 3203 | + } | |
| 3204 | + | |
| 3205 | + static render::ItemID _item; // unique WorldBoxRenderData | |
| 3206 | +}; | |
| 3207 | + | |
| 3208 | +render::ItemID BackgroundRenderData::_item = 0; | |
| 3209 | + | |
| 3210 | +namespace render { | |
| 3211 | + template <> const ItemKey payloadGetKey(const BackgroundRenderData::Pointer& stuff) { return ItemKey::Builder::background(); } | |
| 3212 | + template <> const Item::Bound payloadGetBound(const BackgroundRenderData::Pointer& stuff) { return Item::Bound(); } | |
| 3213 | + template <> void payloadRender(const BackgroundRenderData::Pointer& background, RenderArgs* args) { | |
| 3214 | + | |
| 3215 | + // Background rendering decision | |
| 3216 | + auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage(); | |
| 3217 | + auto skybox = model::SkyboxPointer(); | |
| 3218 | + if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) { | |
| 3219 | + } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) { | |
| 3220 | + if (/*!selfAvatarOnly &&*/ Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { | |
| 3221 | + PerformanceTimer perfTimer("stars"); | |
| 3222 | + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 3223 | + "Application::payloadRender<BackgroundRenderData>() ... stars..."); | |
| 3224 | + if (!background->_stars.isStarsLoaded()) { | |
| 3225 | + background->_stars.generate(STARFIELD_NUM_STARS, STARFIELD_SEED); | |
| 3226 | + } | |
| 3227 | + // should be the first rendering pass - w/o depth buffer / lighting | |
| 3228 | + | |
| 3229 | + // compute starfield alpha based on distance from atmosphere | |
| 3230 | + float alpha = 1.0f; | |
| 3231 | + bool hasStars = true; | |
| 3232 | + | |
| 3233 | + if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { | |
| 3234 | + // TODO: handle this correctly for zones | |
| 3235 | + const EnvironmentData& closestData = background->_environment->getClosestData(args->_viewFrustum->getPosition()); // was theCamera instead of _viewFrustum | |
| 3236 | + | |
| 3237 | + if (closestData.getHasStars()) { | |
| 3238 | + const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f; | |
| 3239 | + const float DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON = 0.2f; | |
| 3240 | + | |
| 3241 | + glm::vec3 sunDirection = (args->_viewFrustum->getPosition()/*getAvatarPosition()*/ - closestData.getSunLocation()) | |
| 3242 | + / closestData.getAtmosphereOuterRadius(); | |
| 3243 | + float height = glm::distance(args->_viewFrustum->getPosition()/*theCamera.getPosition()*/, closestData.getAtmosphereCenter()); | |
| 3244 | + if (height < closestData.getAtmosphereInnerRadius()) { | |
| 3245 | + // If we're inside the atmosphere, then determine if our keyLight is below the horizon | |
| 3246 | + alpha = 0.0f; | |
| 3247 | + | |
| 3248 | + if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) { | |
| 3249 | + float directionY = glm::clamp(sunDirection.y, | |
| 3250 | + -APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON) | |
| 3251 | + + APPROXIMATE_DISTANCE_FROM_HORIZON; | |
| 3252 | + alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON); | |
| 3253 | + } | |
| 3254 | + | |
| 3255 | + | |
| 3256 | + } else if (height < closestData.getAtmosphereOuterRadius()) { | |
| 3257 | + alpha = (height - closestData.getAtmosphereInnerRadius()) / | |
| 3258 | + (closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius()); | |
| 3259 | + | |
| 3260 | + if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) { | |
| 3261 | + float directionY = glm::clamp(sunDirection.y, | |
| 3262 | + -APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON) | |
| 3263 | + + APPROXIMATE_DISTANCE_FROM_HORIZON; | |
| 3264 | + alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON); | |
| 3265 | + } | |
| 3266 | + } | |
| 3267 | + } else { | |
| 3268 | + hasStars = false; | |
| 3269 | + } | |
| 3270 | + } | |
| 3271 | + | |
| 3272 | + // finally render the starfield | |
| 3273 | + if (hasStars) { | |
| 3274 | + background->_stars.render(args->_viewFrustum->getFieldOfView(), args->_viewFrustum->getAspectRatio(), args->_viewFrustum->getNearClip(), alpha); | |
| 3275 | + } | |
| 3276 | + | |
| 3277 | + // draw the sky dome | |
| 3278 | + if (/*!selfAvatarOnly &&*/ Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { | |
| 3279 | + PerformanceTimer perfTimer("atmosphere"); | |
| 3280 | + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 3281 | + "Application::displaySide() ... atmosphere..."); | |
| 3282 | + background->_environment->renderAtmospheres(*(args->_viewFrustum)); | |
| 3283 | + } | |
| 3284 | + | |
| 3285 | + } | |
| 3286 | + } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) { | |
| 3287 | + PerformanceTimer perfTimer("skybox"); | |
| 3288 | + | |
| 3289 | + skybox = skyStage->getSkybox(); | |
| 3290 | + if (skybox) { | |
| 3291 | + gpu::Batch batch; | |
| 3292 | + model::Skybox::render(batch, *(Application::getInstance()->getDisplayViewFrustum()), *skybox); | |
| 3293 | + | |
| 3294 | + gpu::GLBackend::renderBatch(batch, true); | |
| 3295 | + glUseProgram(0); | |
| 3296 | + } | |
| 3297 | + } | |
| 3298 | + } | |
| 3299 | +} | |
| 3300 | + | |
| 3301 | + | |
| 3302 | +void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) { | |
| 3165 | 3303 | activeRenderingThread = QThread::currentThread(); |
| 3166 | 3304 | PROFILE_RANGE(__FUNCTION__); |
| 3167 | 3305 | PerformanceTimer perfTimer("display"); |
| @@ -3200,13 +3338,13 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 32 unmodified lines | ||
| 3200 | 3338 | if (theCamera.getMode() == CAMERA_MODE_MIRROR) { |
| 3201 | 3339 | viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); |
| 3202 | 3340 | } |
| 3203 | − if (renderSide != RenderArgs::MONO) { | |
| 3341 | + if (renderArgs->_renderSide != RenderArgs::MONO) { | |
| 3204 | 3342 | glm::mat4 invView = glm::inverse(_untranslatedViewMatrix); |
| 3205 | − | |
| 3343 | + | |
| 3206 | 3344 | viewTransform.evalFromRawMatrix(invView); |
| 3207 | 3345 | viewTransform.preTranslate(_viewMatrixTranslation); |
| 3208 | 3346 | } |
| 3209 | − | |
| 3347 | + | |
| 3210 | 3348 | setViewTransform(viewTransform); |
| 3211 | 3349 | |
| 3212 | 3350 | glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z); |
| @@ -3231,86 +3369,17 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 18 unmodified lines | ||
| 3231 | 3369 | glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][2]); |
| 3232 | 3370 | } |
| 3233 | 3371 | |
| 3234 | − // Background rendering decision | |
| 3235 | − auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage(); | |
| 3236 | − auto skybox = model::SkyboxPointer(); | |
| 3237 | − if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) { | |
| 3238 | − } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) { | |
| 3239 | − if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { | |
| 3240 | − PerformanceTimer perfTimer("stars"); | |
| 3241 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 3242 | − "Application::displaySide() ... stars..."); | |
| 3243 | − if (!_stars.isStarsLoaded()) { | |
| 3244 | − _stars.generate(STARFIELD_NUM_STARS, STARFIELD_SEED); | |
| 3245 | − } | |
| 3246 | − // should be the first rendering pass - w/o depth buffer / lighting | |
| 3247 | − | |
| 3248 | − // compute starfield alpha based on distance from atmosphere | |
| 3249 | − float alpha = 1.0f; | |
| 3250 | − bool hasStars = true; | |
| 3251 | − | |
| 3252 | − if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { | |
| 3253 | − // TODO: handle this correctly for zones | |
| 3254 | − const EnvironmentData& closestData = _environment.getClosestData(theCamera.getPosition()); | |
| 3255 | − | |
| 3256 | − if (closestData.getHasStars()) { | |
| 3257 | − const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f; | |
| 3258 | − const float DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON = 0.2f; | |
| 3259 | − | |
| 3260 | − glm::vec3 sunDirection = (getAvatarPosition() - closestData.getSunLocation()) | |
| 3261 | − / closestData.getAtmosphereOuterRadius(); | |
| 3262 | − float height = glm::distance(theCamera.getPosition(), closestData.getAtmosphereCenter()); | |
| 3263 | − if (height < closestData.getAtmosphereInnerRadius()) { | |
| 3264 | − // If we're inside the atmosphere, then determine if our keyLight is below the horizon | |
| 3265 | − alpha = 0.0f; | |
| 3266 | − | |
| 3267 | − if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) { | |
| 3268 | − float directionY = glm::clamp(sunDirection.y, | |
| 3269 | − -APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON) | |
| 3270 | − + APPROXIMATE_DISTANCE_FROM_HORIZON; | |
| 3271 | − alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON); | |
| 3272 | − } | |
| 3273 | − | |
| 3274 | − | |
| 3275 | − } else if (height < closestData.getAtmosphereOuterRadius()) { | |
| 3276 | − alpha = (height - closestData.getAtmosphereInnerRadius()) / | |
| 3277 | − (closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius()); | |
| 3278 | − | |
| 3279 | − if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) { | |
| 3280 | − float directionY = glm::clamp(sunDirection.y, | |
| 3281 | − -APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON) | |
| 3282 | − + APPROXIMATE_DISTANCE_FROM_HORIZON; | |
| 3283 | − alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON); | |
| 3284 | − } | |
| 3285 | − } | |
| 3286 | − } else { | |
| 3287 | − hasStars = false; | |
| 3288 | − } | |
| 3289 | − } | |
| 3372 | + // The pending changes collecting the changes here | |
| 3373 | + render::PendingChanges pendingChanges; | |
| 3290 | 3374 | |
| 3291 | − // finally render the starfield | |
| 3292 | − if (hasStars) { | |
| 3293 | − _stars.render(_displayViewFrustum.getFieldOfView(), _displayViewFrustum.getAspectRatio(), _displayViewFrustum.getNearClip(), alpha); | |
| 3294 | − } | |
| 3295 | − | |
| 3296 | − // draw the sky dome | |
| 3297 | − if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { | |
| 3298 | − PerformanceTimer perfTimer("atmosphere"); | |
| 3299 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 3300 | − "Application::displaySide() ... atmosphere..."); | |
| 3301 | − _environment.renderAtmospheres(theCamera); | |
| 3302 | − } | |
| 3375 | + // Background rendering decision | |
| 3376 | + if (BackgroundRenderData::_item == 0) { | |
| 3377 | + auto backgroundRenderData = BackgroundRenderData::Pointer(new BackgroundRenderData(&_environment)); | |
| 3378 | + auto backgroundRenderPayload = render::PayloadPointer(new BackgroundRenderData::Payload(backgroundRenderData)); | |
| 3379 | + BackgroundRenderData::_item = _main3DScene->allocateID(); | |
| 3380 | + pendingChanges.resetItem(WorldBoxRenderData::_item, backgroundRenderPayload); | |
| 3381 | + } else { | |
| 3303 | 3382 | |
| 3304 | − } | |
| 3305 | − } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) { | |
| 3306 | − skybox = skyStage->getSkybox(); | |
| 3307 | − if (skybox) { | |
| 3308 | − gpu::Batch batch; | |
| 3309 | − model::Skybox::render(batch, _displayViewFrustum, *skybox); | |
| 3310 | − | |
| 3311 | − gpu::GLBackend::renderBatch(batch); | |
| 3312 | − glUseProgram(0); | |
| 3313 | − } | |
| 3314 | 3383 | } |
| 3315 | 3384 | |
| 3316 | 3385 | if (Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) { |
| @@ -3320,13 +3389,10 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 3 unmodified lines | ||
| 3320 | 3389 | glEnable(GL_LIGHTING); |
| 3321 | 3390 | glEnable(GL_DEPTH_TEST); |
| 3322 | 3391 | |
| 3323 | − DependencyManager::get<DeferredLightingEffect>()->prepare(); | |
| 3392 | + // Assuming nothing get's rendered through that | |
| 3324 | 3393 | |
| 3325 | 3394 | if (!selfAvatarOnly) { |
| 3326 | − // draw a red sphere | |
| 3327 | − float originSphereRadius = 0.05f; | |
| 3328 | − DependencyManager::get<GeometryCache>()->renderSphere(originSphereRadius, 15, 15, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); | |
| 3329 | − | |
| 3395 | + | |
| 3330 | 3396 | // render models... |
| 3331 | 3397 | if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) { |
| 3332 | 3398 | PerformanceTimer perfTimer("entities"); |
| @@ -3346,18 +3412,9 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 13 unmodified lines | ||
| 3346 | 3412 | if (theCamera.getMode() == CAMERA_MODE_MIRROR) { |
| 3347 | 3413 | renderMode = RenderArgs::MIRROR_RENDER_MODE; |
| 3348 | 3414 | } |
| 3349 | − _entities.render(renderMode, renderSide, renderDebugFlags); | |
| 3350 | − | |
| 3351 | − if (!Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) { | |
| 3352 | − // Restaure polygon mode | |
| 3353 | − glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | |
| 3354 | − } | |
| 3355 | − } | |
| 3356 | − | |
| 3357 | − // render JS/scriptable overlays | |
| 3358 | − { | |
| 3359 | − PerformanceTimer perfTimer("3dOverlays"); | |
| 3360 | − _overlays.renderWorld(false); | |
| 3415 | + renderArgs->_renderMode = renderMode; | |
| 3416 | + renderArgs->_debugFlags = renderDebugFlags; | |
| 3417 | + _entities.render(renderArgs); | |
| 3361 | 3418 | } |
| 3362 | 3419 | |
| 3363 | 3420 | // render the ambient occlusion effect if enabled |
| @@ -3368,13 +3425,21 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 4 unmodified lines | ||
| 3368 | 3425 | DependencyManager::get<AmbientOcclusionEffect>()->render(); |
| 3369 | 3426 | } |
| 3370 | 3427 | } |
| 3371 | − | |
| 3372 | − bool mirrorMode = (theCamera.getMode() == CAMERA_MODE_MIRROR); | |
| 3373 | − | |
| 3374 | − { | |
| 3375 | − PerformanceTimer perfTimer("avatars"); | |
| 3376 | − DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE, | |
| 3377 | − false, selfAvatarOnly); | |
| 3428 | + | |
| 3429 | + // Make sure the WorldBox is in the scene | |
| 3430 | + if (WorldBoxRenderData::_item == 0) { | |
| 3431 | + auto worldBoxRenderData = WorldBoxRenderData::Pointer(new WorldBoxRenderData()); | |
| 3432 | + auto worldBoxRenderPayload = render::PayloadPointer(new WorldBoxRenderData::Payload(worldBoxRenderData)); | |
| 3433 | + | |
| 3434 | + WorldBoxRenderData::_item = _main3DScene->allocateID(); | |
| 3435 | + | |
| 3436 | + pendingChanges.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); | |
| 3437 | + } else { | |
| 3438 | + | |
| 3439 | + pendingChanges.updateItem<WorldBoxRenderData>(WorldBoxRenderData::_item, | |
| 3440 | + [](WorldBoxRenderData& payload) { | |
| 3441 | + payload._val++; | |
| 3442 | + }); | |
| 3378 | 3443 | } |
| 3379 | 3444 | |
| 3380 | 3445 | if (!billboard) { |
| @@ -3382,19 +3447,55 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 1 unmodified line | ||
| 3382 | 3447 | auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage(); |
| 3383 | 3448 | DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity()); |
| 3384 | 3449 | DependencyManager::get<DeferredLightingEffect>()->setGlobalAtmosphere(skyStage->getAtmosphere()); |
| 3450 | + | |
| 3451 | + auto skybox = model::SkyboxPointer(); | |
| 3452 | + if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) { | |
| 3453 | + skybox = skyStage->getSkybox(); | |
| 3454 | + } | |
| 3385 | 3455 | DependencyManager::get<DeferredLightingEffect>()->setGlobalSkybox(skybox); |
| 3456 | + } | |
| 3386 | 3457 | |
| 3387 | − PROFILE_RANGE("DeferredLighting"); | |
| 3388 | − PerformanceTimer perfTimer("lighting"); | |
| 3389 | − DependencyManager::get<DeferredLightingEffect>()->render(); | |
| 3458 | + { | |
| 3459 | + PerformanceTimer perfTimer("SceneProcessPendingChanges"); | |
| 3460 | + _main3DScene->enqueuePendingChanges(pendingChanges); | |
| 3461 | + | |
| 3462 | + _main3DScene->processPendingChangesQueue(); | |
| 3390 | 3463 | } |
| 3391 | 3464 | |
| 3465 | + // For now every frame pass the renderContext | |
| 3392 | 3466 | { |
| 3393 | − PerformanceTimer perfTimer("avatarsPostLighting"); | |
| 3394 | − DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE, | |
| 3395 | − true, selfAvatarOnly); | |
| 3467 | + PerformanceTimer perfTimer("EngineRun"); | |
| 3468 | + render::RenderContext renderContext; | |
| 3469 | + | |
| 3470 | + auto sceneInterface = DependencyManager::get<SceneScriptingInterface>(); | |
| 3471 | + | |
| 3472 | + renderContext._cullOpaque = sceneInterface->doEngineCullOpaque(); | |
| 3473 | + renderContext._sortOpaque = sceneInterface->doEngineSortOpaque(); | |
| 3474 | + renderContext._renderOpaque = sceneInterface->doEngineRenderOpaque(); | |
| 3475 | + renderContext._cullTransparent = sceneInterface->doEngineCullTransparent(); | |
| 3476 | + renderContext._sortTransparent = sceneInterface->doEngineSortTransparent(); | |
| 3477 | + renderContext._renderTransparent = sceneInterface->doEngineRenderTransparent(); | |
| 3478 | + | |
| 3479 | + renderContext._maxDrawnOpaqueItems = sceneInterface->getEngineMaxDrawnOpaqueItems(); | |
| 3480 | + renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems(); | |
| 3481 | + | |
| 3482 | + renderArgs->_shouldRender = LODManager::shouldRender; | |
| 3483 | + | |
| 3484 | + renderContext.args = renderArgs; | |
| 3485 | + renderArgs->_viewFrustum = getDisplayViewFrustum(); | |
| 3486 | + _renderEngine->setRenderContext(renderContext); | |
| 3487 | + | |
| 3488 | + // Before the deferred pass, let's try to use the render engine | |
| 3489 | + _renderEngine->run(); | |
| 3490 | + | |
| 3491 | + auto engineRC = _renderEngine->getRenderContext(); | |
| 3492 | + sceneInterface->setEngineFeedOpaqueItems(engineRC->_numFeedOpaqueItems); | |
| 3493 | + sceneInterface->setEngineDrawnOpaqueItems(engineRC->_numDrawnOpaqueItems); | |
| 3494 | + | |
| 3495 | + sceneInterface->setEngineFeedTransparentItems(engineRC->_numFeedTransparentItems); | |
| 3496 | + sceneInterface->setEngineDrawnTransparentItems(engineRC->_numDrawnTransparentItems); | |
| 3497 | + | |
| 3396 | 3498 | } |
| 3397 | − | |
| 3398 | 3499 | //Render the sixense lasers |
| 3399 | 3500 | if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { |
| 3400 | 3501 | _myAvatar->renderLaserPointers(); |
| @@ -3402,12 +3503,6 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 1 unmodified line | ||
| 3402 | 3503 | |
| 3403 | 3504 | if (!selfAvatarOnly) { |
| 3404 | 3505 | _nodeBoundsDisplay.draw(); |
| 3405 | − | |
| 3406 | − // Render the world box | |
| 3407 | − if (theCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { | |
| 3408 | − PerformanceTimer perfTimer("worldBox"); | |
| 3409 | − renderWorldBox(); | |
| 3410 | − } | |
| 3411 | 3506 | |
| 3412 | 3507 | // render octree fades if they exist |
| 3413 | 3508 | if (_octreeFades.size() > 0) { |
| @@ -3416,7 +3511,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 2 unmodified lines | ||
| 3416 | 3511 | "Application::displaySide() ... octree fades..."); |
| 3417 | 3512 | _octreeFadesLock.lockForWrite(); |
| 3418 | 3513 | for(std::vector<OctreeFade>::iterator fade = _octreeFades.begin(); fade != _octreeFades.end();) { |
| 3419 | − fade->render(); | |
| 3514 | + fade->render(renderArgs); | |
| 3420 | 3515 | if(fade->isDone()) { |
| 3421 | 3516 | fade = _octreeFades.erase(fade); |
| 3422 | 3517 | } else { |
| @@ -3437,14 +3532,6 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb · 14 unmodified lines | ||
| 3437 | 3532 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); |
| 3438 | 3533 | } |
| 3439 | 3534 | |
| 3440 | − // Render 3D overlays that should be drawn in front | |
| 3441 | − { | |
| 3442 | − PerformanceTimer perfTimer("3dOverlaysFront"); | |
| 3443 | − glClear(GL_DEPTH_BUFFER_BIT); | |
| 3444 | − Glower glower; // Sets alpha to 1.0 | |
| 3445 | − _overlays.renderWorld(true); | |
| 3446 | − } | |
| 3447 | − | |
| 3448 | 3535 | activeRenderingThread = nullptr; |
| 3449 | 3536 | } |
| 3450 | 3537 | |
| @@ -3479,9 +3566,9 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom · 28 unmodified lines | ||
| 3479 | 3566 | _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); |
| 3480 | 3567 | if (OculusManager::isConnected()) { |
| 3481 | 3568 | OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); |
| 3482 | − | |
| 3569 | + | |
| 3483 | 3570 | } else if (TV3DManager::isConnected()) { |
| 3484 | − TV3DManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); | |
| 3571 | + TV3DManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); | |
| 3485 | 3572 | } |
| 3486 | 3573 | } |
| 3487 | 3574 | |
| @@ -3491,8 +3578,8 @@ bool Application::getShadowsEnabled() { · 3 unmodified lines | ||
| 3491 | 3578 | menubar->isOptionChecked(MenuOption::CascadedShadows); |
| 3492 | 3579 | } |
| 3493 | 3580 | |
| 3494 | −bool Application::getCascadeShadowsEnabled() { | |
| 3495 | − return Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows); | |
| 3581 | +bool Application::getCascadeShadowsEnabled() { | |
| 3582 | + return Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows); | |
| 3496 | 3583 | } |
| 3497 | 3584 | |
| 3498 | 3585 | glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { |
| @@ -3521,7 +3608,7 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { · 22 unmodified lines | ||
| 3521 | 3608 | return screenPoint; |
| 3522 | 3609 | } |
| 3523 | 3610 | |
| 3524 | −void Application::renderRearViewMirror(const QRect& region, bool billboard) { | |
| 3611 | +void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { | |
| 3525 | 3612 | // Grab current viewport to reset it at the end |
| 3526 | 3613 | int viewport[4]; |
| 3527 | 3614 | glGetIntegerv(GL_VIEWPORT, viewport); |
| @@ -3539,22 +3626,22 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 11 unmodified lines | ||
| 3539 | 3626 | _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); |
| 3540 | 3627 | |
| 3541 | 3628 | } else { // HEAD zoom level |
| 3542 | − // FIXME note that the positioing of the camera relative to the avatar can suffer limited | |
| 3543 | − // precision as the user's position moves further away from the origin. Thus at | |
| 3544 | − // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways | |
| 3545 | − // wildly as you rotate your avatar because the floating point values are becoming | |
| 3546 | − // larger, squeezing out the available digits of precision you have available at the | |
| 3547 | − // human scale for camera positioning. | |
| 3548 | − | |
| 3549 | − // Previously there was a hack to correct this using the mechanism of repositioning | |
| 3550 | − // the avatar at the origin of the world for the purposes of rendering the mirror, | |
| 3551 | − // but it resulted in failing to render the avatar's head model in the mirror view | |
| 3552 | − // when in first person mode. Presumably this was because of some missed culling logic | |
| 3553 | − // that was not accounted for in the hack. | |
| 3554 | − | |
| 3555 | − // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further | |
| 3629 | + // FIXME note that the positioing of the camera relative to the avatar can suffer limited | |
| 3630 | + // precision as the user's position moves further away from the origin. Thus at | |
| 3631 | + // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways | |
| 3632 | + // wildly as you rotate your avatar because the floating point values are becoming | |
| 3633 | + // larger, squeezing out the available digits of precision you have available at the | |
| 3634 | + // human scale for camera positioning. | |
| 3635 | + | |
| 3636 | + // Previously there was a hack to correct this using the mechanism of repositioning | |
| 3637 | + // the avatar at the origin of the world for the purposes of rendering the mirror, | |
| 3638 | + // but it resulted in failing to render the avatar's head model in the mirror view | |
| 3639 | + // when in first person mode. Presumably this was because of some missed culling logic | |
| 3640 | + // that was not accounted for in the hack. | |
| 3641 | + | |
| 3642 | + // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further | |
| 3556 | 3643 | // investigated in order to adapt the technique while fixing the head rendering issue, |
| 3557 | − // but the complexity of the hack suggests that a better approach | |
| 3644 | + // but the complexity of the hack suggests that a better approach | |
| 3558 | 3645 | _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + |
| 3559 | 3646 | _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); |
| 3560 | 3647 | } |
| @@ -3565,7 +3652,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 4 unmodified lines | ||
| 3565 | 3652 | if (billboard) { |
| 3566 | 3653 | QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize(); |
| 3567 | 3654 | glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); |
| 3568 | − glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); | |
| 3655 | + glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); | |
| 3569 | 3656 | } else { |
| 3570 | 3657 | // if not rendering the billboard, the region is in device independent coordinates; must convert to device |
| 3571 | 3658 | QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize(); |
| @@ -3581,11 +3668,11 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 9 unmodified lines | ||
| 3581 | 3668 | |
| 3582 | 3669 | // render rear mirror view |
| 3583 | 3670 | glPushMatrix(); |
| 3584 | − displaySide(_mirrorCamera, true, billboard); | |
| 3671 | + displaySide(renderArgs, _mirrorCamera, true, billboard); | |
| 3585 | 3672 | glPopMatrix(); |
| 3586 | 3673 | |
| 3587 | 3674 | if (!billboard) { |
| 3588 | − _rearMirrorTools->render(false, _glWidget->mapFromGlobal(QCursor::pos())); | |
| 3675 | + _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); | |
| 3589 | 3676 | } |
| 3590 | 3677 | |
| 3591 | 3678 | // reset Viewport and projection matrix |
| @@ -3606,7 +3693,7 @@ void Application::resetSensors() { · 14 unmodified lines | ||
| 3606 | 3693 | QWindow* mainWindow = _window->windowHandle(); |
| 3607 | 3694 | QPoint windowCenter = mainWindow->geometry().center(); |
| 3608 | 3695 | _glWidget->cursor().setPos(currentScreen, windowCenter); |
| 3609 | − | |
| 3696 | + | |
| 3610 | 3697 | _myAvatar->reset(); |
| 3611 | 3698 | |
| 3612 | 3699 | QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "reset", Qt::QueuedConnection); |
| @@ -3639,11 +3726,11 @@ void Application::updateWindowTitle(){ · 26 unmodified lines | ||
| 3639 | 3726 | QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) "; |
| 3640 | 3727 | QString username = AccountManager::getInstance().getAccountInfo().getUsername(); |
| 3641 | 3728 | QString currentPlaceName = DependencyManager::get<AddressManager>()->getHost(); |
| 3642 | − | |
| 3729 | + | |
| 3643 | 3730 | if (currentPlaceName.isEmpty()) { |
| 3644 | 3731 | currentPlaceName = nodeList->getDomainHandler().getHostname(); |
| 3645 | 3732 | } |
| 3646 | − | |
| 3733 | + | |
| 3647 | 3734 | QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) |
| 3648 | 3735 | + currentPlaceName + connectionStatus + buildVersion; |
| 3649 | 3736 | |
| @@ -3657,7 +3744,6 @@ void Application::updateWindowTitle(){ · 7 unmodified lines | ||
| 3657 | 3744 | void Application::clearDomainOctreeDetails() { |
| 3658 | 3745 | qCDebug(interfaceapp) << "Clearing domain octree details..."; |
| 3659 | 3746 | // reset the environment so that we don't erroneously end up with multiple |
| 3660 | − _environment.resetToDefault(); | |
| 3661 | 3747 | |
| 3662 | 3748 | // reset our node to stats and node to jurisdiction maps... since these must be changing... |
| 3663 | 3749 | _entityServerJurisdictions.lockForWrite(); |
| @@ -3689,7 +3775,7 @@ void Application::domainConnectionDenied(const QString& reason) { · 25 unmodified lines | ||
| 3689 | 3775 | void Application::connectedToDomain(const QString& hostname) { |
| 3690 | 3776 | AccountManager& accountManager = AccountManager::getInstance(); |
| 3691 | 3777 | const QUuid& domainID = DependencyManager::get<NodeList>()->getDomainHandler().getUUID(); |
| 3692 | − | |
| 3778 | + | |
| 3693 | 3779 | if (accountManager.isLoggedIn() && !domainID.isNull()) { |
| 3694 | 3780 | _notifiedPacketVersionMismatchThisDomain = false; |
| 3695 | 3781 | } |
| @@ -3873,7 +3959,7 @@ void Application::saveScripts() { · 177 unmodified lines | ||
| 3873 | 3959 | Settings settings; |
| 3874 | 3960 | settings.beginWriteArray(SETTINGS_KEY); |
| 3875 | 3961 | settings.remove(""); |
| 3876 | − | |
| 3962 | + | |
| 3877 | 3963 | QStringList runningScripts = getRunningScripts(); |
| 3878 | 3964 | int i = 0; |
| 3879 | 3965 | for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) { |
| @@ -3924,7 +4010,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 44 unmodified lines | ||
| 3924 | 4010 | |
| 3925 | 4011 | scriptEngine->registerGlobalObject("Overlays", &_overlays); |
| 3926 | 4012 | qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); |
| 3927 | − qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue, | |
| 4013 | + qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue, | |
| 3928 | 4014 | RayToOverlayIntersectionResultFromScriptValue); |
| 3929 | 4015 | |
| 3930 | 4016 | QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", DependencyManager::get<WindowScriptingInterface>().data()); |
| @@ -3935,7 +4021,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 4 unmodified lines | ||
| 3935 | 4021 | LocationScriptingInterface::locationSetter); |
| 3936 | 4022 | |
| 3937 | 4023 | scriptEngine->registerFunction("WebWindow", WebWindowClass::constructor, 1); |
| 3938 | − | |
| 4024 | + | |
| 3939 | 4025 | scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); |
| 3940 | 4026 | scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); |
| 3941 | 4027 | scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); |
| @@ -3947,7 +4033,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 5 unmodified lines | ||
| 3947 | 4033 | qScriptRegisterMetaType(scriptEngine, DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue); |
| 3948 | 4034 | |
| 3949 | 4035 | scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get<AvatarManager>().data()); |
| 3950 | − | |
| 4036 | + | |
| 3951 | 4037 | scriptEngine->registerGlobalObject("Joysticks", &JoystickScriptingInterface::getInstance()); |
| 3952 | 4038 | qScriptRegisterMetaType(scriptEngine, joystickToScriptValue, joystickFromScriptValue); |
| 3953 | 4039 | |
| @@ -3955,6 +4041,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 1 unmodified line | ||
| 3955 | 4041 | |
| 3956 | 4042 | scriptEngine->registerGlobalObject("LODManager", DependencyManager::get<LODManager>().data()); |
| 3957 | 4043 | |
| 4044 | + scriptEngine->registerGlobalObject("Paths", DependencyManager::get<PathUtils>().data()); | |
| 4045 | + | |
| 3958 | 4046 | QScriptValue hmdInterface = scriptEngine->registerGlobalObject("HMD", &HMDScriptingInterface::getInstance()); |
| 3959 | 4047 | scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition2D", HMDScriptingInterface::getHUDLookAtPosition2D, 0); |
| 3960 | 4048 | scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0); |
| @@ -4002,7 +4090,7 @@ void Application::initializeAcceptedFiles() { · 41 unmodified lines | ||
| 4002 | 4090 | |
| 4003 | 4091 | bool Application::canAcceptURL(const QString& urlString) { |
| 4004 | 4092 | initializeAcceptedFiles(); |
| 4005 | − | |
| 4093 | + | |
| 4006 | 4094 | QUrl url(urlString); |
| 4007 | 4095 | if (urlString.startsWith(HIFI_URL_SCHEME)) { |
| 4008 | 4096 | return true; |
| @@ -4020,7 +4108,7 @@ bool Application::canAcceptURL(const QString& urlString) { · 11 unmodified lines | ||
| 4020 | 4108 | |
| 4021 | 4109 | bool Application::acceptURL(const QString& urlString) { |
| 4022 | 4110 | initializeAcceptedFiles(); |
| 4023 | − | |
| 4111 | + | |
| 4024 | 4112 | if (urlString.startsWith(HIFI_URL_SCHEME)) { |
| 4025 | 4113 | // this is a hifi URL - have the AddressManager handle it |
| 4026 | 4114 | QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString", |
| @@ -4058,19 +4146,19 @@ bool Application::askToSetAvatarUrl(const QString& url) { · 31 unmodified lines | ||
| 4058 | 4146 | msgBox.exec(); |
| 4059 | 4147 | return false; |
| 4060 | 4148 | } |
| 4061 | − | |
| 4149 | + | |
| 4062 | 4150 | // Download the FST file, to attempt to determine its model type |
| 4063 | 4151 | QVariantHash fstMapping = FSTReader::downloadMapping(url); |
| 4064 | − | |
| 4152 | + | |
| 4065 | 4153 | FSTReader::ModelType modelType = FSTReader::predictModelType(fstMapping); |
| 4066 | − | |
| 4154 | + | |
| 4067 | 4155 | QMessageBox msgBox; |
| 4068 | 4156 | msgBox.setIcon(QMessageBox::Question); |
| 4069 | 4157 | msgBox.setWindowTitle("Set Avatar"); |
| 4070 | 4158 | QPushButton* headButton = NULL; |
| 4071 | 4159 | QPushButton* bodyButton = NULL; |
| 4072 | 4160 | QPushButton* bodyAndHeadButton = NULL; |
| 4073 | − | |
| 4161 | + | |
| 4074 | 4162 | QString modelName = fstMapping["name"].toString(); |
| 4075 | 4163 | QString message; |
| 4076 | 4164 | QString typeInfo; |
| @@ -4089,7 +4177,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { · 12 unmodified lines | ||
| 4089 | 4177 | message = QString("Would you like to use '") + modelName + QString("' for your avatar?"); |
| 4090 | 4178 | bodyAndHeadButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); |
| 4091 | 4179 | break; |
| 4092 | − | |
| 4180 | + | |
| 4093 | 4181 | default: |
| 4094 | 4182 | message = QString("Would you like to use '") + modelName + QString("' for some part of your avatar head?"); |
| 4095 | 4183 | headButton = msgBox.addButton(tr("Use for Head"), QMessageBox::ActionRole); |
| @@ -4115,7 +4203,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { · 19 unmodified lines | ||
| 4115 | 4203 | } else { |
| 4116 | 4204 | qCDebug(interfaceapp) << "Declined to use the avatar: " << url; |
| 4117 | 4205 | } |
| 4118 | − | |
| 4206 | + | |
| 4119 | 4207 | return true; |
| 4120 | 4208 | } |
| 4121 | 4209 | |
| @@ -4140,7 +4228,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser · 18 unmodified lines | ||
| 4140 | 4228 | if (isAboutToQuit()) { |
| 4141 | 4229 | return NULL; |
| 4142 | 4230 | } |
| 4143 | − | |
| 4231 | + | |
| 4144 | 4232 | QUrl scriptUrl(scriptFilename); |
| 4145 | 4233 | const QString& scriptURLString = scriptUrl.toString(); |
| 4146 | 4234 | if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor |
| @@ -4151,18 +4239,18 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser · 4 unmodified lines | ||
| 4151 | 4239 | |
| 4152 | 4240 | ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); |
| 4153 | 4241 | scriptEngine->setUserLoaded(isUserLoaded); |
| 4154 | − | |
| 4242 | + | |
| 4155 | 4243 | if (scriptFilename.isNull()) { |
| 4156 | 4244 | // this had better be the script editor (we should de-couple so somebody who thinks they are loading a script |
| 4157 | 4245 | // doesn't just get an empty script engine) |
| 4158 | − | |
| 4246 | + | |
| 4159 | 4247 | // we can complete setup now since there isn't a script we have to load |
| 4160 | 4248 | registerScriptEngineWithApplicationServices(scriptEngine); |
| 4161 | 4249 | } else { |
| 4162 | 4250 | // connect to the appropriate signals of this script engine |
| 4163 | 4251 | connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded); |
| 4164 | 4252 | connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError); |
| 4165 | − | |
| 4253 | + | |
| 4166 | 4254 | // get the script engine object to load the script at the designated script URL |
| 4167 | 4255 | scriptEngine->loadURL(scriptUrl); |
| 4168 | 4256 | } |
| @@ -4177,11 +4265,11 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser · 8 unmodified lines | ||
| 4177 | 4265 | |
| 4178 | 4266 | void Application::handleScriptEngineLoaded(const QString& scriptFilename) { |
| 4179 | 4267 | ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender()); |
| 4180 | − | |
| 4268 | + | |
| 4181 | 4269 | _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine); |
| 4182 | 4270 | _runningScriptsWidget->setRunningScripts(getRunningScripts()); |
| 4183 | 4271 | UserActivityLogger::getInstance().loadedScript(scriptFilename); |
| 4184 | − | |
| 4272 | + | |
| 4185 | 4273 | // register our application services and set it off on its own thread |
| 4186 | 4274 | registerScriptEngineWithApplicationServices(scriptEngine); |
| 4187 | 4275 | } |
| @@ -4291,7 +4379,7 @@ void Application::updateMyAvatarTransform() { · 103 unmodified lines | ||
| 4291 | 4379 | glm::vec3 newOriginOffset = avatarPosition; |
| 4292 | 4380 | int halfExtent = (int)HALF_SIMULATION_EXTENT; |
| 4293 | 4381 | for (int i = 0; i < 3; ++i) { |
| 4294 | − newOriginOffset[i] = (float)(glm::max(halfExtent, | |
| 4382 | + newOriginOffset[i] = (float)(glm::max(halfExtent, | |
| 4295 | 4383 | ((int)(avatarPosition[i] / SIMULATION_OFFSET_QUANTIZATION)) * (int)SIMULATION_OFFSET_QUANTIZATION)); |
| 4296 | 4384 | } |
| 4297 | 4385 | // TODO: Andrew to replace this with method that actually moves existing object positions in PhysicsEngine |
| @@ -4305,23 +4393,23 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject · 7 unmodified lines | ||
| 4305 | 4393 | const QString PER_VOXEL_COST_KEY = "per-voxel-credits"; |
| 4306 | 4394 | const QString PER_METER_CUBED_COST_KEY = "per-meter-cubed-credits"; |
| 4307 | 4395 | const QString VOXEL_WALLET_UUID = "voxel-wallet"; |
| 4308 | − | |
| 4396 | + | |
| 4309 | 4397 | const QJsonObject& voxelObject = domainSettingsObject[VOXEL_SETTINGS_KEY].toObject(); |
| 4310 | − | |
| 4398 | + | |
| 4311 | 4399 | qint64 satoshisPerVoxel = 0; |
| 4312 | 4400 | qint64 satoshisPerMeterCubed = 0; |
| 4313 | 4401 | QUuid voxelWalletUUID; |
| 4314 | − | |
| 4402 | + | |
| 4315 | 4403 | if (!domainSettingsObject.isEmpty()) { |
| 4316 | 4404 | float perVoxelCredits = (float) voxelObject[PER_VOXEL_COST_KEY].toDouble(); |
| 4317 | 4405 | float perMeterCubedCredits = (float) voxelObject[PER_METER_CUBED_COST_KEY].toDouble(); |
| 4318 | − | |
| 4406 | + | |
| 4319 | 4407 | satoshisPerVoxel = (qint64) floorf(perVoxelCredits * SATOSHIS_PER_CREDIT); |
| 4320 | 4408 | satoshisPerMeterCubed = (qint64) floorf(perMeterCubedCredits * SATOSHIS_PER_CREDIT); |
| 4321 | − | |
| 4409 | + | |
| 4322 | 4410 | voxelWalletUUID = QUuid(voxelObject[VOXEL_WALLET_UUID].toString()); |
| 4323 | 4411 | } |
| 4324 | − | |
| 4412 | + | |
| 4325 | 4413 | qCDebug(interfaceapp) << "Octree edits costs are" << satoshisPerVoxel << "per octree cell and" << satoshisPerMeterCubed << "per meter cubed"; |
| 4326 | 4414 | qCDebug(interfaceapp) << "Destination wallet UUID for edit payments is" << voxelWalletUUID; |
| 4327 | 4415 | } |
| @@ -4524,7 +4612,7 @@ bool Application::isVSyncOn() const { · 196 unmodified lines | ||
| 4524 | 4612 | } else { |
| 4525 | 4613 | return true; |
| 4526 | 4614 | } |
| 4527 | − */ | |
| 4615 | + */ | |
| 4528 | 4616 | #endif |
| 4529 | 4617 | return true; |
| 4530 | 4618 | } |
| @@ -4622,14 +4710,14 @@ void Application::notifyPacketVersionMismatch() { · 91 unmodified lines | ||
| 4622 | 4710 | void Application::checkSkeleton() { |
| 4623 | 4711 | if (_myAvatar->getSkeletonModel().isActive() && !_myAvatar->getSkeletonModel().hasSkeleton()) { |
| 4624 | 4712 | qCDebug(interfaceapp) << "MyAvatar model has no skeleton"; |
| 4625 | − | |
| 4713 | + | |
| 4626 | 4714 | QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded..."; |
| 4627 | 4715 | QMessageBox msgBox; |
| 4628 | 4716 | msgBox.setText(message); |
| 4629 | 4717 | msgBox.setStandardButtons(QMessageBox::Ok); |
| 4630 | 4718 | msgBox.setIcon(QMessageBox::Warning); |
| 4631 | 4719 | msgBox.exec(); |
| 4632 | − | |
| 4720 | + | |
| 4633 | 4721 | _myAvatar->useBodyURL(DEFAULT_BODY_MODEL_URL, "Default"); |
| 4634 | 4722 | } else { |
| 4635 | 4723 | _physicsEngine.setCharacterController(_myAvatar->getCharacterController()); |
| @@ -4642,7 +4730,7 @@ void Application::showFriendsWindow() { · 6 unmodified lines | ||
| 4642 | 4730 | const int FRIENDS_WINDOW_WIDTH = 290; |
| 4643 | 4731 | const int FRIENDS_WINDOW_HEIGHT = 500; |
| 4644 | 4732 | if (!_friendsWindow) { |
| 4645 | − _friendsWindow = new WebWindowClass(FRIENDS_WINDOW_TITLE, FRIENDS_WINDOW_URL, FRIENDS_WINDOW_WIDTH, | |
| 4733 | + _friendsWindow = new WebWindowClass(FRIENDS_WINDOW_TITLE, FRIENDS_WINDOW_URL, FRIENDS_WINDOW_WIDTH, | |
| 4646 | 4734 | FRIENDS_WINDOW_HEIGHT, false); |
| 4647 | 4735 | connect(_friendsWindow, &WebWindowClass::closed, this, &Application::friendsWindowClosed); |
| 4648 | 4736 | } |
| @@ -4683,16 +4771,16 @@ QSize Application::getDeviceSize() const { · 34 unmodified lines | ||
| 4683 | 4771 | return _glWidget->getDeviceSize(); |
| 4684 | 4772 | } |
| 4685 | 4773 | |
| 4686 | −int Application::getTrueMouseX() const { | |
| 4687 | − return _glWidget->mapFromGlobal(QCursor::pos()).x(); | |
| 4774 | +int Application::getTrueMouseX() const { | |
| 4775 | + return _glWidget->mapFromGlobal(QCursor::pos()).x(); | |
| 4688 | 4776 | } |
| 4689 | 4777 | |
| 4690 | −int Application::getTrueMouseY() const { | |
| 4691 | − return _glWidget->mapFromGlobal(QCursor::pos()).y(); | |
| 4778 | +int Application::getTrueMouseY() const { | |
| 4779 | + return _glWidget->mapFromGlobal(QCursor::pos()).y(); | |
| 4692 | 4780 | } |
| 4693 | 4781 | |
| 4694 | −bool Application::isThrottleRendering() const { | |
| 4695 | − return _glWidget->isThrottleRendering(); | |
| 4782 | +bool Application::isThrottleRendering() const { | |
| 4783 | + return _glWidget->isThrottleRendering(); | |
| 4696 | 4784 | } |
| 4697 | 4785 | |
| 4698 | 4786 | PickRay Application::computePickRay() const { |