Showing the changes to interface/src/Application.cpp (1 of 150 files). Show all
Unified · Split
| @@ -163,7 +163,6 @@ extern "C" { · 162 unmodified lines | ||
| 163 | 163 | using namespace std; |
| 164 | 164 | |
| 165 | 165 | static QTimer locationUpdateTimer; |
| 166 | −static QTimer balanceUpdateTimer; | |
| 167 | 166 | static QTimer identityPacketTimer; |
| 168 | 167 | static QTimer pingTimer; |
| 169 | 168 | |
| @@ -213,9 +212,7 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi · 43 unmodified lines | ||
| 213 | 212 | |
| 214 | 213 | class DeadlockWatchdogThread : public QThread { |
| 215 | 214 | public: |
| 216 | − static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1; | |
| 217 | 215 | static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1; |
| 218 | − static const unsigned long HEARTBEAT_REPORT_INTERVAL_USECS = 5 * USECS_PER_SECOND; | |
| 219 | 216 | static const unsigned long MAX_HEARTBEAT_AGE_USECS = 30 * USECS_PER_SECOND; |
| 220 | 217 | static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large |
| 221 | 218 | static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples |
| @@ -242,8 +239,6 @@ public: · 20 unmodified lines | ||
| 242 | 239 | *crashTrigger = 0xDEAD10CC; |
| 243 | 240 | } |
| 244 | 241 | |
| 245 | − static void setSuppressStatus(bool suppress) { _suppressStatus = suppress; } | |
| 246 | − | |
| 247 | 242 | void run() override { |
| 248 | 243 | while (!_quit) { |
| 249 | 244 | QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS); |
| @@ -251,7 +246,6 @@ public: · 1 unmodified line | ||
| 251 | 246 | uint64_t lastHeartbeat = _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us |
| 252 | 247 | uint64_t now = usecTimestampNow(); |
| 253 | 248 | auto lastHeartbeatAge = (now > lastHeartbeat) ? now - lastHeartbeat : 0; |
| 254 | − auto sinceLastReport = (now > _lastReport) ? now - _lastReport : 0; | |
| 255 | 249 | auto elapsedMovingAverage = _movingAverage.getAverage(); |
| 256 | 250 | |
| 257 | 251 | if (elapsedMovingAverage > _maxElapsedAverage) { |
| @@ -277,21 +271,10 @@ public: · 19 unmodified lines | ||
| 277 | 271 | if (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT) { |
| 278 | 272 | qDebug() << "DEADLOCK WATCHDOG WARNING:" |
| 279 | 273 | << "lastHeartbeatAge:" << lastHeartbeatAge |
| 280 | − << "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE**" | |
| 274 | + << "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE **" | |
| 281 | 275 | << "maxElapsed:" << _maxElapsed |
| 282 | 276 | << "maxElapsedAverage:" << _maxElapsedAverage |
| 283 | 277 | << "samples:" << _movingAverage.getSamples(); |
| 284 | − _lastReport = now; | |
| 285 | − } | |
| 286 | − | |
| 287 | − if (!_suppressStatus && sinceLastReport > HEARTBEAT_REPORT_INTERVAL_USECS) { | |
| 288 | − qDebug() << "DEADLOCK WATCHDOG STATUS:" | |
| 289 | − << "lastHeartbeatAge:" << lastHeartbeatAge | |
| 290 | − << "elapsedMovingAverage:" << elapsedMovingAverage | |
| 291 | − << "maxElapsed:" << _maxElapsed | |
| 292 | − << "maxElapsedAverage:" << _maxElapsedAverage | |
| 293 | − << "samples:" << _movingAverage.getSamples(); | |
| 294 | − _lastReport = now; | |
| 295 | 278 | } |
| 296 | 279 | |
| 297 | 280 | if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) { |
| @@ -313,9 +296,7 @@ public: · 15 unmodified lines | ||
| 313 | 296 | } |
| 314 | 297 | } |
| 315 | 298 | |
| 316 | − static std::atomic<bool> _suppressStatus; | |
| 317 | 299 | static std::atomic<uint64_t> _heartbeat; |
| 318 | − static std::atomic<uint64_t> _lastReport; | |
| 319 | 300 | static std::atomic<uint64_t> _maxElapsed; |
| 320 | 301 | static std::atomic<int> _maxElapsedAverage; |
| 321 | 302 | static ThreadSafeMovingAverage<int, HEARTBEAT_SAMPLES> _movingAverage; |
| @@ -323,17 +304,11 @@ public: · 1 unmodified line | ||
| 323 | 304 | bool _quit { false }; |
| 324 | 305 | }; |
| 325 | 306 | |
| 326 | −std::atomic<bool> DeadlockWatchdogThread::_suppressStatus; | |
| 327 | 307 | std::atomic<uint64_t> DeadlockWatchdogThread::_heartbeat; |
| 328 | −std::atomic<uint64_t> DeadlockWatchdogThread::_lastReport; | |
| 329 | 308 | std::atomic<uint64_t> DeadlockWatchdogThread::_maxElapsed; |
| 330 | 309 | std::atomic<int> DeadlockWatchdogThread::_maxElapsedAverage; |
| 331 | 310 | ThreadSafeMovingAverage<int, DeadlockWatchdogThread::HEARTBEAT_SAMPLES> DeadlockWatchdogThread::_movingAverage; |
| 332 | 311 | |
| 333 | −void Application::toggleSuppressDeadlockWatchdogStatus(bool checked) { | |
| 334 | − DeadlockWatchdogThread::setSuppressStatus(checked); | |
| 335 | −} | |
| 336 | − | |
| 337 | 312 | #ifdef Q_OS_WIN |
| 338 | 313 | class MyNativeEventFilter : public QAbstractNativeEventFilter { |
| 339 | 314 | public: |
| @@ -512,6 +487,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 172 unmodified lines | ||
| 512 | 487 | _sessionRunTimer(startupTimer), |
| 513 | 488 | _previousSessionCrashed(setupEssentials(argc, argv)), |
| 514 | 489 | _undoStackScriptingInterface(&_undoStack), |
| 490 | + _entitySimulation(new PhysicalEntitySimulation()), | |
| 515 | 491 | _physicsEngine(new PhysicsEngine(Vectors::ZERO)), |
| 516 | 492 | _entityClipboardRenderer(false, this, this), |
| 517 | 493 | _entityClipboard(new EntityTree()), |
| @@ -587,12 +563,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 69 unmodified lines | ||
| 587 | 563 | // put the NodeList and datagram processing on the node thread |
| 588 | 564 | nodeList->moveToThread(nodeThread); |
| 589 | 565 | |
| 590 | − // Model background downloads need to happen on the Datagram Processor Thread. The idle loop will | |
| 591 | − // emit checkBackgroundDownloads to cause the ModelCache to check it's queue for requested background | |
| 592 | − // downloads. | |
| 593 | − auto modelCache = DependencyManager::get<ModelCache>(); | |
| 594 | − connect(this, &Application::checkBackgroundDownloads, modelCache.data(), &ModelCache::checkAsynchronousGets); | |
| 595 | − | |
| 596 | 566 | // put the audio processing on a separate thread |
| 597 | 567 | QThread* audioThread = new QThread(); |
| 598 | 568 | audioThread->setObjectName("Audio Thread"); |
| @@ -679,6 +649,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 80 unmodified lines | ||
| 679 | 649 | connect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain, |
| 680 | 650 | discoverabilityManager.data(), &DiscoverabilityManager::updateLocation); |
| 681 | 651 | |
| 652 | + // send a location update immediately | |
| 653 | + discoverabilityManager->updateLocation(); | |
| 654 | + | |
| 682 | 655 | connect(nodeList.data(), &NodeList::nodeAdded, this, &Application::nodeAdded); |
| 683 | 656 | connect(nodeList.data(), &NodeList::nodeKilled, this, &Application::nodeKilled); |
| 684 | 657 | connect(nodeList.data(), &NodeList::nodeActivated, this, &Application::nodeActivated); |
| @@ -690,13 +663,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 5 unmodified lines | ||
| 690 | 663 | // connect to appropriate slots on AccountManager |
| 691 | 664 | AccountManager& accountManager = AccountManager::getInstance(); |
| 692 | 665 | |
| 693 | − const qint64 BALANCE_UPDATE_INTERVAL_MSECS = 5 * MSECS_PER_SEC; | |
| 694 | − | |
| 695 | − connect(&balanceUpdateTimer, &QTimer::timeout, &accountManager, &AccountManager::updateBalance); | |
| 696 | − balanceUpdateTimer.start(BALANCE_UPDATE_INTERVAL_MSECS); | |
| 697 | − | |
| 698 | − connect(&accountManager, &AccountManager::balanceChanged, this, &Application::updateWindowTitle); | |
| 699 | − | |
| 700 | 666 | auto dialogsManager = DependencyManager::get<DialogsManager>(); |
| 701 | 667 | connect(&accountManager, &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog); |
| 702 | 668 | connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); |
| @@ -1199,7 +1165,6 @@ void Application::cleanupBeforeQuit() { · 496 unmodified lines | ||
| 1199 | 1165 | // first stop all timers directly or by invokeMethod |
| 1200 | 1166 | // depending on what thread they run in |
| 1201 | 1167 | locationUpdateTimer.stop(); |
| 1202 | − balanceUpdateTimer.stop(); | |
| 1203 | 1168 | identityPacketTimer.stop(); |
| 1204 | 1169 | pingTimer.stop(); |
| 1205 | 1170 | QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection); |
| @@ -1513,10 +1478,17 @@ void Application::paintGL() { · 307 unmodified lines | ||
| 1513 | 1478 | |
| 1514 | 1479 | auto lodManager = DependencyManager::get<LODManager>(); |
| 1515 | 1480 | |
| 1516 | − | |
| 1517 | − RenderArgs renderArgs(_gpuContext, getEntities(), getViewFrustum(), lodManager->getOctreeSizeScale(), | |
| 1481 | + { | |
| 1482 | + QMutexLocker viewLocker(&_viewMutex); | |
| 1483 | + _viewFrustum.calculate(); | |
| 1484 | + } | |
| 1485 | + RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(), | |
| 1518 | 1486 | lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, |
| 1519 | 1487 | RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); |
| 1488 | + { | |
| 1489 | + QMutexLocker viewLocker(&_viewMutex); | |
| 1490 | + renderArgs.setViewFrustum(_viewFrustum); | |
| 1491 | + } | |
| 1520 | 1492 | |
| 1521 | 1493 | PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); |
| 1522 | 1494 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| @@ -1683,7 +1655,7 @@ void Application::paintGL() { · 160 unmodified lines | ||
| 1683 | 1655 | renderArgs._context->enableStereo(true); |
| 1684 | 1656 | mat4 eyeOffsets[2]; |
| 1685 | 1657 | mat4 eyeProjections[2]; |
| 1686 | − auto baseProjection = renderArgs._viewFrustum->getProjection(); | |
| 1658 | + auto baseProjection = renderArgs.getViewFrustum().getProjection(); | |
| 1687 | 1659 | auto hmdInterface = DependencyManager::get<HMDScriptingInterface>(); |
| 1688 | 1660 | float IPDScale = hmdInterface->getIPDScale(); |
| 1689 | 1661 | mat4 headPose = displayPlugin->getHeadPose(); |
| @@ -1813,7 +1785,10 @@ void Application::resizeGL() { · 123 unmodified lines | ||
| 1813 | 1785 | _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio, |
| 1814 | 1786 | DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); |
| 1815 | 1787 | // Possible change in aspect ratio |
| 1816 | − loadViewFrustum(_myCamera, _viewFrustum); | |
| 1788 | + { | |
| 1789 | + QMutexLocker viewLocker(&_viewMutex); | |
| 1790 | + loadViewFrustum(_myCamera, _viewFrustum); | |
| 1791 | + } | |
| 1817 | 1792 | |
| 1818 | 1793 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); |
| 1819 | 1794 | auto uiSize = displayPlugin->getRecommendedUiSize(); |
| @@ -2140,6 +2115,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 320 unmodified lines | ||
| 2140 | 2115 | |
| 2141 | 2116 | case Qt::Key_J: |
| 2142 | 2117 | if (isShifted) { |
| 2118 | + QMutexLocker viewLocker(&_viewMutex); | |
| 2143 | 2119 | _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); |
| 2144 | 2120 | } else { |
| 2145 | 2121 | _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); |
| @@ -2149,6 +2125,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 3 unmodified lines | ||
| 2149 | 2125 | |
| 2150 | 2126 | case Qt::Key_M: |
| 2151 | 2127 | if (isShifted) { |
| 2128 | + QMutexLocker viewLocker(&_viewMutex); | |
| 2152 | 2129 | _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); |
| 2153 | 2130 | } else { |
| 2154 | 2131 | _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); |
| @@ -2754,9 +2731,6 @@ void Application::idle(uint64_t now) { · 599 unmodified lines | ||
| 2754 | 2731 | } |
| 2755 | 2732 | |
| 2756 | 2733 | _overlayConductor.update(secondsSinceLastUpdate); |
| 2757 | − | |
| 2758 | − // check for any requested background downloads. | |
| 2759 | − emit checkBackgroundDownloads(); | |
| 2760 | 2734 | } |
| 2761 | 2735 | |
| 2762 | 2736 | void Application::setLowVelocityFilter(bool lowVelocityFilter) { |
| @@ -2997,19 +2971,22 @@ void Application::init() { · 234 unmodified lines | ||
| 2997 | 2971 | DependencyManager::get<NodeList>()->sendDomainServerCheckIn(); |
| 2998 | 2972 | |
| 2999 | 2973 | getEntities()->init(); |
| 3000 | − getEntities()->setViewFrustum(getViewFrustum()); | |
| 2974 | + { | |
| 2975 | + QMutexLocker viewLocker(&_viewMutex); | |
| 2976 | + getEntities()->setViewFrustum(_viewFrustum); | |
| 2977 | + } | |
| 3001 | 2978 | |
| 3002 | 2979 | ObjectMotionState::setShapeManager(&_shapeManager); |
| 3003 | 2980 | _physicsEngine->init(); |
| 3004 | 2981 | |
| 3005 | 2982 | EntityTreePointer tree = getEntities()->getTree(); |
| 3006 | − _entitySimulation.init(tree, _physicsEngine, &_entityEditSender); | |
| 3007 | − tree->setSimulation(&_entitySimulation); | |
| 2983 | + _entitySimulation->init(tree, _physicsEngine, &_entityEditSender); | |
| 2984 | + tree->setSimulation(_entitySimulation); | |
| 3008 | 2985 | |
| 3009 | 2986 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); |
| 3010 | 2987 | |
| 3011 | 2988 | // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts |
| 3012 | − connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity, | |
| 2989 | + connect(_entitySimulation.get(), &EntitySimulation::entityCollisionWithEntity, | |
| 3013 | 2990 | getEntities(), &EntityTreeRenderer::entityCollisionWithEntity); |
| 3014 | 2991 | |
| 3015 | 2992 | // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing |
| @@ -3017,12 +2994,26 @@ void Application::init() { · 1 unmodified line | ||
| 3017 | 2994 | getEntities()->connectSignalsToSlots(entityScriptingInterface.data()); |
| 3018 | 2995 | |
| 3019 | 2996 | _entityClipboardRenderer.init(); |
| 3020 | − _entityClipboardRenderer.setViewFrustum(getViewFrustum()); | |
| 2997 | + { | |
| 2998 | + QMutexLocker viewLocker(&_viewMutex); | |
| 2999 | + _entityClipboardRenderer.setViewFrustum(_viewFrustum); | |
| 3000 | + } | |
| 3021 | 3001 | _entityClipboardRenderer.setTree(_entityClipboard); |
| 3022 | 3002 | |
| 3023 | 3003 | // Make sure any new sounds are loaded as soon as know about them. |
| 3024 | − connect(tree.get(), &EntityTree::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound); | |
| 3025 | − connect(getMyAvatar(), &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound); | |
| 3004 | + connect(tree.get(), &EntityTree::newCollisionSoundURL, this, [this](QUrl newURL, EntityItemID id) { | |
| 3005 | + EntityTreePointer tree = getEntities()->getTree(); | |
| 3006 | + if (auto entity = tree->findEntityByEntityItemID(id)) { | |
| 3007 | + auto sound = DependencyManager::get<SoundCache>()->getSound(newURL); | |
| 3008 | + entity->setCollisionSound(sound); | |
| 3009 | + } | |
| 3010 | + }, Qt::QueuedConnection); | |
| 3011 | + connect(getMyAvatar(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) { | |
| 3012 | + if (auto avatar = getMyAvatar()) { | |
| 3013 | + auto sound = DependencyManager::get<SoundCache>()->getSound(newURL); | |
| 3014 | + avatar->setCollisionSound(sound); | |
| 3015 | + } | |
| 3016 | + }, Qt::QueuedConnection); | |
| 3026 | 3017 | } |
| 3027 | 3018 | |
| 3028 | 3019 | void Application::updateLOD() const { |
| @@ -3220,9 +3211,12 @@ void Application::resetPhysicsReadyInformation() { · 191 unmodified lines | ||
| 3220 | 3211 | |
| 3221 | 3212 | void Application::reloadResourceCaches() { |
| 3222 | 3213 | resetPhysicsReadyInformation(); |
| 3214 | + { | |
| 3215 | + QMutexLocker viewLocker(&_viewMutex); | |
| 3216 | + _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE)); | |
| 3217 | + _viewFrustum.setOrientation(glm::quat()); | |
| 3218 | + } | |
| 3223 | 3219 | // Clear entities out of view frustum |
| 3224 | − _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE)); | |
| 3225 | − _viewFrustum.setOrientation(glm::quat()); | |
| 3226 | 3220 | queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions); |
| 3227 | 3221 | |
| 3228 | 3222 | DependencyManager::get<AssetClient>()->clearCache(); |
| @@ -3412,22 +3406,22 @@ void Application::update(float deltaTime) { · 183 unmodified lines | ||
| 3412 | 3406 | |
| 3413 | 3407 | PerformanceTimer perfTimer("updateStates)"); |
| 3414 | 3408 | static VectorOfMotionStates motionStates; |
| 3415 | − _entitySimulation.getObjectsToRemoveFromPhysics(motionStates); | |
| 3409 | + _entitySimulation->getObjectsToRemoveFromPhysics(motionStates); | |
| 3416 | 3410 | _physicsEngine->removeObjects(motionStates); |
| 3417 | − _entitySimulation.deleteObjectsRemovedFromPhysics(); | |
| 3411 | + _entitySimulation->deleteObjectsRemovedFromPhysics(); | |
| 3418 | 3412 | |
| 3419 | 3413 | getEntities()->getTree()->withReadLock([&] { |
| 3420 | − _entitySimulation.getObjectsToAddToPhysics(motionStates); | |
| 3414 | + _entitySimulation->getObjectsToAddToPhysics(motionStates); | |
| 3421 | 3415 | _physicsEngine->addObjects(motionStates); |
| 3422 | 3416 | |
| 3423 | 3417 | }); |
| 3424 | 3418 | getEntities()->getTree()->withReadLock([&] { |
| 3425 | − _entitySimulation.getObjectsToChange(motionStates); | |
| 3419 | + _entitySimulation->getObjectsToChange(motionStates); | |
| 3426 | 3420 | VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); |
| 3427 | − _entitySimulation.setObjectsToChange(stillNeedChange); | |
| 3421 | + _entitySimulation->setObjectsToChange(stillNeedChange); | |
| 3428 | 3422 | }); |
| 3429 | 3423 | |
| 3430 | − _entitySimulation.applyActionChanges(); | |
| 3424 | + _entitySimulation->applyActionChanges(); | |
| 3431 | 3425 | |
| 3432 | 3426 | avatarManager->getObjectsToRemoveFromPhysics(motionStates); |
| 3433 | 3427 | _physicsEngine->removeObjects(motionStates); |
| @@ -3455,7 +3449,7 @@ void Application::update(float deltaTime) { · 21 unmodified lines | ||
| 3455 | 3449 | getEntities()->getTree()->withWriteLock([&] { |
| 3456 | 3450 | PerformanceTimer perfTimer("handleOutgoingChanges"); |
| 3457 | 3451 | const VectorOfMotionStates& outgoingChanges = _physicsEngine->getOutgoingChanges(); |
| 3458 | − _entitySimulation.handleOutgoingChanges(outgoingChanges); | |
| 3452 | + _entitySimulation->handleOutgoingChanges(outgoingChanges); | |
| 3459 | 3453 | avatarManager->handleOutgoingChanges(outgoingChanges); |
| 3460 | 3454 | }); |
| 3461 | 3455 | |
| @@ -3468,7 +3462,7 @@ void Application::update(float deltaTime) { · 6 unmodified lines | ||
| 3468 | 3462 | PerformanceTimer perfTimer("entities"); |
| 3469 | 3463 | // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk |
| 3470 | 3464 | // deadlock.) |
| 3471 | − _entitySimulation.handleCollisionEvents(collisionEvents); | |
| 3465 | + _entitySimulation->handleCollisionEvents(collisionEvents); | |
| 3472 | 3466 | |
| 3473 | 3467 | // NOTE: the getEntities()->update() call below will wait for lock |
| 3474 | 3468 | // and will simulate entity motion (the EntityTree has been given an EntitySimulation). |
| @@ -3511,7 +3505,7 @@ void Application::update(float deltaTime) { · 36 unmodified lines | ||
| 3511 | 3505 | // actually need to calculate the view frustum planes to send these details |
| 3512 | 3506 | // to the server. |
| 3513 | 3507 | { |
| 3514 | − PerformanceTimer perfTimer("loadViewFrustum"); | |
| 3508 | + QMutexLocker viewLocker(&_viewMutex); | |
| 3515 | 3509 | loadViewFrustum(_myCamera, _viewFrustum); |
| 3516 | 3510 | } |
| 3517 | 3511 | |
| @@ -3520,6 +3514,7 @@ void Application::update(float deltaTime) { · 2 unmodified lines | ||
| 3520 | 3514 | // Update my voxel servers with my current voxel query... |
| 3521 | 3515 | { |
| 3522 | 3516 | PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); |
| 3517 | + QMutexLocker viewLocker(&_viewMutex); | |
| 3523 | 3518 | PerformanceTimer perfTimer("queryOctree"); |
| 3524 | 3519 | quint64 sinceLastQuery = now - _lastQueriedTime; |
| 3525 | 3520 | const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; |
| @@ -3635,14 +3630,16 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 109 unmodified lines | ||
| 3635 | 3630 | //qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView(); |
| 3636 | 3631 | bool wantExtraDebugging = getLogger()->extraDebugging(); |
| 3637 | 3632 | |
| 3638 | − _octreeQuery.setCameraPosition(_viewFrustum.getPosition()); | |
| 3639 | − _octreeQuery.setCameraOrientation(_viewFrustum.getOrientation()); | |
| 3640 | − _octreeQuery.setCameraFov(_viewFrustum.getFieldOfView()); | |
| 3641 | − _octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio()); | |
| 3642 | − _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); | |
| 3643 | − _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); | |
| 3633 | + ViewFrustum viewFrustum; | |
| 3634 | + copyViewFrustum(viewFrustum); | |
| 3635 | + _octreeQuery.setCameraPosition(viewFrustum.getPosition()); | |
| 3636 | + _octreeQuery.setCameraOrientation(viewFrustum.getOrientation()); | |
| 3637 | + _octreeQuery.setCameraFov(viewFrustum.getFieldOfView()); | |
| 3638 | + _octreeQuery.setCameraAspectRatio(viewFrustum.getAspectRatio()); | |
| 3639 | + _octreeQuery.setCameraNearClip(viewFrustum.getNearClip()); | |
| 3640 | + _octreeQuery.setCameraFarClip(viewFrustum.getFarClip()); | |
| 3644 | 3641 | _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); |
| 3645 | − _octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius()); | |
| 3642 | + _octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius()); | |
| 3646 | 3643 | auto lodManager = DependencyManager::get<LODManager>(); |
| 3647 | 3644 | _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); |
| 3648 | 3645 | _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); |
| @@ -3678,7 +3675,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 29 unmodified lines | ||
| 3678 | 3675 | rootDetails.y * TREE_SCALE, |
| 3679 | 3676 | rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE), |
| 3680 | 3677 | rootDetails.s * TREE_SCALE); |
| 3681 | − if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) { | |
| 3678 | + if (viewFrustum.cubeIntersectsKeyhole(serverBounds)) { | |
| 3682 | 3679 | inViewServers++; |
| 3683 | 3680 | } |
| 3684 | 3681 | } |
| @@ -3744,11 +3741,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 59 unmodified lines | ||
| 3744 | 3741 | rootDetails.s * TREE_SCALE); |
| 3745 | 3742 | |
| 3746 | 3743 | |
| 3747 | − inView = _viewFrustum.cubeIntersectsKeyhole(serverBounds); | |
| 3748 | − } else { | |
| 3749 | − if (wantExtraDebugging) { | |
| 3750 | − qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!"; | |
| 3751 | − } | |
| 3744 | + inView = viewFrustum.cubeIntersectsKeyhole(serverBounds); | |
| 3745 | + } else if (wantExtraDebugging) { | |
| 3746 | + qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!"; | |
| 3752 | 3747 | } |
| 3753 | 3748 | } |
| 3754 | 3749 | |
| @@ -3839,6 +3834,7 @@ QRect Application::getDesirableApplicationGeometry() const { · 84 unmodified lines | ||
| 3839 | 3834 | // or the "myCamera". |
| 3840 | 3835 | // |
| 3841 | 3836 | void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { |
| 3837 | + PerformanceTimer perfTimer("loadViewFrustum"); | |
| 3842 | 3838 | PROFILE_RANGE(__FUNCTION__); |
| 3843 | 3839 | // We will use these below, from either the camera or head vectors calculated above |
| 3844 | 3840 | viewFrustum.setProjection(camera.getProjection()); |
| @@ -3867,7 +3863,8 @@ PickRay Application::computePickRay(float x, float y) const { · 22 unmodified lines | ||
| 3867 | 3863 | getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction); |
| 3868 | 3864 | } else { |
| 3869 | 3865 | pickPoint /= getCanvasSize(); |
| 3870 | − getViewFrustum()->computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction); | |
| 3866 | + QMutexLocker viewLocker(&_viewMutex); | |
| 3867 | + _viewFrustum.computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction); | |
| 3871 | 3868 | } |
| 3872 | 3869 | return result; |
| 3873 | 3870 | } |
| @@ -3880,44 +3877,19 @@ glm::vec3 Application::getAvatarPosition() const { · 6 unmodified lines | ||
| 3880 | 3877 | return getMyAvatar()->getPosition(); |
| 3881 | 3878 | } |
| 3882 | 3879 | |
| 3883 | −ViewFrustum* Application::getViewFrustum() { | |
| 3884 | −#ifdef DEBUG | |
| 3885 | − if (QThread::currentThread() == activeRenderingThread) { | |
| 3886 | − // FIXME, figure out a better way to do this | |
| 3887 | − //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; | |
| 3888 | − } | |
| 3889 | −#endif | |
| 3890 | − return &_viewFrustum; | |
| 3891 | −} | |
| 3892 | − | |
| 3893 | −const ViewFrustum* Application::getViewFrustum() const { | |
| 3894 | −#ifdef DEBUG | |
| 3895 | − if (QThread::currentThread() == activeRenderingThread) { | |
| 3896 | − // FIXME, figure out a better way to do this | |
| 3897 | − //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; | |
| 3898 | − } | |
| 3899 | −#endif | |
| 3900 | − return &_viewFrustum; | |
| 3880 | +void Application::copyViewFrustum(ViewFrustum& viewOut) const { | |
| 3881 | + QMutexLocker viewLocker(&_viewMutex); | |
| 3882 | + viewOut = _viewFrustum; | |
| 3901 | 3883 | } |
| 3902 | 3884 | |
| 3903 | −ViewFrustum* Application::getDisplayViewFrustum() { | |
| 3904 | −#ifdef DEBUG | |
| 3905 | − if (QThread::currentThread() != activeRenderingThread) { | |
| 3906 | − // FIXME, figure out a better way to do this | |
| 3907 | − // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; | |
| 3908 | − } | |
| 3909 | −#endif | |
| 3910 | − return &_displayViewFrustum; | |
| 3885 | +void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const { | |
| 3886 | + QMutexLocker viewLocker(&_viewMutex); | |
| 3887 | + viewOut = _displayViewFrustum; | |
| 3911 | 3888 | } |
| 3912 | 3889 | |
| 3913 | −const ViewFrustum* Application::getDisplayViewFrustum() const { | |
| 3914 | −#ifdef DEBUG | |
| 3915 | − if (QThread::currentThread() != activeRenderingThread) { | |
| 3916 | − // FIXME, figure out a better way to do this | |
| 3917 | − // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; | |
| 3918 | − } | |
| 3919 | −#endif | |
| 3920 | − return &_displayViewFrustum; | |
| 3890 | +void Application::copyShadowViewFrustum(ViewFrustum& viewOut) const { | |
| 3891 | + QMutexLocker viewLocker(&_viewMutex); | |
| 3892 | + viewOut = _shadowViewFrustum; | |
| 3921 | 3893 | } |
| 3922 | 3894 | |
| 3923 | 3895 | // WorldBox Render Data & rendering functions |
| @@ -3982,7 +3954,7 @@ namespace render { · 58 unmodified lines | ||
| 3982 | 3954 | auto skybox = skyStage->getSkybox(); |
| 3983 | 3955 | if (skybox) { |
| 3984 | 3956 | PerformanceTimer perfTimer("skybox"); |
| 3985 | − skybox->render(batch, *(args->_viewFrustum)); | |
| 3957 | + skybox->render(batch, args->getViewFrustum()); | |
| 3986 | 3958 | break; |
| 3987 | 3959 | } |
| 3988 | 3960 | } |
| @@ -4023,7 +3995,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 34 unmodified lines | ||
| 4023 | 3995 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); |
| 4024 | 3996 | |
| 4025 | 3997 | // load the view frustum |
| 4026 | − loadViewFrustum(theCamera, _displayViewFrustum); | |
| 3998 | + { | |
| 3999 | + QMutexLocker viewLocker(&_viewMutex); | |
| 4000 | + loadViewFrustum(theCamera, _displayViewFrustum); | |
| 4001 | + } | |
| 4027 | 4002 | |
| 4028 | 4003 | // TODO fix shadows and make them use the GPU library |
| 4029 | 4004 | |
| @@ -4091,7 +4066,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 61 unmodified lines | ||
| 4091 | 4066 | { |
| 4092 | 4067 | PerformanceTimer perfTimer("EngineRun"); |
| 4093 | 4068 | |
| 4094 | − renderArgs->_viewFrustum = getDisplayViewFrustum(); | |
| 4069 | + { | |
| 4070 | + QMutexLocker viewLocker(&_viewMutex); | |
| 4071 | + renderArgs->setViewFrustum(_displayViewFrustum); | |
| 4072 | + } | |
| 4095 | 4073 | _renderEngine->getRenderContext()->args = renderArgs; |
| 4096 | 4074 | |
| 4097 | 4075 | // Before the deferred pass, let's try to use the render engine |
| @@ -5221,10 +5199,10 @@ void Application::updateInputModes() { · 1123 unmodified lines | ||
| 5221 | 5199 | } |
| 5222 | 5200 | |
| 5223 | 5201 | mat4 Application::getEyeProjection(int eye) const { |
| 5202 | + QMutexLocker viewLocker(&_viewMutex); | |
| 5224 | 5203 | if (isHMDMode()) { |
| 5225 | 5204 | return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection()); |
| 5226 | 5205 | } |
| 5227 | − | |
| 5228 | 5206 | return _viewFrustum.getProjection(); |
| 5229 | 5207 | } |
| 5230 | 5208 | |