History

Merge branch 'master' into tony/improved-avatar-debug-draw

Anthony J. Thibault committed 10 years ago

Commit 80a349c2 parents 9821c27 3507434150 files · +2127 −1244Browse files

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

Unified · Split

interface/src/Application.cpp+95−117
@@ -163,7 +163,6 @@ extern "C" { · 162 unmodified lines
163163 using namespace std;
164164
165165 static QTimer locationUpdateTimer;
166−static QTimer balanceUpdateTimer;
167166 static QTimer identityPacketTimer;
168167 static QTimer pingTimer;
169168
@@ -213,9 +212,7 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi · 43 unmodified lines
213212
214213 class DeadlockWatchdogThread : public QThread {
215214 public:
216− static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1;
217215 static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
218− static const unsigned long HEARTBEAT_REPORT_INTERVAL_USECS = 5 * USECS_PER_SECOND;
219216 static const unsigned long MAX_HEARTBEAT_AGE_USECS = 30 * USECS_PER_SECOND;
220217 static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large
221218 static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples
@@ -242,8 +239,6 @@ public: · 20 unmodified lines
242239 *crashTrigger = 0xDEAD10CC;
243240 }
244241
245− static void setSuppressStatus(bool suppress) { _suppressStatus = suppress; }
246−
247242 void run() override {
248243 while (!_quit) {
249244 QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
@@ -251,7 +246,6 @@ public: · 1 unmodified line
251246 uint64_t lastHeartbeat = _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us
252247 uint64_t now = usecTimestampNow();
253248 auto lastHeartbeatAge = (now > lastHeartbeat) ? now - lastHeartbeat : 0;
254− auto sinceLastReport = (now > _lastReport) ? now - _lastReport : 0;
255249 auto elapsedMovingAverage = _movingAverage.getAverage();
256250
257251 if (elapsedMovingAverage > _maxElapsedAverage) {
@@ -277,21 +271,10 @@ public: · 19 unmodified lines
277271 if (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT) {
278272 qDebug() << "DEADLOCK WATCHDOG WARNING:"
279273 << "lastHeartbeatAge:" << lastHeartbeatAge
280− << "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE**"
274+ << "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE **"
281275 << "maxElapsed:" << _maxElapsed
282276 << "maxElapsedAverage:" << _maxElapsedAverage
283277 << "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;
295278 }
296279
297280 if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
@@ -313,9 +296,7 @@ public: · 15 unmodified lines
313296 }
314297 }
315298
316− static std::atomic<bool> _suppressStatus;
317299 static std::atomic<uint64_t> _heartbeat;
318− static std::atomic<uint64_t> _lastReport;
319300 static std::atomic<uint64_t> _maxElapsed;
320301 static std::atomic<int> _maxElapsedAverage;
321302 static ThreadSafeMovingAverage<int, HEARTBEAT_SAMPLES> _movingAverage;
@@ -323,17 +304,11 @@ public: · 1 unmodified line
323304 bool _quit { false };
324305 };
325306
326−std::atomic<bool> DeadlockWatchdogThread::_suppressStatus;
327307 std::atomic<uint64_t> DeadlockWatchdogThread::_heartbeat;
328−std::atomic<uint64_t> DeadlockWatchdogThread::_lastReport;
329308 std::atomic<uint64_t> DeadlockWatchdogThread::_maxElapsed;
330309 std::atomic<int> DeadlockWatchdogThread::_maxElapsedAverage;
331310 ThreadSafeMovingAverage<int, DeadlockWatchdogThread::HEARTBEAT_SAMPLES> DeadlockWatchdogThread::_movingAverage;
332311
333−void Application::toggleSuppressDeadlockWatchdogStatus(bool checked) {
334− DeadlockWatchdogThread::setSuppressStatus(checked);
335−}
336−
337312 #ifdef Q_OS_WIN
338313 class MyNativeEventFilter : public QAbstractNativeEventFilter {
339314 public:
@@ -512,6 +487,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 172 unmodified lines
512487 _sessionRunTimer(startupTimer),
513488 _previousSessionCrashed(setupEssentials(argc, argv)),
514489 _undoStackScriptingInterface(&_undoStack),
490+ _entitySimulation(new PhysicalEntitySimulation()),
515491 _physicsEngine(new PhysicsEngine(Vectors::ZERO)),
516492 _entityClipboardRenderer(false, this, this),
517493 _entityClipboard(new EntityTree()),
@@ -587,12 +563,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 69 unmodified lines
587563 // put the NodeList and datagram processing on the node thread
588564 nodeList->moveToThread(nodeThread);
589565
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−
596566 // put the audio processing on a separate thread
597567 QThread* audioThread = new QThread();
598568 audioThread->setObjectName("Audio Thread");
@@ -679,6 +649,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 80 unmodified lines
679649 connect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain,
680650 discoverabilityManager.data(), &DiscoverabilityManager::updateLocation);
681651
652+ // send a location update immediately
653+ discoverabilityManager->updateLocation();
654+
682655 connect(nodeList.data(), &NodeList::nodeAdded, this, &Application::nodeAdded);
683656 connect(nodeList.data(), &NodeList::nodeKilled, this, &Application::nodeKilled);
684657 connect(nodeList.data(), &NodeList::nodeActivated, this, &Application::nodeActivated);
@@ -690,13 +663,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 5 unmodified lines
690663 // connect to appropriate slots on AccountManager
691664 AccountManager& accountManager = AccountManager::getInstance();
692665
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−
700666 auto dialogsManager = DependencyManager::get<DialogsManager>();
701667 connect(&accountManager, &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog);
702668 connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
@@ -1199,7 +1165,6 @@ void Application::cleanupBeforeQuit() { · 496 unmodified lines
11991165 // first stop all timers directly or by invokeMethod
12001166 // depending on what thread they run in
12011167 locationUpdateTimer.stop();
1202− balanceUpdateTimer.stop();
12031168 identityPacketTimer.stop();
12041169 pingTimer.stop();
12051170 QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
@@ -1513,10 +1478,17 @@ void Application::paintGL() { · 307 unmodified lines
15131478
15141479 auto lodManager = DependencyManager::get<LODManager>();
15151480
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(),
15181486 lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
15191487 RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
1488+ {
1489+ QMutexLocker viewLocker(&_viewMutex);
1490+ renderArgs.setViewFrustum(_viewFrustum);
1491+ }
15201492
15211493 PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
15221494 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
@@ -1683,7 +1655,7 @@ void Application::paintGL() { · 160 unmodified lines
16831655 renderArgs._context->enableStereo(true);
16841656 mat4 eyeOffsets[2];
16851657 mat4 eyeProjections[2];
1686− auto baseProjection = renderArgs._viewFrustum->getProjection();
1658+ auto baseProjection = renderArgs.getViewFrustum().getProjection();
16871659 auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
16881660 float IPDScale = hmdInterface->getIPDScale();
16891661 mat4 headPose = displayPlugin->getHeadPose();
@@ -1813,7 +1785,10 @@ void Application::resizeGL() { · 123 unmodified lines
18131785 _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
18141786 DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
18151787 // Possible change in aspect ratio
1816− loadViewFrustum(_myCamera, _viewFrustum);
1788+ {
1789+ QMutexLocker viewLocker(&_viewMutex);
1790+ loadViewFrustum(_myCamera, _viewFrustum);
1791+ }
18171792
18181793 auto offscreenUi = DependencyManager::get<OffscreenUi>();
18191794 auto uiSize = displayPlugin->getRecommendedUiSize();
@@ -2140,6 +2115,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 320 unmodified lines
21402115
21412116 case Qt::Key_J:
21422117 if (isShifted) {
2118+ QMutexLocker viewLocker(&_viewMutex);
21432119 _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
21442120 } else {
21452121 _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
@@ -2149,6 +2125,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 3 unmodified lines
21492125
21502126 case Qt::Key_M:
21512127 if (isShifted) {
2128+ QMutexLocker viewLocker(&_viewMutex);
21522129 _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
21532130 } else {
21542131 _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
@@ -2754,9 +2731,6 @@ void Application::idle(uint64_t now) { · 599 unmodified lines
27542731 }
27552732
27562733 _overlayConductor.update(secondsSinceLastUpdate);
2757−
2758− // check for any requested background downloads.
2759− emit checkBackgroundDownloads();
27602734 }
27612735
27622736 void Application::setLowVelocityFilter(bool lowVelocityFilter) {
@@ -2997,19 +2971,22 @@ void Application::init() { · 234 unmodified lines
29972971 DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
29982972
29992973 getEntities()->init();
3000− getEntities()->setViewFrustum(getViewFrustum());
2974+ {
2975+ QMutexLocker viewLocker(&_viewMutex);
2976+ getEntities()->setViewFrustum(_viewFrustum);
2977+ }
30012978
30022979 ObjectMotionState::setShapeManager(&_shapeManager);
30032980 _physicsEngine->init();
30042981
30052982 EntityTreePointer tree = getEntities()->getTree();
3006− _entitySimulation.init(tree, _physicsEngine, &_entityEditSender);
3007− tree->setSimulation(&_entitySimulation);
2983+ _entitySimulation->init(tree, _physicsEngine, &_entityEditSender);
2984+ tree->setSimulation(_entitySimulation);
30082985
30092986 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
30102987
30112988 // 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,
30132990 getEntities(), &EntityTreeRenderer::entityCollisionWithEntity);
30142991
30152992 // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
@@ -3017,12 +2994,26 @@ void Application::init() { · 1 unmodified line
30172994 getEntities()->connectSignalsToSlots(entityScriptingInterface.data());
30182995
30192996 _entityClipboardRenderer.init();
3020− _entityClipboardRenderer.setViewFrustum(getViewFrustum());
2997+ {
2998+ QMutexLocker viewLocker(&_viewMutex);
2999+ _entityClipboardRenderer.setViewFrustum(_viewFrustum);
3000+ }
30213001 _entityClipboardRenderer.setTree(_entityClipboard);
30223002
30233003 // 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);
30263017 }
30273018
30283019 void Application::updateLOD() const {
@@ -3220,9 +3211,12 @@ void Application::resetPhysicsReadyInformation() { · 191 unmodified lines
32203211
32213212 void Application::reloadResourceCaches() {
32223213 resetPhysicsReadyInformation();
3214+ {
3215+ QMutexLocker viewLocker(&_viewMutex);
3216+ _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
3217+ _viewFrustum.setOrientation(glm::quat());
3218+ }
32233219 // Clear entities out of view frustum
3224− _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
3225− _viewFrustum.setOrientation(glm::quat());
32263220 queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
32273221
32283222 DependencyManager::get<AssetClient>()->clearCache();
@@ -3412,22 +3406,22 @@ void Application::update(float deltaTime) { · 183 unmodified lines
34123406
34133407 PerformanceTimer perfTimer("updateStates)");
34143408 static VectorOfMotionStates motionStates;
3415− _entitySimulation.getObjectsToRemoveFromPhysics(motionStates);
3409+ _entitySimulation->getObjectsToRemoveFromPhysics(motionStates);
34163410 _physicsEngine->removeObjects(motionStates);
3417− _entitySimulation.deleteObjectsRemovedFromPhysics();
3411+ _entitySimulation->deleteObjectsRemovedFromPhysics();
34183412
34193413 getEntities()->getTree()->withReadLock([&] {
3420− _entitySimulation.getObjectsToAddToPhysics(motionStates);
3414+ _entitySimulation->getObjectsToAddToPhysics(motionStates);
34213415 _physicsEngine->addObjects(motionStates);
34223416
34233417 });
34243418 getEntities()->getTree()->withReadLock([&] {
3425− _entitySimulation.getObjectsToChange(motionStates);
3419+ _entitySimulation->getObjectsToChange(motionStates);
34263420 VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
3427− _entitySimulation.setObjectsToChange(stillNeedChange);
3421+ _entitySimulation->setObjectsToChange(stillNeedChange);
34283422 });
34293423
3430− _entitySimulation.applyActionChanges();
3424+ _entitySimulation->applyActionChanges();
34313425
34323426 avatarManager->getObjectsToRemoveFromPhysics(motionStates);
34333427 _physicsEngine->removeObjects(motionStates);
@@ -3455,7 +3449,7 @@ void Application::update(float deltaTime) { · 21 unmodified lines
34553449 getEntities()->getTree()->withWriteLock([&] {
34563450 PerformanceTimer perfTimer("handleOutgoingChanges");
34573451 const VectorOfMotionStates& outgoingChanges = _physicsEngine->getOutgoingChanges();
3458− _entitySimulation.handleOutgoingChanges(outgoingChanges);
3452+ _entitySimulation->handleOutgoingChanges(outgoingChanges);
34593453 avatarManager->handleOutgoingChanges(outgoingChanges);
34603454 });
34613455
@@ -3468,7 +3462,7 @@ void Application::update(float deltaTime) { · 6 unmodified lines
34683462 PerformanceTimer perfTimer("entities");
34693463 // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
34703464 // deadlock.)
3471− _entitySimulation.handleCollisionEvents(collisionEvents);
3465+ _entitySimulation->handleCollisionEvents(collisionEvents);
34723466
34733467 // NOTE: the getEntities()->update() call below will wait for lock
34743468 // and will simulate entity motion (the EntityTree has been given an EntitySimulation).
@@ -3511,7 +3505,7 @@ void Application::update(float deltaTime) { · 36 unmodified lines
35113505 // actually need to calculate the view frustum planes to send these details
35123506 // to the server.
35133507 {
3514− PerformanceTimer perfTimer("loadViewFrustum");
3508+ QMutexLocker viewLocker(&_viewMutex);
35153509 loadViewFrustum(_myCamera, _viewFrustum);
35163510 }
35173511
@@ -3520,6 +3514,7 @@ void Application::update(float deltaTime) { · 2 unmodified lines
35203514 // Update my voxel servers with my current voxel query...
35213515 {
35223516 PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
3517+ QMutexLocker viewLocker(&_viewMutex);
35233518 PerformanceTimer perfTimer("queryOctree");
35243519 quint64 sinceLastQuery = now - _lastQueriedTime;
35253520 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
36353630 //qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
36363631 bool wantExtraDebugging = getLogger()->extraDebugging();
36373632
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());
36443641 _octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
3645− _octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius());
3642+ _octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius());
36463643 auto lodManager = DependencyManager::get<LODManager>();
36473644 _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
36483645 _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
@@ -3678,7 +3675,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 29 unmodified lines
36783675 rootDetails.y * TREE_SCALE,
36793676 rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
36803677 rootDetails.s * TREE_SCALE);
3681− if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
3678+ if (viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
36823679 inViewServers++;
36833680 }
36843681 }
@@ -3744,11 +3741,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 59 unmodified lines
37443741 rootDetails.s * TREE_SCALE);
37453742
37463743
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!";
37523747 }
37533748 }
37543749
@@ -3839,6 +3834,7 @@ QRect Application::getDesirableApplicationGeometry() const { · 84 unmodified lines
38393834 // or the "myCamera".
38403835 //
38413836 void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
3837+ PerformanceTimer perfTimer("loadViewFrustum");
38423838 PROFILE_RANGE(__FUNCTION__);
38433839 // We will use these below, from either the camera or head vectors calculated above
38443840 viewFrustum.setProjection(camera.getProjection());
@@ -3867,7 +3863,8 @@ PickRay Application::computePickRay(float x, float y) const { · 22 unmodified lines
38673863 getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction);
38683864 } else {
38693865 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);
38713868 }
38723869 return result;
38733870 }
@@ -3880,44 +3877,19 @@ glm::vec3 Application::getAvatarPosition() const { · 6 unmodified lines
38803877 return getMyAvatar()->getPosition();
38813878 }
38823879
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;
39013883 }
39023884
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;
39113888 }
39123889
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;
39213893 }
39223894
39233895 // WorldBox Render Data & rendering functions
@@ -3982,7 +3954,7 @@ namespace render { · 58 unmodified lines
39823954 auto skybox = skyStage->getSkybox();
39833955 if (skybox) {
39843956 PerformanceTimer perfTimer("skybox");
3985− skybox->render(batch, *(args->_viewFrustum));
3957+ skybox->render(batch, args->getViewFrustum());
39863958 break;
39873959 }
39883960 }
@@ -4023,7 +3995,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 34 unmodified lines
40233995 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
40243996
40253997 // load the view frustum
4026− loadViewFrustum(theCamera, _displayViewFrustum);
3998+ {
3999+ QMutexLocker viewLocker(&_viewMutex);
4000+ loadViewFrustum(theCamera, _displayViewFrustum);
4001+ }
40274002
40284003 // TODO fix shadows and make them use the GPU library
40294004
@@ -4091,7 +4066,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 61 unmodified lines
40914066 {
40924067 PerformanceTimer perfTimer("EngineRun");
40934068
4094− renderArgs->_viewFrustum = getDisplayViewFrustum();
4069+ {
4070+ QMutexLocker viewLocker(&_viewMutex);
4071+ renderArgs->setViewFrustum(_displayViewFrustum);
4072+ }
40954073 _renderEngine->getRenderContext()->args = renderArgs;
40964074
40974075 // Before the deferred pass, let's try to use the render engine
@@ -5221,10 +5199,10 @@ void Application::updateInputModes() { · 1123 unmodified lines
52215199 }
52225200
52235201 mat4 Application::getEyeProjection(int eye) const {
5202+ QMutexLocker viewLocker(&_viewMutex);
52245203 if (isHMDMode()) {
52255204 return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection());
52265205 }
5227−
52285206 return _viewFrustum.getProjection();
52295207 }
52305208