History

Merge pull request #7827 from AndrewMeadows/threadsafe-viewfrustum

resurrection of threadsafe ViewFrustum

Brad Hefta-Gaub committed 10 years ago

Commit d7eee982 parents 466b535 db9a4d651 files · +622 −552Browse files

Unified · Split

51 files
  1. assignment-client/src/octree/OctreeQueryNode.cpp +30 −15
  2. assignment-client/src/octree/OctreeQueryNode.h +6 −4
  3. assignment-client/src/octree/OctreeSendThread.cpp +9 −7
  4. interface/src/Application.cpp +66 −61
  5. interface/src/Application.h +5 −6
  6. interface/src/LODManager.cpp +2 −3
  7. interface/src/Stars.cpp +2 −2
  8. interface/src/avatar/Avatar.cpp +21 −18
  9. interface/src/avatar/Avatar.h +1 −1
  10. interface/src/avatar/Head.cpp +0 −3
  11. interface/src/avatar/Head.h +2 −3
  12. interface/src/avatar/MyAvatar.cpp +11 −12
  13. interface/src/avatar/MyAvatar.h +1 −1
  14. interface/src/ui/overlays/Grid3DOverlay.cpp +1 −1
  15. interface/src/ui/overlays/LocalModelsOverlay.cpp +2 −2
  16. libraries/entities-renderer/src/RenderableTextEntityItem.cpp +1 −1
  17. libraries/entities/src/EntityTreeElement.cpp +7 −5
  18. libraries/octree/src/Octree.cpp +28 −32
  19. libraries/octree/src/Octree.h +13 −16
  20. libraries/octree/src/OctreeElement.cpp +4 −3
  21. libraries/octree/src/OctreeElement.h +2 −2
  22. libraries/octree/src/OctreeHeadlessViewer.cpp +1 −3
  23. libraries/octree/src/OctreeHeadlessViewer.h +1 −2
  24. libraries/octree/src/OctreeQuery.cpp +0 −1
  25. libraries/octree/src/OctreeRenderer.cpp +3 −4
  26. libraries/octree/src/OctreeRenderer.h +4 −4
  27. libraries/octree/src/OctreeUtils.cpp +71 −0
  28. libraries/octree/src/OctreeUtils.h +30 −0
  29. libraries/render-utils/src/AbstractViewStateInterface.h +5 −5
  30. libraries/render-utils/src/AmbientOcclusionEffect.cpp +4 −4
  31. libraries/render-utils/src/AntialiasingEffect.cpp +4 −4
  32. libraries/render-utils/src/DebugDeferredBuffer.cpp +6 −6
  33. libraries/render-utils/src/DeferredLightingEffect.cpp +5 −5
  34. libraries/render-utils/src/HitEffect.cpp +5 −5
  35. libraries/render-utils/src/LightStage.cpp +4 −5
  36. libraries/render-utils/src/LightStage.h +1 −1
  37. libraries/render-utils/src/RenderDeferredTask.cpp +14 −14
  38. libraries/render-utils/src/RenderShadowTask.cpp +5 −6
  39. libraries/render/src/render/CullTask.cpp +16 −20
  40. libraries/render/src/render/DrawSceneOctree.cpp +8 −7
  41. libraries/render/src/render/DrawStatus.cpp +3 −3
  42. libraries/render/src/render/DrawTask.cpp +1 −1
  43. libraries/render/src/render/SortTask.cpp +3 −3
  44. libraries/shared/src/CubeProjectedPolygon.cpp +48 −48
  45. libraries/shared/src/CubeProjectedPolygon.h +39 −39
  46. libraries/shared/src/PIDController.cpp +1 −1
  47. libraries/shared/src/Plane.cpp +5 −5
  48. libraries/shared/src/Plane.h +5 −4
  49. libraries/shared/src/RenderArgs.h +22 −10
  50. libraries/shared/src/ViewFrustum.cpp +66 −107
  51. libraries/shared/src/ViewFrustum.h +28 −37
assignment-client/src/octree/OctreeQueryNode.cpp+30−15
@@ -141,6 +141,16 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by · 140 unmodified lines
141141 }
142142 }
143143
144+void OctreeQueryNode::copyCurrentViewFrustum(ViewFrustum& viewOut) const {
145+ QMutexLocker viewLocker(&_viewMutex);
146+ viewOut = _currentViewFrustum;
147+}
148+
149+void OctreeQueryNode::copyLastKnownViewFrustum(ViewFrustum& viewOut) const {
150+ QMutexLocker viewLocker(&_viewMutex);
151+ viewOut = _lastKnownViewFrustum;
152+}
153+
144154 bool OctreeQueryNode::updateCurrentViewFrustum() {
145155 // if shutting down, return immediately
146156 if (_isShuttingDown) {
@@ -171,11 +181,13 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { · 24 unmodified lines
171181 }
172182
173183
174− // if there has been a change, then recalculate
175− if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
176− _currentViewFrustum = newestViewFrustum;
177− _currentViewFrustum.calculate();
178− currentViewFrustumChanged = true;
184+ { // if there has been a change, then recalculate
185+ QMutexLocker viewLocker(&_viewMutex);
186+ if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
187+ _currentViewFrustum = newestViewFrustum;
188+ _currentViewFrustum.calculate();
189+ currentViewFrustumChanged = true;
190+ }
179191 }
180192
181193 // Also check for LOD changes from the client
@@ -219,11 +231,14 @@ void OctreeQueryNode::updateLastKnownViewFrustum() { · 37 unmodified lines
219231 return;
220232 }
221233
222− bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
234+ {
235+ QMutexLocker viewLocker(&_viewMutex);
236+ bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
223237
224− if (frustumChanges) {
225− // save our currentViewFrustum into our lastKnownViewFrustum
226− _lastKnownViewFrustum = _currentViewFrustum;
238+ if (frustumChanges) {
239+ // save our currentViewFrustum into our lastKnownViewFrustum
240+ _lastKnownViewFrustum = _currentViewFrustum;
241+ }
227242 }
228243
229244 // save that we know the view has been sent.
@@ -237,15 +252,13 @@ bool OctreeQueryNode::moveShouldDump() const { · 7 unmodified lines
237252 return false;
238253 }
239254
255+ QMutexLocker viewLocker(&_viewMutex);
240256 glm::vec3 oldPosition = _lastKnownViewFrustum.getPosition();
241257 glm::vec3 newPosition = _currentViewFrustum.getPosition();
242258
243259 // theoretically we could make this slightly larger but relative to avatar scale.
244260 const float MAXIMUM_MOVE_WITHOUT_DUMP = 0.0f;
245− if (glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP) {
246− return true;
247− }
248− return false;
261+ return glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP;
249262 }
250263
251264 void OctreeQueryNode::dumpOutOfView() {
@@ -257,8 +270,10 @@ void OctreeQueryNode::dumpOutOfView() { · 5 unmodified lines
257270 int stillInView = 0;
258271 int outOfView = 0;
259272 OctreeElementBag tempBag;
273+ ViewFrustum viewCopy;
274+ copyCurrentViewFrustum(viewCopy);
260275 while (OctreeElementPointer elementToCheck = elementBag.extract()) {
261− if (elementToCheck->isInView(_currentViewFrustum)) {
276+ if (elementToCheck->isInView(viewCopy)) {
262277 tempBag.insert(elementToCheck);
263278 stillInView++;
264279 } else {
@@ -267,7 +282,7 @@ void OctreeQueryNode::dumpOutOfView() { · 2 unmodified lines
267282 }
268283 if (stillInView > 0) {
269284 while (OctreeElementPointer elementToKeepInBag = tempBag.extract()) {
270− if (elementToKeepInBag->isInView(_currentViewFrustum)) {
285+ if (elementToKeepInBag->isInView(viewCopy)) {
271286 elementBag.insert(elementToKeepInBag);
272287 }
273288 }
assignment-client/src/octree/OctreeQueryNode.h+6−4
@@ -44,7 +44,7 @@ public: · 43 unmodified lines
4444
4545 bool packetIsDuplicate() const;
4646 bool shouldSuppressDuplicatePacket();
47−
47+
4848 unsigned int getAvailable() const { return _octreePacket->bytesAvailableForWrite(); }
4949 int getMaxSearchLevel() const { return _maxSearchLevel; }
5050 void resetMaxSearchLevel() { _maxSearchLevel = 1; }
@@ -56,8 +56,8 @@ public: · 5 unmodified lines
5656 OctreeElementBag elementBag;
5757 OctreeElementExtraEncodeData extraEncodeData;
5858
59− ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; }
60− ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; }
59+ void copyCurrentViewFrustum(ViewFrustum& viewOut) const;
60+ void copyLastKnownViewFrustum(ViewFrustum& viewOut) const;
6161
6262 // These are not classic setters because they are calculating and maintaining state
6363 // which is set asynchronously through the network receive
@@ -114,6 +114,8 @@ private: · 50 unmodified lines
114114
115115 int _maxSearchLevel { 1 };
116116 int _maxLevelReachedInLastSearch { 1 };
117+
118+ mutable QMutex _viewMutex { QMutex::Recursive };
117119 ViewFrustum _currentViewFrustum;
118120 ViewFrustum _lastKnownViewFrustum;
119121 quint64 _lastTimeBagEmpty { 0 };
@@ -139,7 +141,7 @@ private: · 19 unmodified lines
139141 QQueue<OCTREE_PACKET_SEQUENCE> _nackedSequenceNumbers;
140142
141143 quint64 _sceneSendStartTime = 0;
142−
144+
143145 std::array<char, udt::MAX_PACKET_SIZE> _lastOctreePayload;
144146 };
145147
assignment-client/src/octree/OctreeSendThread.cpp+9−7
@@ -338,8 +338,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* · 337 unmodified lines
338338
339339 _packetData.changeSettings(true, targetSize); // FIXME - eventually support only compressed packets
340340
341− const ViewFrustum* lastViewFrustum = viewFrustumChanged ? &nodeData->getLastKnownViewFrustum() : NULL;
342−
343341 // If the current view frustum has changed OR we have nothing to send, then search against
344342 // the current view frustum for things to send.
345343 if (viewFrustumChanged || nodeData->elementBag.isEmpty()) {
@@ -417,7 +415,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* · 71 unmodified lines
417415 quint64 lockWaitEnd = usecTimestampNow();
418416 lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
419417 quint64 encodeStart = usecTimestampNow();
420−
418+
421419 OctreeElementPointer subTree = nodeData->elementBag.extract();
422420 if (!subTree) {
423421 return;
@@ -426,18 +424,22 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* · 2 unmodified lines
426424 float octreeSizeScale = nodeData->getOctreeSizeScale();
427425 int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
428426
429− int boundaryLevelAdjust = boundaryLevelAdjustClient +
427+ int boundaryLevelAdjust = boundaryLevelAdjustClient +
430428 (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
431429
432− EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(),
433− WANT_EXISTS_BITS, DONT_CHOP, viewFrustumChanged, lastViewFrustum,
430+ EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
431+ viewFrustumChanged,
434432 boundaryLevelAdjust, octreeSizeScale,
435433 nodeData->getLastTimeBagEmpty(),
436434 isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
437435 &nodeData->extraEncodeData);
436+ nodeData->copyCurrentViewFrustum(params.viewFrustum);
437+ if (viewFrustumChanged) {
438+ nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
439+ }
438440
439441 // Our trackSend() function is implemented by the server subclass, and will be called back
440− // during the encodeTreeBitstream() as new entities/data elements are sent
442+ // during the encodeTreeBitstream() as new entities/data elements are sent
441443 params.trackSend = [this, node](const QUuid& dataID, quint64 dataEdited) {
442444 _myServer->trackSend(dataID, dataEdited, node->getUUID());
443445 };
interface/src/Application.cpp+66−61
@@ -1481,10 +1481,17 @@ void Application::paintGL() { · 1480 unmodified lines
14811481
14821482 auto lodManager = DependencyManager::get<LODManager>();
14831483
1484−
1485− RenderArgs renderArgs(_gpuContext, getEntities(), getViewFrustum(), lodManager->getOctreeSizeScale(),
1484+ {
1485+ QMutexLocker viewLocker(&_viewMutex);
1486+ _viewFrustum.calculate();
1487+ }
1488+ RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
14861489 lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
14871490 RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
1491+ {
1492+ QMutexLocker viewLocker(&_viewMutex);
1493+ renderArgs.setViewFrustum(_viewFrustum);
1494+ }
14881495
14891496 PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
14901497 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
@@ -1651,7 +1658,7 @@ void Application::paintGL() { · 160 unmodified lines
16511658 renderArgs._context->enableStereo(true);
16521659 mat4 eyeOffsets[2];
16531660 mat4 eyeProjections[2];
1654− auto baseProjection = renderArgs._viewFrustum->getProjection();
1661+ auto baseProjection = renderArgs.getViewFrustum().getProjection();
16551662 auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
16561663 float IPDScale = hmdInterface->getIPDScale();
16571664 mat4 headPose = displayPlugin->getHeadPose();
@@ -1781,7 +1788,10 @@ void Application::resizeGL() { · 123 unmodified lines
17811788 _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
17821789 DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
17831790 // Possible change in aspect ratio
1784− loadViewFrustum(_myCamera, _viewFrustum);
1791+ {
1792+ QMutexLocker viewLocker(&_viewMutex);
1793+ loadViewFrustum(_myCamera, _viewFrustum);
1794+ }
17851795
17861796 auto offscreenUi = DependencyManager::get<OffscreenUi>();
17871797 auto uiSize = displayPlugin->getRecommendedUiSize();
@@ -2108,6 +2118,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 320 unmodified lines
21082118
21092119 case Qt::Key_J:
21102120 if (isShifted) {
2121+ QMutexLocker viewLocker(&_viewMutex);
21112122 _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
21122123 } else {
21132124 _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
@@ -2117,6 +2128,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 3 unmodified lines
21172128
21182129 case Qt::Key_M:
21192130 if (isShifted) {
2131+ QMutexLocker viewLocker(&_viewMutex);
21202132 _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
21212133 } else {
21222134 _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
@@ -2965,7 +2977,10 @@ void Application::init() { · 842 unmodified lines
29652977 DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
29662978
29672979 getEntities()->init();
2968− getEntities()->setViewFrustum(getViewFrustum());
2980+ {
2981+ QMutexLocker viewLocker(&_viewMutex);
2982+ getEntities()->setViewFrustum(_viewFrustum);
2983+ }
29692984
29702985 ObjectMotionState::setShapeManager(&_shapeManager);
29712986 _physicsEngine->init();
@@ -2985,7 +3000,10 @@ void Application::init() { · 13 unmodified lines
29853000 getEntities()->connectSignalsToSlots(entityScriptingInterface.data());
29863001
29873002 _entityClipboardRenderer.init();
2988− _entityClipboardRenderer.setViewFrustum(getViewFrustum());
3003+ {
3004+ QMutexLocker viewLocker(&_viewMutex);
3005+ _entityClipboardRenderer.setViewFrustum(_viewFrustum);
3006+ }
29893007 _entityClipboardRenderer.setTree(_entityClipboard);
29903008
29913009 // Make sure any new sounds are loaded as soon as know about them.
@@ -3199,9 +3217,12 @@ void Application::resetPhysicsReadyInformation() { · 207 unmodified lines
31993217
32003218 void Application::reloadResourceCaches() {
32013219 resetPhysicsReadyInformation();
3220+ {
3221+ QMutexLocker viewLocker(&_viewMutex);
3222+ _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
3223+ _viewFrustum.setOrientation(glm::quat());
3224+ }
32023225 // Clear entities out of view frustum
3203− _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
3204− _viewFrustum.setOrientation(glm::quat());
32053226 queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
32063227
32073228 DependencyManager::get<AssetClient>()->clearCache();
@@ -3490,7 +3511,7 @@ void Application::update(float deltaTime) { · 282 unmodified lines
34903511 // actually need to calculate the view frustum planes to send these details
34913512 // to the server.
34923513 {
3493− PerformanceTimer perfTimer("loadViewFrustum");
3514+ QMutexLocker viewLocker(&_viewMutex);
34943515 loadViewFrustum(_myCamera, _viewFrustum);
34953516 }
34963517
@@ -3499,6 +3520,7 @@ void Application::update(float deltaTime) { · 2 unmodified lines
34993520 // Update my voxel servers with my current voxel query...
35003521 {
35013522 PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
3523+ QMutexLocker viewLocker(&_viewMutex);
35023524 PerformanceTimer perfTimer("queryOctree");
35033525 quint64 sinceLastQuery = now - _lastQueriedTime;
35043526 const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
@@ -3610,14 +3632,16 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 105 unmodified lines
36103632 //qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
36113633 bool wantExtraDebugging = getLogger()->extraDebugging();
36123634
3613− _octreeQuery.setCameraPosition(_viewFrustum.getPosition());
3614− _octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
3615− _octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
3616− _octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio());
3617− _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
3618− _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
3635+ ViewFrustum viewFrustum;
3636+ copyViewFrustum(viewFrustum);
3637+ _octreeQuery.setCameraPosition(viewFrustum.getPosition());
3638+ _octreeQuery.setCameraOrientation(viewFrustum.getOrientation());
3639+ _octreeQuery.setCameraFov(viewFrustum.getFieldOfView());
3640+ _octreeQuery.setCameraAspectRatio(viewFrustum.getAspectRatio());
3641+ _octreeQuery.setCameraNearClip(viewFrustum.getNearClip());
3642+ _octreeQuery.setCameraFarClip(viewFrustum.getFarClip());
36193643 _octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
3620− _octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius());
3644+ _octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius());
36213645 auto lodManager = DependencyManager::get<LODManager>();
36223646 _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
36233647 _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
@@ -3653,7 +3677,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 29 unmodified lines
36533677 rootDetails.y * TREE_SCALE,
36543678 rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
36553679 rootDetails.s * TREE_SCALE);
3656− if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
3680+ if (viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
36573681 inViewServers++;
36583682 }
36593683 }
@@ -3719,11 +3743,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node · 59 unmodified lines
37193743 rootDetails.s * TREE_SCALE);
37203744
37213745
3722− inView = _viewFrustum.cubeIntersectsKeyhole(serverBounds);
3723− } else {
3724− if (wantExtraDebugging) {
3725− qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
3726− }
3746+ inView = viewFrustum.cubeIntersectsKeyhole(serverBounds);
3747+ } else if (wantExtraDebugging) {
3748+ qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
37273749 }
37283750 }
37293751
@@ -3814,6 +3836,7 @@ QRect Application::getDesirableApplicationGeometry() const { · 84 unmodified lines
38143836 // or the "myCamera".
38153837 //
38163838 void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
3839+ PerformanceTimer perfTimer("loadViewFrustum");
38173840 PROFILE_RANGE(__FUNCTION__);
38183841 // We will use these below, from either the camera or head vectors calculated above
38193842 viewFrustum.setProjection(camera.getProjection());
@@ -3842,7 +3865,8 @@ PickRay Application::computePickRay(float x, float y) const { · 22 unmodified lines
38423865 getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction);
38433866 } else {
38443867 pickPoint /= getCanvasSize();
3845− getViewFrustum()->computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction);
3868+ QMutexLocker viewLocker(&_viewMutex);
3869+ _viewFrustum.computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction);
38463870 }
38473871 return result;
38483872 }
@@ -3855,44 +3879,19 @@ glm::vec3 Application::getAvatarPosition() const { · 6 unmodified lines
38553879 return getMyAvatar()->getPosition();
38563880 }
38573881
3858−ViewFrustum* Application::getViewFrustum() {
3859−#ifdef DEBUG
3860− if (QThread::currentThread() == activeRenderingThread) {
3861− // FIXME, figure out a better way to do this
3862− //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
3863− }
3864−#endif
3865− return &_viewFrustum;
3866−}
3867−
3868−const ViewFrustum* Application::getViewFrustum() const {
3869−#ifdef DEBUG
3870− if (QThread::currentThread() == activeRenderingThread) {
3871− // FIXME, figure out a better way to do this
3872− //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
3873− }
3874−#endif
3875− return &_viewFrustum;
3882+void Application::copyViewFrustum(ViewFrustum& viewOut) const {
3883+ QMutexLocker viewLocker(&_viewMutex);
3884+ viewOut = _viewFrustum;
38763885 }
38773886
3878−ViewFrustum* Application::getDisplayViewFrustum() {
3879−#ifdef DEBUG
3880− if (QThread::currentThread() != activeRenderingThread) {
3881− // FIXME, figure out a better way to do this
3882− // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
3883− }
3884−#endif
3885− return &_displayViewFrustum;
3887+void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const {
3888+ QMutexLocker viewLocker(&_viewMutex);
3889+ viewOut = _displayViewFrustum;
38863890 }
38873891
3888−const ViewFrustum* Application::getDisplayViewFrustum() const {
3889−#ifdef DEBUG
3890− if (QThread::currentThread() != activeRenderingThread) {
3891− // FIXME, figure out a better way to do this
3892− // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
3893− }
3894−#endif
3895− return &_displayViewFrustum;
3892+void Application::copyShadowViewFrustum(ViewFrustum& viewOut) const {
3893+ QMutexLocker viewLocker(&_viewMutex);
3894+ viewOut = _shadowViewFrustum;
38963895 }
38973896
38983897 // WorldBox Render Data & rendering functions
@@ -3957,7 +3956,7 @@ namespace render { · 58 unmodified lines
39573956 auto skybox = skyStage->getSkybox();
39583957 if (skybox) {
39593958 PerformanceTimer perfTimer("skybox");
3960− skybox->render(batch, *(args->_viewFrustum));
3959+ skybox->render(batch, args->getViewFrustum());
39613960 break;
39623961 }
39633962 }
@@ -4001,7 +4000,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 37 unmodified lines
40014000 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
40024001
40034002 // load the view frustum
4004− loadViewFrustum(theCamera, _displayViewFrustum);
4003+ {
4004+ QMutexLocker viewLocker(&_viewMutex);
4005+ loadViewFrustum(theCamera, _displayViewFrustum);
4006+ }
40054007
40064008 // TODO fix shadows and make them use the GPU library
40074009
@@ -4069,7 +4071,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 61 unmodified lines
40694071 {
40704072 PerformanceTimer perfTimer("EngineRun");
40714073
4072− renderArgs->_viewFrustum = getDisplayViewFrustum();
4074+ {
4075+ QMutexLocker viewLocker(&_viewMutex);
4076+ renderArgs->setViewFrustum(_displayViewFrustum);
4077+ }
40734078 _renderEngine->getRenderContext()->args = renderArgs;
40744079
40754080 // Before the deferred pass, let's try to use the render engine
@@ -5199,10 +5204,10 @@ void Application::updateInputModes() { · 1123 unmodified lines
51995204 }
52005205
52015206 mat4 Application::getEyeProjection(int eye) const {
5207+ QMutexLocker viewLocker(&_viewMutex);
52025208 if (isHMDMode()) {
52035209 return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection());
52045210 }
5205−
52065211 return _viewFrustum.getProjection();
52075212 }
52085213
interface/src/Application.h+5−6
@@ -128,14 +128,12 @@ public: · 127 unmodified lines
128128 Camera* getCamera() { return &_myCamera; }
129129 const Camera* getCamera() const { return &_myCamera; }
130130 // Represents the current view frustum of the avatar.
131− ViewFrustum* getViewFrustum();
132− const ViewFrustum* getViewFrustum() const;
131+ void copyViewFrustum(ViewFrustum& viewOut) const;
133132 // Represents the view frustum of the current rendering pass,
134133 // which might be different from the viewFrustum, i.e. shadowmap
135134 // passes, mirror window passes, etc
136− ViewFrustum* getDisplayViewFrustum();
137− const ViewFrustum* getDisplayViewFrustum() const;
138− ViewFrustum* getShadowViewFrustum() override { return &_shadowViewFrustum; }
135+ void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
136+ void copyShadowViewFrustum(ViewFrustum& viewOut) const override;
139137 const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
140138 EntityTreeRenderer* getEntities() const { return DependencyManager::get<EntityTreeRenderer>().data(); }
141139 QUndoStack* getUndoStack() { return &_undoStack; }
@@ -169,7 +167,7 @@ public: · 27 unmodified lines
169167 virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
170168 virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override;
171169
172− virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); }
170+ virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override { copyDisplayViewFrustum(viewOut); }
173171 virtual QThread* getMainThread() override { return thread(); }
174172 virtual PickRay computePickRay(float x, float y) const override;
175173 virtual glm::vec3 getAvatarPosition() const override;
@@ -413,6 +411,7 @@ private: · 237 unmodified lines
413411 EntityTreeRenderer _entityClipboardRenderer;
414412 EntityTreePointer _entityClipboard;
415413
414+ mutable QMutex _viewMutex { QMutex::Recursive };
416415 ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
417416 ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
418417 ViewFrustum _displayViewFrustum;
interface/src/LODManager.cpp+2−3
@@ -10,6 +10,7 @@ · 9 unmodified lines
1010 //
1111
1212 #include <SettingHandle.h>
13+#include <OctreeUtils.h>
1314 #include <Util.h>
1415
1516 #include "Application.h"
@@ -216,7 +217,7 @@ QString LODManager::getLODFeedbackText() { · 200 unmodified lines
216217 bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
217218 // FIXME - eventually we want to use the render accuracy as an indicator for the level of detail
218219 // to use in rendering.
219− float renderAccuracy = args->_viewFrustum->calculateRenderAccuracy(bounds, args->_sizeScale, args->_boundaryLevelAdjust);
220+ float renderAccuracy = calculateRenderAccuracy(args->getViewFrustum().getPosition(), bounds, args->_sizeScale, args->_boundaryLevelAdjust);
220221 return (renderAccuracy > 0.0f);
221222 };
222223
@@ -228,7 +229,6 @@ void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { · 5 unmodified lines
228229 _boundaryLevelAdjust = boundaryLevelAdjust;
229230 }
230231
231−
232232 void LODManager::loadSettings() {
233233 setDesktopLODDecreaseFPS(desktopLODDecreaseFPS.get());
234234 setHMDLODDecreaseFPS(hmdLODDecreaseFPS.get());
@@ -239,4 +239,3 @@ void LODManager::saveSettings() { · 4 unmodified lines
239239 hmdLODDecreaseFPS.set(getHMDLODDecreaseFPS());
240240 }
241241
242−
interface/src/Stars.cpp+2−2
@@ -194,8 +194,8 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { · 193 unmodified lines
194194
195195 gpu::Batch& batch = *renderArgs->_batch;
196196 batch.setViewTransform(Transform());
197− batch.setProjectionTransform(renderArgs->_viewFrustum->getProjection());
198− batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->_viewFrustum->getOrientation()) *
197+ batch.setProjectionTransform(renderArgs->getViewFrustum().getProjection());
198+ batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->getViewFrustum().getOrientation()) *
199199 quat(vec3(TILT, 0, 0))));
200200 batch.setResourceTexture(0, textureCache->getWhiteTexture());
201201
interface/src/avatar/Avatar.cpp+21−18
@@ -25,6 +25,7 @@ · 24 unmodified lines
2525 #include <LODManager.h>
2626 #include <NodeList.h>
2727 #include <NumericalConstants.h>
28+#include <OctreeUtils.h>
2829 #include <udt/PacketHeaders.h>
2930 #include <PerfStat.h>
3031 #include <SharedUtil.h>
@@ -171,7 +172,10 @@ void Avatar::simulate(float deltaTime) { · 140 unmodified lines
171172 // update the shouldAnimate flag to match whether or not we will render the avatar.
172173 const float MINIMUM_VISIBILITY_FOR_ON = 0.4f;
173174 const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
174− float visibility = qApp->getViewFrustum()->calculateRenderAccuracy(getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
175+ ViewFrustum viewFrustum;
176+ qApp->copyViewFrustum(viewFrustum);
177+ float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
178+ getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
175179 if (!_shouldAnimate) {
176180 if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
177181 _shouldAnimate = true;
@@ -184,8 +188,9 @@ void Avatar::simulate(float deltaTime) { · 6 unmodified lines
184188
185189 // simple frustum check
186190 float boundingRadius = getBoundingRadius();
187− bool avatarPositionInView = qApp->getDisplayViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius);
188− bool avatarMeshInView = qApp->getDisplayViewFrustum()->boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
191+ qApp->copyDisplayViewFrustum(viewFrustum);
192+ bool avatarPositionInView = viewFrustum.sphereIntersectsFrustum(getPosition(), boundingRadius);
193+ bool avatarMeshInView = viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
189194
190195 if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) {
191196 {
@@ -381,17 +386,16 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { · 189 unmodified lines
381386 }
382387 }
383388
384− // simple frustum check
385− float boundingRadius = getBoundingRadius();
386− ViewFrustum* frustum = nullptr;
387− if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
388− frustum = qApp->getShadowViewFrustum();
389− } else {
390− frustum = qApp->getDisplayViewFrustum();
391− }
392−
393− if (!frustum->sphereIntersectsFrustum(getPosition(), boundingRadius)) {
394− return;
389+ { // simple frustum check
390+ ViewFrustum frustum;
391+ if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
392+ qApp->copyShadowViewFrustum(frustum);
393+ } else {
394+ qApp->copyDisplayViewFrustum(frustum);
395+ }
396+ if (!frustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())) {
397+ return;
398+ }
395399 }
396400
397401 glm::vec3 toTarget = cameraPosition - getPosition();
@@ -413,7 +417,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { · 15 unmodified lines
413417 : GLOW_FROM_AVERAGE_LOUDNESS;
414418
415419 // render body
416− renderBody(renderArgs, frustum, glowLevel);
420+ renderBody(renderArgs, glowLevel);
417421
418422 if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) {
419423 // add local lights
@@ -502,9 +506,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { · 82 unmodified lines
502506
503507 auto cameraMode = qApp->getCamera()->getMode();
504508 if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
505− auto& frustum = *renderArgs->_viewFrustum;
509+ auto& frustum = renderArgs->getViewFrustum();
506510 auto textPosition = getDisplayNamePosition();
507−
508511 if (frustum.pointIntersectsFrustum(textPosition)) {
509512 renderDisplayName(batch, frustum, textPosition);
510513 }
@@ -553,7 +556,7 @@ void Avatar::fixupModelsInScene() { · 42 unmodified lines
553556 scene->enqueuePendingChanges(pendingChanges);
554557 }
555558
556−void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
559+void Avatar::renderBody(RenderArgs* renderArgs, float glowLevel) {
557560 fixupModelsInScene();
558561 getHead()->renderLookAts(renderArgs);
559562 }
interface/src/avatar/Avatar.h+1−1
@@ -232,7 +232,7 @@ protected: · 231 unmodified lines
232232
233233 Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const;
234234 void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const;
235− virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f);
235+ virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f);
236236 virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
237237 virtual void fixupModelsInScene();
238238
interface/src/avatar/Head.cpp+0−3
@@ -316,9 +316,6 @@ void Head::relaxLean(float deltaTime) { · 315 unmodified lines
316316 _deltaLeanForward *= relaxationFactor;
317317 }
318318
319−void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum) {
320−}
321−
322319 void Head::renderLookAts(RenderArgs* renderArgs) {
323320 renderLookAts(renderArgs, _leftEyePosition, _rightEyePosition);
324321 }
interface/src/avatar/Head.h+2−3
@@ -28,11 +28,10 @@ class Avatar; · 27 unmodified lines
2828 class Head : public HeadData {
2929 public:
3030 explicit Head(Avatar* owningAvatar);
31−
31+
3232 void init();
3333 void reset();
3434 void simulate(float deltaTime, bool isMine, bool billboard = false);
35− void render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum);
3635 void setScale(float scale);
3736 void setPosition(glm::vec3 position) { _position = position; }
3837 void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
@@ -44,7 +43,7 @@ public: · 5 unmodified lines
4443
4544 /// \return orientationBase+Delta
4645 glm::quat getFinalOrientationInLocalFrame() const;
47−
46+
4847 /// \return orientationBody * (orientationBase+Delta)
4948 glm::quat getFinalOrientationInWorldFrame() const;
5049
interface/src/avatar/MyAvatar.cpp+11−12
@@ -545,7 +545,9 @@ void MyAvatar::updateFromTrackers(float deltaTime) { · 544 unmodified lines
545545 head->setDeltaYaw(estimatedRotation.y);
546546 head->setDeltaRoll(estimatedRotation.z);
547547 } else {
548− float magnifyFieldOfView = qApp->getViewFrustum()->getFieldOfView() / _realWorldFieldOfView.get();
548+ ViewFrustum viewFrustum;
549+ qApp->copyViewFrustum(viewFrustum);
550+ float magnifyFieldOfView = viewFrustum.getFieldOfView() / _realWorldFieldOfView.get();
549551 head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView);
550552 head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView);
551553 head->setDeltaRoll(estimatedRotation.z);
@@ -928,15 +930,17 @@ void MyAvatar::updateLookAtTargetAvatar() { · 376 unmodified lines
928930 // (We will be adding that offset to the camera position, after making some other adjustments.)
929931 glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition();
930932
933+ ViewFrustum viewFrustum;
934+ qApp->copyViewFrustum(viewFrustum);
935+
931936 // scale gazeOffset by IPD, if wearing an HMD.
932937 if (qApp->isHMDMode()) {
933938 glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left);
934939 glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right);
935940 glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]);
936941 glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]);
937− auto humanSystem = qApp->getViewFrustum();
938− glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal);
939− glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal);
942+ glm::vec3 humanLeftEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * leftEyeHeadLocal);
943+ glm::vec3 humanRightEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * rightEyeHeadLocal);
940944
941945 auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
942946 float ipdScale = hmdInterface->getIPDScale();
@@ -950,7 +954,7 @@ void MyAvatar::updateLookAtTargetAvatar() { · 7 unmodified lines
950954 }
951955
952956 // And now we can finally add that offset to the camera.
953− glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset;
957+ glm::vec3 corrected = viewFrustum.getPosition() + gazeOffset;
954958
955959 avatar->getHead()->setCorrectedLookAtPosition(corrected);
956960
@@ -1266,7 +1270,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, · 309 unmodified lines
12661270 Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
12671271 }
12681272
1269−void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
1273+void MyAvatar::renderBody(RenderArgs* renderArgs, float glowLevel) {
12701274
12711275 if (!_skeletonModel->isRenderable()) {
12721276 return; // wait until all models are loaded
@@ -1274,11 +1278,6 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl · 1 unmodified line
12741278
12751279 fixupModelsInScene();
12761280
1277− // Render head so long as the camera isn't inside it
1278− if (shouldRenderHead(renderArgs)) {
1279− getHead()->render(renderArgs, 1.0f, renderFrustum);
1280− }
1281−
12821281 // This is drawing the lookat vectors from our avatar to wherever we're looking.
12831282 if (qApp->isHMDMode()) {
12841283 glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
@@ -1359,7 +1358,6 @@ void MyAvatar::destroyAnimGraph() { · 74 unmodified lines
13591358 void MyAvatar::preRender(RenderArgs* renderArgs) {
13601359
13611360 render::ScenePointer scene = qApp->getMain3DScene();
1362− const bool shouldDrawHead = shouldRenderHead(renderArgs);
13631361
13641362 if (_skeletonModel->initWhenReady(scene)) {
13651363 initHeadBones();
@@ -1411,6 +1409,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { · 45 unmodified lines
14111409 DebugDraw::getInstance().updateMyAvatarPos(getPosition());
14121410 DebugDraw::getInstance().updateMyAvatarRot(getOrientation());
14131411
1412+ const bool shouldDrawHead = shouldRenderHead(renderArgs);
14141413 if (shouldDrawHead != _prevShouldDrawHead) {
14151414 _skeletonModel->setCauterizeBones(!shouldDrawHead);
14161415 }
interface/src/avatar/MyAvatar.h+1−1
@@ -310,7 +310,7 @@ private: · 309 unmodified lines
310310 void simulate(float deltaTime);
311311 void updateFromTrackers(float deltaTime);
312312 virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
313− virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f) override;
313+ virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f) override;
314314 virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
315315 void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); }
316316 bool getShouldRenderLocally() const { return _shouldRender; }
interface/src/ui/overlays/Grid3DOverlay.cpp+1−1
@@ -65,7 +65,7 @@ void Grid3DOverlay::render(RenderArgs* args) { · 64 unmodified lines
6565 // Get the camera position rounded to the nearest major grid line
6666 // This grid is for UI and should lie on worldlines
6767 auto cameraPosition =
68− (float)_majorGridEvery * glm::round(args->_viewFrustum->getPosition() / (float)_majorGridEvery);
68+ (float)_majorGridEvery * glm::round(args->getViewFrustum().getPosition() / (float)_majorGridEvery);
6969
7070 position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z);
7171 }
interface/src/ui/overlays/LocalModelsOverlay.cpp+2−2
@@ -37,10 +37,10 @@ void LocalModelsOverlay::render(RenderArgs* args) { · 36 unmodified lines
3737 auto batch = args ->_batch;
3838
3939 Transform transform = Transform();
40− transform.setTranslation(args->_viewFrustum->getPosition() + getPosition());
40+ transform.setTranslation(args->getViewFrustum().getPosition() + getPosition());
4141 batch->setViewTransform(transform);
4242 _entityTreeRenderer->render(args);
43− transform.setTranslation(args->_viewFrustum->getPosition());
43+ transform.setTranslation(args->getViewFrustum().getPosition());
4444 batch->setViewTransform(transform);
4545 }
4646 }
libraries/entities-renderer/src/RenderableTextEntityItem.cpp+1−1
@@ -51,7 +51,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) { · 50 unmodified lines
5151 }
5252 if (getFaceCamera()) {
5353 //rotate about vertical to face the camera
54− glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition();
54+ glm::vec3 dPosition = args->getViewFrustum().getPosition() - getPosition();
5555 // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
5656 float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
5757 glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
libraries/entities/src/EntityTreeElement.cpp+7−5
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313
1414 #include <FBXReader.h>
1515 #include <GeometryUtil.h>
16+#include <OctreeUtils.h>
1617
1718 #include "EntitiesLogging.h"
1819 #include "EntityItemProperties.h"
@@ -295,7 +296,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData · 276 unmodified lines
295296 entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID());
296297 }
297298
298− if (includeThisEntity && params.viewFrustum) {
299+ if (includeThisEntity || params.recurseEverything) {
299300
300301 // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of
301302 // simulation changing what's visible. consider the case where the entity contains an angular velocity
@@ -303,7 +304,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData · 1 unmodified line
303304 // frustum culling on rendering.
304305 bool success;
305306 AACube entityCube = entity->getQueryAACube(success);
306− if (!success || !params.viewFrustum->cubeIntersectsKeyhole(entityCube)) {
307+ if (!success || !params.viewFrustum.cubeIntersectsKeyhole(entityCube)) {
307308 includeThisEntity = false; // out of view, don't include it
308309 } else {
309310 // Check the size of the entity, it's possible that a "too small to see" entity is included in a
@@ -320,9 +321,10 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData · 10 unmodified lines
320321 // AABox. If this happens, fall back to the queryAACube.
321322 entityBounds = AABox(entityCube);
322323 }
323− auto renderAccuracy = params.viewFrustum->calculateRenderAccuracy(entityBounds,
324− params.octreeElementSizeScale,
325− params.boundaryLevelAdjust);
324+ auto renderAccuracy = calculateRenderAccuracy(params.viewFrustum.getPosition(),
325+ entityBounds,
326+ params.octreeElementSizeScale,
327+ params.boundaryLevelAdjust);
326328 if (renderAccuracy <= 0.0f) {
327329 includeThisEntity = false; // too small, don't include it
328330
libraries/octree/src/Octree.cpp+28−32
@@ -33,6 +33,7 @@ · 32 unmodified lines
3333 #include <QString>
3434
3535 #include <GeometryUtil.h>
36+#include <Gzip.h>
3637 #include <LogHandler.h>
3738 #include <NetworkAccessManager.h>
3839 #include <OctalCode.h>
@@ -40,12 +41,12 @@ · 1 unmodified line
4041 #include <ResourceManager.h>
4142 #include <SharedUtil.h>
4243 #include <PathUtils.h>
43−#include <Gzip.h>
44+#include <ViewFrustum.h>
4445
4546 #include "OctreeConstants.h"
4647 #include "OctreeElementBag.h"
4748 #include "Octree.h"
48−#include "ViewFrustum.h"
49+#include "OctreeUtils.h"
4950 #include "OctreeLogging.h"
5051
5152
@@ -898,7 +899,7 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element, · 846 unmodified lines
898899 }
899900
900901 // If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
901− if (params.viewFrustum && !element->isInView(*params.viewFrustum)) {
902+ if (!params.recurseEverything && !element->isInView(params.viewFrustum)) {
902903 params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
903904 return bytesWritten;
904905 }
@@ -1014,15 +1015,12 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 109 unmodified lines
10141015 }
10151016
10161017 ViewFrustum::intersection nodeLocationThisView = ViewFrustum::INSIDE; // assume we're inside
1017−
1018− // caller can pass NULL as viewFrustum if they want everything
1019− if (params.viewFrustum) {
1020− float distance = element->distanceToCamera(*params.viewFrustum);
1018+ if (!params.recurseEverything) {
10211019 float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
10221020 params.octreeElementSizeScale);
10231021
10241022 // If we're too far away for our render level, then just return
1025− if (distance >= boundaryDistance) {
1023+ if (element->distanceToCamera(params.viewFrustum) >= boundaryDistance) {
10261024 if (params.stats) {
10271025 params.stats->skippedDistance(element);
10281026 }
@@ -1034,7 +1032,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 5 unmodified lines
10341032 // if we are INSIDE, INTERSECT, or OUTSIDE
10351033 if (parentLocationThisView != ViewFrustum::INSIDE) {
10361034 assert(parentLocationThisView != ViewFrustum::OUTSIDE); // we shouldn't be here if our parent was OUTSIDE!
1037− nodeLocationThisView = element->computeViewIntersection(*params.viewFrustum);
1035+ nodeLocationThisView = element->computeViewIntersection(params.viewFrustum);
10381036 }
10391037
10401038 // If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
@@ -1052,8 +1050,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 11 unmodified lines
10521050 // because we don't send nodes from the previously know in view frustum.
10531051 bool wasInView = false;
10541052
1055− if (params.deltaViewFrustum && params.lastViewFrustum) {
1056− ViewFrustum::intersection location = element->computeViewIntersection(*params.lastViewFrustum);
1053+ if (params.deltaView) {
1054+ ViewFrustum::intersection location = element->computeViewIntersection(params.lastViewFrustum);
10571055
10581056 // If we're a leaf, then either intersect or inside is considered "formerly in view"
10591057 if (element->isLeaf()) {
@@ -1067,10 +1065,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 7 unmodified lines
10671065 // to it, and so therefore it may now be visible from an LOD perspective, in which case we don't consider it
10681066 // as "was in view"...
10691067 if (wasInView) {
1070− float distance = element->distanceToCamera(*params.lastViewFrustum);
10711068 float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
10721069 params.octreeElementSizeScale);
1073− if (distance >= boundaryDistance) {
1070+ if (element->distanceToCamera(params.lastViewFrustum) >= boundaryDistance) {
10741071 // This would have been invisible... but now should be visible (we wouldn't be here otherwise)...
10751072 wasInView = false;
10761073 }
@@ -1078,9 +1075,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 1 unmodified line
10781075 }
10791076
10801077 // If we were previously in the view, then we normally will return out of here and stop recursing. But
1081− // if we're in deltaViewFrustum mode, and this element has changed since it was last sent, then we do
1078+ // if we're in deltaView mode, and this element has changed since it was last sent, then we do
10821079 // need to send it.
1083− if (wasInView && !(params.deltaViewFrustum && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
1080+ if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
10841081 if (params.stats) {
10851082 params.stats->skippedWasInView(element);
10861083 }
@@ -1090,7 +1087,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 3 unmodified lines
10901087
10911088 // If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed,
10921089 // then we can also bail early and save bits
1093− if (!params.forceSendScene && !params.deltaViewFrustum &&
1090+ if (!params.forceSendScene && !params.deltaView &&
10941091 !element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
10951092 if (params.stats) {
10961093 params.stats->skippedNoChange(element);
@@ -1179,10 +1176,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 82 unmodified lines
11791176 int originalIndex = indexOfChildren[i];
11801177
11811178 bool childIsInView = (childElement &&
1182− ( !params.viewFrustum || // no view frustum was given, everything is assumed in view
1183− (nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are
1179+ (params.recurseEverything ||
1180+ (nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are
11841181 (nodeLocationThisView == ViewFrustum::INTERSECT &&
1185− childElement->isInView(*params.viewFrustum)) // the parent intersects and the child is in view
1182+ childElement->isInView(params.viewFrustum)) // the parent intersects and the child is in view
11861183 ));
11871184
11881185 if (!childIsInView) {
@@ -1192,12 +1189,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 3 unmodified lines
11921189 }
11931190 } else {
11941191 // Before we consider this further, let's see if it's in our LOD scope...
1195− float distance = distancesToChildren[i];
1196− float boundaryDistance = !params.viewFrustum ? 1 :
1197− boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
1192+ float boundaryDistance = params.recurseEverything ? 1 :
1193+ boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
11981194 params.octreeElementSizeScale);
11991195
1200− if (!(distance < boundaryDistance)) {
1196+ if (!(distancesToChildren[i] < boundaryDistance)) {
12011197 // don't need to check childElement here, because we can't get here with no childElement
12021198 if (params.stats) {
12031199 params.stats->skippedDistance(childElement);
@@ -1215,10 +1211,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 11 unmodified lines
12151211
12161212 bool childIsOccluded = false; // assume it's not occluded
12171213
1218− bool shouldRender = !params.viewFrustum
1219− ? true
1220− : childElement->calculateShouldRender(params.viewFrustum,
1221− params.octreeElementSizeScale, params.boundaryLevelAdjust);
1214+ bool shouldRender = params.recurseEverything ||
1215+ childElement->calculateShouldRender(params.viewFrustum,
1216+ params.octreeElementSizeScale, params.boundaryLevelAdjust);
12221217
12231218 // track some stats
12241219 if (params.stats) {
@@ -1236,8 +1231,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 11 unmodified lines
12361231 if (shouldRender && !childIsOccluded) {
12371232 bool childWasInView = false;
12381233
1239− if (childElement && params.deltaViewFrustum && params.lastViewFrustum) {
1240− ViewFrustum::intersection location = childElement->computeViewIntersection(*params.lastViewFrustum);
1234+ if (childElement && params.deltaView) {
1235+ ViewFrustum::intersection location = childElement->computeViewIntersection(params.lastViewFrustum);
12411236
12421237 // If we're a leaf, then either intersect or inside is considered "formerly in view"
12431238 if (childElement->isLeaf()) {
@@ -1251,7 +1246,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 7 unmodified lines
12511246 // Or if we were previously in the view, but this element has changed since it was last sent, then we do
12521247 // need to send it.
12531248 if (!childWasInView ||
1254− (params.deltaViewFrustum &&
1249+ (params.deltaView &&
12551250 childElement->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
12561251
12571252 childrenDataBits += (1 << (7 - originalIndex));
@@ -1456,7 +1451,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, · 198 unmodified lines
14561451 // called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep
14571452 // recursing, by returning TRUE in recurseChildrenWithData().
14581453
1459− if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenDataBits, originalIndex)) {
1454+ if (params.recurseEverything || recurseChildrenWithData() || !oneAtBit(childrenDataBits, originalIndex)) {
14601455
14611456 // Allow the datatype a chance to determine if it really wants to recurse this tree. Usually this
14621457 // will be true. But if the tree has already been encoded, we will skip this.
@@ -1978,7 +1973,8 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElementPointer element) · 515 unmodified lines
19781973 bool lastPacketWritten = false;
19791974
19801975 while (OctreeElementPointer subTree = elementBag.extract()) {
1981− EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, NO_EXISTS_BITS);
1976+ EncodeBitstreamParams params(INT_MAX, NO_EXISTS_BITS);
1977+ params.recurseEverything = true;
19821978 withReadLock([&] {
19831979 params.extraEncodeData = &extraEncodeData;
19841980 bytesWritten = encodeTreeBitstream(subTree, &packetData, elementBag, params);
libraries/octree/src/Octree.h+13−16
@@ -20,9 +20,9 @@ · 19 unmodified lines
2020
2121 #include <shared/ReadWriteLockable.h>
2222 #include <SimpleMovingAverage.h>
23+#include <ViewFrustum.h>
2324
2425 #include "JurisdictionMap.h"
25−#include "ViewFrustum.h"
2626 #include "OctreeElement.h"
2727 #include "OctreeElementBag.h"
2828 #include "OctreePacketData.h"
@@ -61,22 +61,22 @@ const int LOW_RES_MOVING_ADJUST = 1; · 32 unmodified lines
6161 const quint64 IGNORE_LAST_SENT = 0;
6262
6363 #define IGNORE_SCENE_STATS NULL
64−#define IGNORE_VIEW_FRUSTUM NULL
6564 #define IGNORE_COVERAGE_MAP NULL
6665 #define IGNORE_JURISDICTION_MAP NULL
6766
6867 class EncodeBitstreamParams {
6968 public:
69+ ViewFrustum viewFrustum;
70+ ViewFrustum lastViewFrustum;
71+ quint64 lastViewFrustumSent;
7072 int maxEncodeLevel;
7173 int maxLevelReached;
72− const ViewFrustum* viewFrustum;
7374 bool includeExistsBits;
7475 int chopLevels;
75− bool deltaViewFrustum;
76− const ViewFrustum* lastViewFrustum;
76+ bool deltaView;
77+ bool recurseEverything { false };
7778 int boundaryLevelAdjust;
7879 float octreeElementSizeScale;
79− quint64 lastViewFrustumSent;
8080 bool forceSendScene;
8181 OctreeSceneStats* stats;
8282 JurisdictionMap* jurisdictionMap;
@@ -99,11 +99,9 @@ public: · 16 unmodified lines
9999
100100 EncodeBitstreamParams(
101101 int maxEncodeLevel = INT_MAX,
102− const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
103102 bool includeExistsBits = WANT_EXISTS_BITS,
104103 int chopLevels = 0,
105− bool deltaViewFrustum = false,
106− const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
104+ bool useDeltaView = false,
107105 int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
108106 float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
109107 quint64 lastViewFrustumSent = IGNORE_LAST_SENT,
@@ -111,22 +109,22 @@ public: · 1 unmodified line
111109 OctreeSceneStats* stats = IGNORE_SCENE_STATS,
112110 JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP,
113111 OctreeElementExtraEncodeData* extraEncodeData = NULL) :
112+ lastViewFrustumSent(lastViewFrustumSent),
114113 maxEncodeLevel(maxEncodeLevel),
115114 maxLevelReached(0),
116− viewFrustum(viewFrustum),
117115 includeExistsBits(includeExistsBits),
118116 chopLevels(chopLevels),
119− deltaViewFrustum(deltaViewFrustum),
120− lastViewFrustum(lastViewFrustum),
117+ deltaView(useDeltaView),
121118 boundaryLevelAdjust(boundaryLevelAdjust),
122119 octreeElementSizeScale(octreeElementSizeScale),
123− lastViewFrustumSent(lastViewFrustumSent),
124120 forceSendScene(forceSendScene),
125121 stats(stats),
126122 jurisdictionMap(jurisdictionMap),
127123 extraEncodeData(extraEncodeData),
128124 stopReason(UNKNOWN)
129− {}
125+ {
126+ lastViewFrustum.invalidate();
127+ }
130128
131129 void displayStopReason() {
132130 printf("StopReason: ");
@@ -341,7 +339,7 @@ public: · 208 unmodified lines
341339
342340 bool getIsClient() const { return !_isServer; } /// Is this a client based tree. Allows guards for certain operations
343341 void setIsClient(bool isClient) { _isServer = !isClient; }
344−
342+
345343 virtual void dumpTree() { }
346344 virtual void pruneTree() { }
347345
@@ -352,7 +350,6 @@ public: · 4 unmodified lines
352350 virtual quint64 getAverageCreateTime() const { return 0; }
353351 virtual quint64 getAverageLoggingTime() const { return 0; }
354352
355−
356353 signals:
357354 void importSize(float x, float y, float z);
358355 void importProgress(int progress);
libraries/octree/src/OctreeElement.cpp+4−3
@@ -22,10 +22,11 @@ · 21 unmodified lines
2222
2323 #include "AACube.h"
2424 #include "OctalCode.h"
25+#include "Octree.h"
2526 #include "OctreeConstants.h"
2627 #include "OctreeElement.h"
27−#include "Octree.h"
2828 #include "OctreeLogging.h"
29+#include "OctreeUtils.h"
2930 #include "SharedUtil.h"
3031
3132 AtomicUIntStat OctreeElement::_octreeMemoryUsage { 0 };
@@ -471,11 +472,11 @@ ViewFrustum::intersection OctreeElement::computeViewIntersection(const ViewFrust · 439 unmodified lines
471472 // Since, if we know the camera position and orientation, we can know which of the corners is the "furthest"
472473 // corner. We can use we can use this corner as our "voxel position" to do our distance calculations off of.
473474 // By doing this, we don't need to test each child voxel's position vs the LOD boundary
474−bool OctreeElement::calculateShouldRender(const ViewFrustum* viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
475+bool OctreeElement::calculateShouldRender(const ViewFrustum& viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
475476 bool shouldRender = false;
476477
477478 if (hasContent()) {
478− float furthestDistance = furthestDistanceToCamera(*viewFrustum);
479+ float furthestDistance = furthestDistanceToCamera(viewFrustum);
479480 float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust, voxelScaleSize);
480481 bool inChildBoundary = (furthestDistance <= childBoundary);
481482 if (hasDetailedContent() && inChildBoundary) {
libraries/octree/src/OctreeElement.h+2−2
@@ -21,9 +21,9 @@ · 20 unmodified lines
2121
2222 #include <OctalCode.h>
2323 #include <SharedUtil.h>
24+#include <ViewFrustum.h>
2425
2526 #include "AACube.h"
26−#include "ViewFrustum.h"
2727 #include "OctreeConstants.h"
2828
2929 using AtomicUIntStat = std::atomic<uintmax_t>;
@@ -139,7 +139,7 @@ public: · 109 unmodified lines
139139 float distanceToCamera(const ViewFrustum& viewFrustum) const;
140140 float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const;
141141
142− bool calculateShouldRender(const ViewFrustum* viewFrustum,
142+ bool calculateShouldRender(const ViewFrustum& viewFrustum,
143143 float voxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
144144
145145 // points are assumed to be in Voxel Coordinates (not TREE_SCALE'd)
libraries/octree/src/OctreeHeadlessViewer.cpp+1−3
@@ -14,14 +14,12 @@ · 13 unmodified lines
1414 #include "OctreeLogging.h"
1515 #include "OctreeHeadlessViewer.h"
1616
17−OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer()
18−{
17+OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer() {
1918 _viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
2019 }
2120
2221 void OctreeHeadlessViewer::init() {
2322 OctreeRenderer::init();
24− setViewFrustum(&_viewFrustum);
2523 }
2624
2725 void OctreeHeadlessViewer::queryOctree() {
libraries/octree/src/OctreeHeadlessViewer.h+1−2
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414
1515 #include <udt/PacketHeaders.h>
1616 #include <SharedUtil.h>
17+#include <ViewFrustum.h>
1718
1819 #include "JurisdictionListener.h"
1920 #include "Octree.h"
@@ -22,7 +23,6 @@ · 2 unmodified lines
2223 #include "OctreeRenderer.h"
2324 #include "OctreeSceneStats.h"
2425 #include "Octree.h"
25−#include "ViewFrustum.h"
2626
2727 // Generic client side Octree renderer class.
2828 class OctreeHeadlessViewer : public OctreeRenderer {
@@ -66,7 +66,6 @@ public slots: · 37 unmodified lines
6666 unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); }
6767
6868 private:
69− ViewFrustum _viewFrustum;
7069 JurisdictionListener* _jurisdictionListener = nullptr;
7170 OctreeQuery _octreeQuery;
7271
libraries/octree/src/OctreeQuery.cpp+0−1
@@ -120,4 +120,3 @@ glm::vec3 OctreeQuery::calculateCameraDirection() const { · 119 unmodified lines
120120 glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FRONT, 0.0f));
121121 return direction;
122122 }
123−
libraries/octree/src/OctreeRenderer.cpp+3−4
@@ -22,8 +22,7 @@ · 21 unmodified lines
2222
2323 OctreeRenderer::OctreeRenderer() :
2424 _tree(NULL),
25− _managedTree(false),
26− _viewFrustum(NULL)
25+ _managedTree(false)
2726 {
2827 }
2928
@@ -201,9 +200,9 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer · 171 unmodified lines
201200
202201 bool OctreeRenderer::renderOperation(OctreeElementPointer element, void* extraData) {
203202 RenderArgs* args = static_cast<RenderArgs*>(extraData);
204− if (element->isInView(*args->_viewFrustum)) {
203+ if (element->isInView(args->getViewFrustum())) {
205204 if (element->hasContent()) {
206− if (element->calculateShouldRender(args->_viewFrustum, args->_sizeScale, args->_boundaryLevelAdjust)) {
205+ if (element->calculateShouldRender(args->getViewFrustum(), args->_sizeScale, args->_boundaryLevelAdjust)) {
207206 args->_renderer->renderElement(element, args);
208207 } else {
209208 return false; // if we shouldn't render, then we also should stop recursing.
libraries/octree/src/OctreeRenderer.h+4−4
@@ -20,10 +20,10 @@ · 19 unmodified lines
2020 #include <udt/PacketHeaders.h>
2121 #include <RenderArgs.h>
2222 #include <SharedUtil.h>
23+#include <ViewFrustum.h>
2324
2425 #include "Octree.h"
2526 #include "OctreePacketData.h"
26−#include "ViewFrustum.h"
2727
2828 class OctreeRenderer;
2929
@@ -51,8 +51,8 @@ public: · 21 unmodified lines
5151 /// render the content of the octree
5252 virtual void render(RenderArgs* renderArgs);
5353
54− ViewFrustum* getViewFrustum() const { return _viewFrustum; }
55− void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
54+ const ViewFrustum& getViewFrustum() const { return _viewFrustum; }
55+ void setViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustum = viewFrustum; }
5656
5757 static bool renderOperation(OctreeElementPointer element, void* extraData);
5858
@@ -75,7 +75,7 @@ protected: · 16 unmodified lines
7575
7676 OctreePointer _tree;
7777 bool _managedTree;
78− ViewFrustum* _viewFrustum;
78+ ViewFrustum _viewFrustum;
7979
8080 SimpleMovingAverage _elementsPerPacket;
8181 SimpleMovingAverage _entitiesPerPacket;
libraries/octree/src/OctreeUtils.cpp+71−0
@@ -0,0 +1,71 @@
1+//
2+// OctreeUtils.cpp
3+// libraries/octree/src
4+//
5+// Created by Andrew Meadows 2016.03.04
6+// Copyright 2016 High Fidelity, Inc.
7+//
8+// Distributed under the Apache License, Version 2.0.
9+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10+//
11+
12+#include "OctreeUtils.h"
13+
14+#include <mutex>
15+
16+#include <glm/glm.hpp>
17+
18+#include <AABox.h>
19+
20+
21+float calculateRenderAccuracy(const glm::vec3& position,
22+ const AABox& bounds,
23+ float octreeSizeScale,
24+ int boundaryLevelAdjust) {
25+ float largestDimension = bounds.getLargestDimension();
26+
27+ const float maxScale = (float)TREE_SCALE;
28+ float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
29+
30+ static std::once_flag once;
31+ static QMap<float, float> shouldRenderTable;
32+ std::call_once(once, [&] {
33+ float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
34+ float scale = maxScale;
35+ float factor = 1.0f;
36+
37+ while (scale > SMALLEST_SCALE_IN_TABLE) {
38+ scale /= 2.0f;
39+ factor /= 2.0f;
40+ shouldRenderTable[scale] = factor;
41+ }
42+ });
43+
44+ float closestScale = maxScale;
45+ float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
46+ QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
47+ if (lowerBound != shouldRenderTable.constEnd()) {
48+ closestScale = lowerBound.key();
49+ visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
50+ }
51+
52+ if (closestScale < largestDimension) {
53+ visibleDistanceAtClosestScale *= 2.0f;
54+ }
55+
56+ // FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return
57+ // a floating point for objects that have small angular size to indicate that they may be rendered
58+ // with lower preciscion
59+ float distanceToCamera = glm::length(bounds.calcCenter() - position);
60+ return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
61+}
62+
63+float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
64+ return voxelSizeScale / powf(2.0f, renderLevel);
65+}
66+
67+float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) {
68+ const float maxScale = (float)TREE_SCALE;
69+ float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
70+ return atan(maxScale / visibleDistanceAtMaxScale);
71+}
libraries/octree/src/OctreeUtils.h+30−0
@@ -0,0 +1,30 @@
1+//
2+// OctreeUtils.h
3+// libraries/octree/src
4+//
5+// Created by Andrew Meadows 2016.03.04
6+// Copyright 2016 High Fidelity, Inc.
7+//
8+// Distributed under the Apache License, Version 2.0.
9+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10+//
11+
12+#ifndef hifi_OctreeUtils_h
13+#define hifi_OctreeUtils_h
14+
15+#include "OctreeConstants.h"
16+
17+class AABox;
18+
19+/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
20+/// level it returns 0.0f for things that are so small for the current settings that they could not be visible.
21+float calculateRenderAccuracy(const glm::vec3& position,
22+ const AABox& bounds,
23+ float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
24+ int boundaryLevelAdjust = 0);
25+
26+float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
27+
28+float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust);
29+
30+#endif // hifi_OctreeUtils_h
libraries/render-utils/src/AbstractViewStateInterface.h+5−5
@@ -28,14 +28,14 @@ class PickRay; · 27 unmodified lines
2828 /// Interface provided by Application to other objects that need access to the current view state details
2929 class AbstractViewStateInterface {
3030 public:
31− /// gets the current view frustum for rendering the view state
32− virtual ViewFrustum* getCurrentViewFrustum() = 0;
31+ /// copies the current view frustum for rendering the view state
32+ virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0;
3333
34− /// gets the shadow view frustum for rendering the view state
35− virtual ViewFrustum* getShadowViewFrustum() = 0;
34+ /// copies the shadow view frustum for rendering the view state
35+ virtual void copyShadowViewFrustum(ViewFrustum& viewOut) const = 0;
3636
3737 virtual QThread* getMainThread() = 0;
38−
38+
3939 virtual PickRay computePickRay(float x, float y) const = 0;
4040
4141 virtual glm::vec3 getAvatarPosition() const = 0;
libraries/render-utils/src/AmbientOcclusionEffect.cpp+4−4
@@ -284,7 +284,7 @@ void AmbientOcclusionEffect::updateGaussianDistribution() { · 283 unmodified lines
284284
285285 void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
286286 assert(renderContext->args);
287− assert(renderContext->args->_viewFrustum);
287+ assert(renderContext->args->hasViewFrustum());
288288
289289 RenderArgs* args = renderContext->args;
290290
@@ -309,7 +309,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext · 18 unmodified lines
309309 auto resolutionLevel = getResolutionLevel();
310310
311311 // Update the depth info with near and far (same for stereo)
312− setDepthInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip());
312+ setDepthInfo(args->getViewFrustum().getNearClip(), args->getViewFrustum().getFarClip());
313313
314314 _frameTransformBuffer.edit<FrameTransform>().pixelInfo = args->_viewport;
315315 //_parametersBuffer.edit<Parameters>()._ditheringInfo.y += 0.25f;
@@ -319,7 +319,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext · 3 unmodified lines
319319 if (!isStereo) {
320320 // Eval the mono projection
321321 mat4 monoProjMat;
322− args->_viewFrustum->evalProjectionMatrix(monoProjMat);
322+ args->getViewFrustum().evalProjectionMatrix(monoProjMat);
323323 _frameTransformBuffer.edit<FrameTransform>().projection[0] = monoProjMat;
324324 _frameTransformBuffer.edit<FrameTransform>().stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f);
325325
@@ -365,7 +365,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext · 39 unmodified lines
365365
366366 // Pyramid pass
367367 batch.setFramebuffer(pyramidFBO);
368− batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->_viewFrustum->getFarClip(), 0.0f, 0.0f, 0.0f));
368+ batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->getViewFrustum().getFarClip(), 0.0f, 0.0f, 0.0f));
369369 batch.setPipeline(pyramidPipeline);
370370 batch.setResourceTexture(AmbientOcclusionEffect_DepthMapSlot, depthBuffer);
371371 batch.draw(gpu::TRIANGLE_STRIP, 4);
libraries/render-utils/src/AntialiasingEffect.cpp+4−4
@@ -94,7 +94,7 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { · 93 unmodified lines
9494
9595 void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
9696 assert(renderContext->args);
97− assert(renderContext->args->_viewFrustum);
97+ assert(renderContext->args->hasViewFrustum());
9898
9999 RenderArgs* args = renderContext->args;
100100
@@ -118,8 +118,8 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re · 17 unmodified lines
118118
119119 glm::mat4 projMat;
120120 Transform viewMat;
121− args->_viewFrustum->evalProjectionMatrix(projMat);
122− args->_viewFrustum->evalViewTransform(viewMat);
121+ args->getViewFrustum().evalProjectionMatrix(projMat);
122+ args->getViewFrustum().evalViewTransform(viewMat);
123123 batch.setProjectionTransform(projMat);
124124 batch.setViewTransform(viewMat);
125125 batch.setModelTransform(Transform());
@@ -134,7 +134,7 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re · 8 unmodified lines
134134 float left, right, bottom, top, nearVal, farVal;
135135 glm::vec4 nearClipPlane, farClipPlane;
136136
137− args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
137+ args->getViewFrustum().computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
138138
139139 // float depthScale = (farVal - nearVal) / farVal;
140140 // float nearScale = -1.0f / nearVal;
libraries/render-utils/src/DebugDeferredBuffer.cpp+6−6
@@ -275,7 +275,7 @@ void DebugDeferredBuffer::configure(const Config& config) { · 274 unmodified lines
275275
276276 void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
277277 assert(renderContext->args);
278− assert(renderContext->args->_viewFrustum);
278+ assert(renderContext->args->hasViewFrustum());
279279 RenderArgs* args = renderContext->args;
280280
281281 gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
@@ -283,20 +283,20 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren · 1 unmodified line
283283 const auto framebufferCache = DependencyManager::get<FramebufferCache>();
284284 const auto textureCache = DependencyManager::get<TextureCache>();
285285 const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
286−
286+
287287 glm::mat4 projMat;
288288 Transform viewMat;
289− args->_viewFrustum->evalProjectionMatrix(projMat);
290− args->_viewFrustum->evalViewTransform(viewMat);
289+ args->getViewFrustum().evalProjectionMatrix(projMat);
290+ args->getViewFrustum().evalViewTransform(viewMat);
291291 batch.setProjectionTransform(projMat);
292292 batch.setViewTransform(viewMat);
293293 batch.setModelTransform(Transform());
294294
295295 // TODO REMOVE: Temporary until UI
296296 auto first = _customPipelines.begin()->first;
297−
297+
298298 batch.setPipeline(getPipeline(_mode, first));
299−
299+
300300 batch.setResourceTexture(Albedo, framebufferCache->getDeferredColorTexture());
301301 batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture());
302302 batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture());
libraries/render-utils/src/DeferredLightingEffect.cpp+5−5
@@ -218,15 +218,15 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo · 217 unmodified lines
218218 float tHeight = args->_viewport.w / (float)framebufferSize.height();
219219
220220 // The view frustum is the mono frustum base
221− auto viewFrustum = args->_viewFrustum;
221+ auto viewFrustum = args->getViewFrustum();
222222
223223 // Eval the mono projection
224224 mat4 monoProjMat;
225− viewFrustum->evalProjectionMatrix(monoProjMat);
225+ viewFrustum.evalProjectionMatrix(monoProjMat);
226226
227227 // The mono view transform
228228 Transform monoViewTransform;
229− viewFrustum->evalViewTransform(monoViewTransform);
229+ viewFrustum.evalViewTransform(monoViewTransform);
230230
231231 // THe mono view matrix coming from the mono view transform
232232 glm::mat4 monoViewMat;
@@ -296,8 +296,8 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo · 63 unmodified lines
296296 fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight);
297297 }
298298
299− auto eyePoint = viewFrustum->getPosition();
300− float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft());
299+ auto eyePoint = viewFrustum.getPosition();
300+ float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft());
301301
302302
303303 for (int side = 0; side < numPasses; side++) {
libraries/render-utils/src/HitEffect.cpp+5−5
@@ -62,19 +62,19 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() { · 61 unmodified lines
6262
6363 void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
6464 assert(renderContext->args);
65− assert(renderContext->args->_viewFrustum);
65+ assert(renderContext->args->hasViewFrustum());
6666 RenderArgs* args = renderContext->args;
6767
6868 gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
69−
69+
7070 glm::mat4 projMat;
7171 Transform viewMat;
72− args->_viewFrustum->evalProjectionMatrix(projMat);
73− args->_viewFrustum->evalViewTransform(viewMat);
72+ args->getViewFrustum().evalProjectionMatrix(projMat);
73+ args->getViewFrustum().evalViewTransform(viewMat);
7474 batch.setProjectionTransform(projMat);
7575 batch.setViewTransform(viewMat);
7676 batch.setModelTransform(Transform());
77−
77+
7878 batch.setPipeline(getHitEffectPipeline());
7979
8080 glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f);
libraries/render-utils/src/LightStage.cpp+4−5
@@ -20,7 +20,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum · 19 unmodified lines
2020 _schemaBuffer = std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema);
2121 }
2222
23−void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth) {
23+void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth) {
2424 assert(nearDepth < farDepth);
2525
2626 // Orient the keylight frustum
@@ -38,14 +38,13 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near · 11 unmodified lines
3838 _frustum->setOrientation(orientation);
3939
4040 // Position the keylight frustum
41− _frustum->setPosition(viewFrustum->getPosition() - (nearDepth + farDepth)*direction);
41+ _frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction);
4242
4343 const Transform view{ _frustum->getView()};
4444 const Transform viewInverse{ view.getInverseMatrix() };
4545
46− viewFrustum->calculate();
47− auto nearCorners = viewFrustum->getCorners(nearDepth);
48− auto farCorners = viewFrustum->getCorners(farDepth);
46+ auto nearCorners = viewFrustum.getCorners(nearDepth);
47+ auto farCorners = viewFrustum.getCorners(farDepth);
4948
5049 vec3 min{ viewInverse.transform(nearCorners.bottomLeft) };
5150 vec3 max{ min };
libraries/render-utils/src/LightStage.h+1−1
@@ -28,7 +28,7 @@ public: · 27 unmodified lines
2828
2929 Shadow(model::LightPointer light);
3030
31− void setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth);
31+ void setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth);
3232
3333 const std::shared_ptr<ViewFrustum> getFrustum() const { return _frustum; }
3434
libraries/render-utils/src/RenderDeferredTask.cpp+14−14
@@ -163,7 +163,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend · 162 unmodified lines
163163
164164
165165 // Is it possible that we render without a viewFrustum ?
166− if (!(renderContext->args && renderContext->args->_viewFrustum)) {
166+ if (!(renderContext->args && renderContext->args->hasViewFrustum())) {
167167 return;
168168 }
169169
@@ -174,7 +174,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend · 4 unmodified lines
174174
175175 void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
176176 assert(renderContext->args);
177− assert(renderContext->args->_viewFrustum);
177+ assert(renderContext->args->hasViewFrustum());
178178
179179 auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
180180
@@ -187,8 +187,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont · 6 unmodified lines
187187
188188 glm::mat4 projMat;
189189 Transform viewMat;
190− args->_viewFrustum->evalProjectionMatrix(projMat);
191− args->_viewFrustum->evalViewTransform(viewMat);
190+ args->getViewFrustum().evalProjectionMatrix(projMat);
191+ args->getViewFrustum().evalViewTransform(viewMat);
192192
193193 batch.setProjectionTransform(projMat);
194194 batch.setViewTransform(viewMat);
@@ -202,7 +202,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont · 7 unmodified lines
202202
203203 void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
204204 assert(renderContext->args);
205− assert(renderContext->args->_viewFrustum);
205+ assert(renderContext->args->hasViewFrustum());
206206
207207 auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
208208
@@ -215,8 +215,8 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R · 6 unmodified lines
215215
216216 glm::mat4 projMat;
217217 Transform viewMat;
218− args->_viewFrustum->evalProjectionMatrix(projMat);
219− args->_viewFrustum->evalViewTransform(viewMat);
218+ args->getViewFrustum().evalProjectionMatrix(projMat);
219+ args->getViewFrustum().evalViewTransform(viewMat);
220220
221221 batch.setProjectionTransform(projMat);
222222 batch.setViewTransform(viewMat);
@@ -240,7 +240,7 @@ DrawOverlay3D::DrawOverlay3D(bool opaque) : · 17 unmodified lines
240240
241241 void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const render::ItemBounds& inItems) {
242242 assert(renderContext->args);
243− assert(renderContext->args->_viewFrustum);
243+ assert(renderContext->args->hasViewFrustum());
244244
245245 auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
246246
@@ -268,8 +268,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon · 21 unmodified lines
268268
269269 glm::mat4 projMat;
270270 Transform viewMat;
271− args->_viewFrustum->evalProjectionMatrix(projMat);
272− args->_viewFrustum->evalViewTransform(viewMat);
271+ args->getViewFrustum().evalProjectionMatrix(projMat);
272+ args->getViewFrustum().evalViewTransform(viewMat);
273273
274274 batch.setProjectionTransform(projMat);
275275 batch.setViewTransform(viewMat);
@@ -290,7 +290,7 @@ const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() { · 14 unmodified lines
290290
291291 void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
292292 assert(renderContext->args);
293− assert(renderContext->args->_viewFrustum);
293+ assert(renderContext->args->hasViewFrustum());
294294
295295 // from the touched pixel generate the stencil buffer
296296 RenderArgs* args = renderContext->args;
@@ -316,7 +316,7 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren · 19 unmodified lines
316316
317317 void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
318318 assert(renderContext->args);
319− assert(renderContext->args->_viewFrustum);
319+ assert(renderContext->args->hasViewFrustum());
320320
321321 RenderArgs* args = renderContext->args;
322322 doInBatch(args->_context, [&](gpu::Batch& batch) {
@@ -334,8 +334,8 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const · 11 unmodified lines
334334
335335 glm::mat4 projMat;
336336 Transform viewMat;
337− args->_viewFrustum->evalProjectionMatrix(projMat);
338− args->_viewFrustum->evalViewTransform(viewMat);
337+ args->getViewFrustum().evalProjectionMatrix(projMat);
338+ args->getViewFrustum().evalViewTransform(viewMat);
339339
340340 batch.setProjectionTransform(projMat);
341341 batch.setViewTransform(viewMat);
libraries/render-utils/src/RenderShadowTask.cpp+5−6
@@ -34,7 +34,7 @@ using namespace render; · 33 unmodified lines
3434 void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
3535 const render::ShapeBounds& inShapes) {
3636 assert(renderContext->args);
37− assert(renderContext->args->_viewFrustum);
37+ assert(renderContext->args->hasViewFrustum());
3838
3939 const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
4040 const auto globalLight = lightStage.lights[0];
@@ -146,16 +146,15 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render · 105 unmodified lines
146146 }
147147
148148 // Cache old render args
149− ViewFrustum* viewFrustum = args->_viewFrustum;
150149 RenderArgs::RenderMode mode = args->_renderMode;
151150
152− auto nearClip = viewFrustum->getNearClip();
151+ auto nearClip = args->getViewFrustum().getNearClip();
153152 float nearDepth = -args->_boomOffset.z;
154153 const int SHADOW_FAR_DEPTH = 20;
155− globalLight->shadow.setKeylightFrustum(viewFrustum, nearDepth, nearClip + SHADOW_FAR_DEPTH);
154+ globalLight->shadow.setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH);
156155
157156 // Set the keylight render args
158− args->_viewFrustum = globalLight->shadow.getFrustum().get();
157+ args->pushViewFrustum(*(globalLight->shadow.getFrustum()));
159158 args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
160159
161160 // TODO: Allow runtime manipulation of culling ShouldRenderFunctor
@@ -165,6 +164,6 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render · 3 unmodified lines
165164 }
166165
167166 // Reset the render args
168− args->_viewFrustum = viewFrustum;
167+ args->popViewFrustum();
169168 args->_renderMode = mode;
170169 };
libraries/render/src/render/CullTask.cpp+16−20
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <algorithm>
1515 #include <assert.h>
1616
17+#include <OctreeUtils.h>
1718 #include <PerfStat.h>
1819 #include <ViewFrustum.h>
1920 #include <gpu/Context.h>
@@ -23,10 +24,10 @@ using namespace render; · 3 unmodified lines
2324 void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details,
2425 const ItemBounds& inItems, ItemBounds& outItems) {
2526 assert(renderContext->args);
26− assert(renderContext->args->_viewFrustum);
27+ assert(renderContext->args->hasViewFrustum());
2728
2829 RenderArgs* args = renderContext->args;
29− ViewFrustum* frustum = args->_viewFrustum;
30+ const ViewFrustum& frustum = args->getViewFrustum();
3031
3132 details._considered += (int)inItems.size();
3233
@@ -42,7 +43,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc · 9 unmodified lines
4243 bool inView;
4344 {
4445 PerformanceTimer perfTimer("boxIntersectsFrustum");
45− inView = frustum->boxIntersectsFrustum(item.bound);
46+ inView = frustum.boxIntersectsFrustum(item.bound);
4647 }
4748 if (inView) {
4849 bool bigEnoughToRender;
@@ -64,7 +65,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc · 15 unmodified lines
6465
6566 void FetchNonspatialItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) {
6667 assert(renderContext->args);
67− assert(renderContext->args->_viewFrustum);
68+ assert(renderContext->args->hasViewFrustum());
6869 auto& scene = sceneContext->_scene;
6970
7071 outItems.clear();
@@ -85,7 +86,7 @@ void FetchSpatialTree::configure(const Config& config) { · 14 unmodified lines
8586
8687 void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemSpatialTree::ItemSelection& outSelection) {
8788 assert(renderContext->args);
88− assert(renderContext->args->_viewFrustum);
89+ assert(renderContext->args->hasViewFrustum());
8990 RenderArgs* args = renderContext->args;
9091 auto& scene = sceneContext->_scene;
9192
@@ -93,22 +94,18 @@ void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const Render · 1 unmodified line
9394 outSelection.clear();
9495
9596 // Eventually use a frozen frustum
96− auto queryFrustum = *args->_viewFrustum;
97+ auto queryFrustum = args->getViewFrustum();
9798 if (_freezeFrustum) {
9899 if (_justFrozeFrustum) {
99100 _justFrozeFrustum = false;
100− _frozenFrutstum = *args->_viewFrustum;
101+ _frozenFrutstum = args->getViewFrustum();
101102 }
102103 queryFrustum = _frozenFrutstum;
103104 }
104105
105106 // Octree selection!
106−
107− float angle = glm::degrees(queryFrustum.getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
108−
109−
107+ float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
110108 scene->getSpatialTree().selectCellItems(outSelection, _filter, queryFrustum, angle);
111−
112109 }
113110
114111 void CullSpatialSelection::configure(const Config& config) {
@@ -120,7 +117,7 @@ void CullSpatialSelection::configure(const Config& config) { · 5 unmodified lines
120117 void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext,
121118 const ItemSpatialTree::ItemSelection& inSelection, ItemBounds& outItems) {
122119 assert(renderContext->args);
123− assert(renderContext->args->_viewFrustum);
120+ assert(renderContext->args->hasViewFrustum());
124121 RenderArgs* args = renderContext->args;
125122 auto& scene = sceneContext->_scene;
126123
@@ -128,13 +125,12 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re · 1 unmodified line
128125 details._considered += (int)inSelection.numItems();
129126
130127 // Eventually use a frozen frustum
131− auto argFrustum = args->_viewFrustum;
132128 if (_freezeFrustum) {
133129 if (_justFrozeFrustum) {
134130 _justFrozeFrustum = false;
135− _frozenFrutstum = *args->_viewFrustum;
131+ _frozenFrutstum = args->getViewFrustum();
136132 }
137− args->_viewFrustum = &_frozenFrutstum; // replace the true view frustum by the frozen one
133+ args->pushViewFrustum(_frozenFrutstum); // replace the true view frustum by the frozen one
138134 }
139135
140136 // Culling Frustum / solidAngle test helper class
@@ -151,8 +147,8 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re · 10 unmodified lines
151147 _renderDetails(renderDetails)
152148 {
153149 // FIXME: Keep this code here even though we don't use it yet
154− /*_eyePos = _args->_viewFrustum->getPosition();
155− float a = glm::degrees(_args->_viewFrustum->getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
150+ /*_eyePos = _args->getViewFrustum().getPosition();
151+ float a = glm::degrees(Octree::getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
156152 auto angle = std::min(glm::radians(45.0f), a); // no worse than 45 degrees
157153 angle = std::max(glm::radians(1.0f / 60.0f), a); // no better than 1 minute of degree
158154 auto tanAlpha = tan(angle);
@@ -161,7 +157,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re · 2 unmodified lines
161157 }
162158
163159 bool frustumTest(const AABox& bound) {
164− if (!_args->_viewFrustum->boxIntersectsFrustum(bound)) {
160+ if (!_args->getViewFrustum().boxIntersectsFrustum(bound)) {
165161 _renderDetails._outOfView++;
166162 return false;
167163 }
@@ -305,7 +301,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re · 137 unmodified lines
305301
306302 // Restore frustum if using the frozen one:
307303 if (_freezeFrustum) {
308− args->_viewFrustum = argFrustum;
304+ args->popViewFrustum();
309305 }
310306
311307 std::static_pointer_cast<Config>(renderContext->jobConfig)->numItems = (int)outItems.size();
libraries/render/src/render/DrawSceneOctree.cpp+8−7
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <algorithm>
1515 #include <assert.h>
1616
17+#include <OctreeUtils.h>
1718 #include <PerfStat.h>
1819 #include <RenderArgs.h>
1920
@@ -86,7 +87,7 @@ void DrawSceneOctree::configure(const Config& config) { · 66 unmodified lines
8687 void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
8788 const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) {
8889 assert(renderContext->args);
89− assert(renderContext->args->_viewFrustum);
90+ assert(renderContext->args->hasViewFrustum());
9091 RenderArgs* args = renderContext->args;
9192 auto& scene = sceneContext->_scene;
9293
@@ -97,8 +98,8 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext, · 4 unmodified lines
9798 gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
9899 glm::mat4 projMat;
99100 Transform viewMat;
100− args->_viewFrustum->evalProjectionMatrix(projMat);
101− args->_viewFrustum->evalViewTransform(viewMat);
101+ args->getViewFrustum().evalProjectionMatrix(projMat);
102+ args->getViewFrustum().evalViewTransform(viewMat);
102103 batch.setViewportTransform(args->_viewport);
103104
104105 batch.setProjectionTransform(projMat);
@@ -148,7 +149,7 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext, · 43 unmodified lines
148149 }
149150 // Draw the LOD Reticle
150151 {
151− float angle = glm::degrees(args->_viewFrustum->getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
152+ float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
152153 Transform crosshairModel;
153154 crosshairModel.setTranslation(glm::vec3(0.0, 0.0, -1000.0));
154155 crosshairModel.setScale(1000.0 * tan(glm::radians(angle))); // Scaling at the actual tan of the lod angle => Multiplied by TWO
@@ -198,15 +199,15 @@ void DrawItemSelection::configure(const Config& config) { · 43 unmodified lines
198199 void DrawItemSelection::run(const SceneContextPointer& sceneContext,
199200 const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) {
200201 assert(renderContext->args);
201− assert(renderContext->args->_viewFrustum);
202+ assert(renderContext->args->hasViewFrustum());
202203 RenderArgs* args = renderContext->args;
203204 auto& scene = sceneContext->_scene;
204205
205206 gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
206207 glm::mat4 projMat;
207208 Transform viewMat;
208− args->_viewFrustum->evalProjectionMatrix(projMat);
209− args->_viewFrustum->evalViewTransform(viewMat);
209+ args->getViewFrustum().evalProjectionMatrix(projMat);
210+ args->getViewFrustum().evalViewTransform(viewMat);
210211 batch.setViewportTransform(args->_viewport);
211212
212213 batch.setProjectionTransform(projMat);
libraries/render/src/render/DrawStatus.cpp+3−3
@@ -107,7 +107,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, · 106 unmodified lines
107107 const RenderContextPointer& renderContext,
108108 const ItemBounds& inItems) {
109109 assert(renderContext->args);
110− assert(renderContext->args->_viewFrustum);
110+ assert(renderContext->args->hasViewFrustum());
111111 RenderArgs* args = renderContext->args;
112112 auto& scene = sceneContext->_scene;
113113 const int NUM_STATUS_VEC4_PER_ITEM = 2;
@@ -183,8 +183,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, · 69 unmodified lines
183183 gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
184184 glm::mat4 projMat;
185185 Transform viewMat;
186− args->_viewFrustum->evalProjectionMatrix(projMat);
187− args->_viewFrustum->evalViewTransform(viewMat);
186+ args->getViewFrustum().evalProjectionMatrix(projMat);
187+ args->getViewFrustum().evalViewTransform(viewMat);
188188 batch.setViewportTransform(args->_viewport);
189189
190190 batch.setProjectionTransform(projMat);
libraries/render/src/render/DrawTask.cpp+1−1
@@ -120,7 +120,7 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons · 119 unmodified lines
120120
121121 void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) {
122122 assert(renderContext->args);
123− assert(renderContext->args->_viewFrustum);
123+ assert(renderContext->args->hasViewFrustum());
124124 RenderArgs* args = renderContext->args;
125125
126126 // render lights
libraries/render/src/render/SortTask.cpp+3−3
@@ -1,5 +1,5 @@
11 //
2−// CullTask.cpp
2+// SortTask.cpp
33 // render/src/render
44 //
55 // Created by Sam Gateau on 2/2/16.
@@ -42,7 +42,7 @@ struct BackToFrontSort { · 36 unmodified lines
4242
4343 void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) {
4444 assert(renderContext->args);
45− assert(renderContext->args->_viewFrustum);
45+ assert(renderContext->args->hasViewFrustum());
4646
4747 auto& scene = sceneContext->_scene;
4848 RenderArgs* args = renderContext->args;
@@ -60,7 +60,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende · 11 unmodified lines
6060 for (auto itemDetails : inItems) {
6161 auto item = scene->getItem(itemDetails.id);
6262 auto bound = itemDetails.bound; // item.getBound();
63− float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter());
63+ float distance = args->getViewFrustum().distanceToCamera(bound.calcCenter());
6464
6565 itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound));
6666 }
libraries/shared/src/CubeProjectedPolygon.cpprenamed from libraries/octree/src/OctreeProjectedPolygon.cpp+48−48
@@ -1,6 +1,6 @@
11 //
2−// OctreeProjectedPolygon.cpp
3−// libraries/octree/src
2+// CubeProjectedPolygon.cpp
3+// libraries/shared/src
44 //
55 // Created by Brad Hefta-Gaub on 06/11/13.
66 // Copyright 2013 High Fidelity, Inc.
@@ -15,50 +15,50 @@ · 8 unmodified lines
1515
1616 #include "GeometryUtil.h"
1717 #include "SharedUtil.h"
18−#include "OctreeLogging.h"
19−#include "OctreeProjectedPolygon.h"
18+#include "SharedLogging.h"
19+#include "CubeProjectedPolygon.h"
2020
2121
22−glm::vec2 BoundingBox::getVertex(int vertexNumber) const {
22+glm::vec2 BoundingRectangle::getVertex(int vertexNumber) const {
2323 switch (vertexNumber) {
24− case BoundingBox::BOTTOM_LEFT:
24+ case BoundingRectangle::BOTTOM_LEFT:
2525 return corner;
26− case BoundingBox::TOP_LEFT:
26+ case BoundingRectangle::TOP_LEFT:
2727 return glm::vec2(corner.x, corner.y + size.y);
28− case BoundingBox::BOTTOM_RIGHT:
28+ case BoundingRectangle::BOTTOM_RIGHT:
2929 return glm::vec2(corner.x + size.x, corner.y);
30− case BoundingBox::TOP_RIGHT:
30+ case BoundingRectangle::TOP_RIGHT:
3131 return corner + size;
3232 }
3333 assert(false); // not allowed
3434 return glm::vec2(0,0);
3535 }
3636
37−BoundingBox BoundingBox::topHalf() const {
37+BoundingRectangle BoundingRectangle::topHalf() const {
3838 float halfY = size.y/2.0f;
39− BoundingBox result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY));
39+ BoundingRectangle result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY));
4040 return result;
4141 }
4242
43−BoundingBox BoundingBox::bottomHalf() const {
43+BoundingRectangle BoundingRectangle::bottomHalf() const {
4444 float halfY = size.y/2.0f;
45− BoundingBox result(corner, glm::vec2(size.x, halfY));
45+ BoundingRectangle result(corner, glm::vec2(size.x, halfY));
4646 return result;
4747 }
4848
49−BoundingBox BoundingBox::leftHalf() const {
49+BoundingRectangle BoundingRectangle::leftHalf() const {
5050 float halfX = size.x/2.0f;
51− BoundingBox result(corner, glm::vec2(halfX, size.y));
51+ BoundingRectangle result(corner, glm::vec2(halfX, size.y));
5252 return result;
5353 }
5454
55−BoundingBox BoundingBox::rightHalf() const {
55+BoundingRectangle BoundingRectangle::rightHalf() const {
5656 float halfX = size.x/2.0f;
57− BoundingBox result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y));
57+ BoundingRectangle result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y));
5858 return result;
5959 }
6060
61−bool BoundingBox::contains(const BoundingBox& box) const {
61+bool BoundingRectangle::contains(const BoundingRectangle& box) const {
6262 return ( _set &&
6363 (box.corner.x >= corner.x) &&
6464 (box.corner.y >= corner.y) &&
@@ -67,7 +67,7 @@ bool BoundingBox::contains(const BoundingBox& box) const { · 2 unmodified lines
6767 );
6868 }
6969
70−bool BoundingBox::contains(const glm::vec2& point) const {
70+bool BoundingRectangle::contains(const glm::vec2& point) const {
7171 return ( _set &&
7272 (point.x > corner.x) &&
7373 (point.y > corner.y) &&
@@ -76,7 +76,7 @@ bool BoundingBox::contains(const glm::vec2& point) const { · 2 unmodified lines
7676 );
7777 }
7878
79−void BoundingBox::explandToInclude(const BoundingBox& box) {
79+void BoundingRectangle::explandToInclude(const BoundingRectangle& box) {
8080 if (!_set) {
8181 corner = box.corner;
8282 size = box.size;
@@ -94,20 +94,20 @@ void BoundingBox::explandToInclude(const BoundingBox& box) { · 11 unmodified lines
9494 }
9595
9696
97−void BoundingBox::printDebugDetails(const char* label) const {
98− qCDebug(octree, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]",
99− (label ? label : "BoundingBox"),
97+void BoundingRectangle::printDebugDetails(const char* label) const {
98+ qCDebug(shared, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]",
99+ (label ? label : "BoundingRectangle"),
100100 debug::valueOf(_set), (double)corner.x, (double)corner.y, (double)size.x, (double)size.y,
101101 (double)corner.x, (double)corner.y, (double)(corner.x+size.x), (double)(corner.y+size.y));
102102 }
103103
104104
105−long OctreeProjectedPolygon::pointInside_calls = 0;
106−long OctreeProjectedPolygon::occludes_calls = 0;
107−long OctreeProjectedPolygon::intersects_calls = 0;
105+long CubeProjectedPolygon::pointInside_calls = 0;
106+long CubeProjectedPolygon::occludes_calls = 0;
107+long CubeProjectedPolygon::intersects_calls = 0;
108108
109109
110−OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) :
110+CubeProjectedPolygon::CubeProjectedPolygon(const BoundingRectangle& box) :
111111 _vertexCount(4),
112112 _maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX),
113113 _distance(0)
@@ -118,7 +118,7 @@ OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) : · 4 unmodified lines
118118 }
119119
120120
121−void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
121+void CubeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
122122 _vertices[vertex] = point;
123123
124124 // keep track of our bounding box
@@ -138,9 +138,9 @@ void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) { · 13 unmodified lines
138138 }
139139
140140 // can be optimized with new pointInside()
141−bool OctreeProjectedPolygon::occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView) const {
141+bool CubeProjectedPolygon::occludes(const CubeProjectedPolygon& occludee, bool checkAllInView) const {
142142
143− OctreeProjectedPolygon::occludes_calls++;
143+ CubeProjectedPolygon::occludes_calls++;
144144
145145 // if we are completely out of view, then we definitely don't occlude!
146146 // if the occludee is completely out of view, then we also don't occlude it
@@ -197,12 +197,12 @@ bool OctreeProjectedPolygon::occludes(const OctreeProjectedPolygon& occludee, bo · 50 unmodified lines
197197 return false; // if we got this far, then we're not occluded
198198 }
199199
200−bool OctreeProjectedPolygon::occludes(const BoundingBox& boxOccludee) const {
201− OctreeProjectedPolygon testee(boxOccludee);
200+bool CubeProjectedPolygon::occludes(const BoundingRectangle& boxOccludee) const {
201+ CubeProjectedPolygon testee(boxOccludee);
202202 return occludes(testee);
203203 }
204204
205−bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const {
205+bool CubeProjectedPolygon::matches(const CubeProjectedPolygon& testee) const {
206206 if (testee.getVertexCount() != getVertexCount()) {
207207 return false;
208208 }
@@ -231,14 +231,14 @@ bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const · 22 unmodified lines
231231 return true; // all of our vertices match, therefore we're the same
232232 }
233233
234−bool OctreeProjectedPolygon::matches(const BoundingBox& box) const {
235− OctreeProjectedPolygon testee(box);
234+bool CubeProjectedPolygon::matches(const BoundingRectangle& box) const {
235+ CubeProjectedPolygon testee(box);
236236 return matches(testee);
237237 }
238238
239−bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const {
239+bool CubeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const {
240240
241− OctreeProjectedPolygon::pointInside_calls++;
241+ CubeProjectedPolygon::pointInside_calls++;
242242
243243 // first check the bounding boxes, the point must be fully within the boounding box of this polygon
244244 if ((point.x > getMaxX()) ||
@@ -264,23 +264,23 @@ bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVe · 19 unmodified lines
264264 return true;
265265 }
266266
267−void OctreeProjectedPolygon::printDebugDetails() const {
268− qCDebug(octree, "OctreeProjectedPolygon..."
267+void CubeProjectedPolygon::printDebugDetails() const {
268+ qCDebug(shared, "CubeProjectedPolygon..."
269269 " minX=%f maxX=%f minY=%f maxY=%f", (double)getMinX(), (double)getMaxX(), (double)getMinY(), (double)getMaxY());
270− qCDebug(octree, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance());
270+ qCDebug(shared, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance());
271271 for (int i = 0; i < getVertexCount(); i++) {
272272 glm::vec2 point = getVertex(i);
273− qCDebug(octree, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y);
273+ qCDebug(shared, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y);
274274 }
275275 }
276276
277−bool OctreeProjectedPolygon::intersects(const BoundingBox& box) const {
278− OctreeProjectedPolygon testee(box);
277+bool CubeProjectedPolygon::intersects(const BoundingRectangle& box) const {
278+ CubeProjectedPolygon testee(box);
279279 return intersects(testee);
280280 }
281281
282−bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) const {
283− OctreeProjectedPolygon::intersects_calls++;
282+bool CubeProjectedPolygon::intersects(const CubeProjectedPolygon& testee) const {
283+ CubeProjectedPolygon::intersects_calls++;
284284 return intersectsOnAxes(testee) && testee.intersectsOnAxes(*this);
285285 }
286286
@@ -294,7 +294,7 @@ bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) co · 7 unmodified lines
294294 // Note: this only works on convex polygons
295295 //
296296 //
297−bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& testee) const {
297+bool CubeProjectedPolygon::intersectsOnAxes(const CubeProjectedPolygon& testee) const {
298298
299299 // consider each edge of this polygon as a potential separating axis
300300 for (int i = 0; i < getVertexCount(); i++) {
@@ -324,7 +324,7 @@ bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& test · 23 unmodified lines
324324 return true;
325325 }
326326
327−bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const {
327+bool CubeProjectedPolygon::canMerge(const CubeProjectedPolygon& that) const {
328328
329329 // RIGHT/NEAR
330330 // LEFT/NEAR
@@ -642,7 +642,7 @@ bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const · 311 unmodified lines
642642 }
643643
644644
645−void OctreeProjectedPolygon::merge(const OctreeProjectedPolygon& that) {
645+void CubeProjectedPolygon::merge(const CubeProjectedPolygon& that) {
646646
647647 // RIGHT/NEAR
648648 // LEFT/NEAR
libraries/shared/src/CubeProjectedPolygon.hrenamed from libraries/octree/src/OctreeProjectedPolygon.h+39−39
@@ -1,55 +1,55 @@
11 //
2−// OctreeProjectedPolygon.h
3−// libraries/octree/src
2+// CubeProjectedPolygon.h
3+// libraries/shared/src
44 //
55 // Created by Brad Hefta-Gaub on 06/11/13.
66 // Copyright 2013 High Fidelity, Inc.
77 //
8−// The projected shadow (on the 2D view plane) for a voxel
8+// The projected shadow (on the 2D view plane) for a cube
99 //
1010 // Distributed under the Apache License, Version 2.0.
1111 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
1212 //
1313
14−#ifndef hifi_OctreeProjectedPolygon_h
15−#define hifi_OctreeProjectedPolygon_h
14+#ifndef hifi_CubeProjectedPolygon_h
15+#define hifi_CubeProjectedPolygon_h
1616
1717 #include <glm/glm.hpp>
1818
1919 // there's a max of 6 vertices of a project polygon, and a max of twice that when clipped to the screen
20−const int MAX_PROJECTED_POLYGON_VERTEX_COUNT = 6;
21−const int MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT = MAX_PROJECTED_POLYGON_VERTEX_COUNT * 2;
20+const int MAX_PROJECTED_POLYGON_VERTEX_COUNT = 6;
21+const int MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT = MAX_PROJECTED_POLYGON_VERTEX_COUNT * 2;
2222 typedef glm::vec2 ProjectedVertices[MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT];
2323
24−class BoundingBox {
24+class BoundingRectangle {
2525 public:
2626 enum { BOTTOM_LEFT, BOTTOM_RIGHT, TOP_RIGHT, TOP_LEFT, VERTEX_COUNT };
2727
28− BoundingBox(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {}
29− BoundingBox() : _set(false) {}
28+ BoundingRectangle(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {}
29+ BoundingRectangle() : _set(false) {}
3030 glm::vec2 corner;
3131 glm::vec2 size;
32− bool contains(const BoundingBox& box) const;
32+ bool contains(const BoundingRectangle& box) const;
3333 bool contains(const glm::vec2& point) const;
3434 bool pointInside(const glm::vec2& point) const { return contains(point); }
3535
36− void explandToInclude(const BoundingBox& box);
36+ void explandToInclude(const BoundingRectangle& box);
3737
3838 float area() const { return size.x * size.y; }
3939
4040 int getVertexCount() const { return VERTEX_COUNT; }
4141 glm::vec2 getVertex(int vertexNumber) const;
4242
43− BoundingBox topHalf() const;
44− BoundingBox bottomHalf() const;
45− BoundingBox leftHalf() const;
46− BoundingBox rightHalf() const;
43+ BoundingRectangle topHalf() const;
44+ BoundingRectangle bottomHalf() const;
45+ BoundingRectangle leftHalf() const;
46+ BoundingRectangle rightHalf() const;
4747
4848 float getMaxX() const { return corner.x + size.x; }
4949 float getMaxY() const { return corner.y + size.y; }
5050 float getMinX() const { return corner.x; }
5151 float getMinY() const { return corner.y; }
52−
52+
5353 void printDebugDetails(const char* label=NULL) const;
5454 private:
5555 bool _set;
@@ -63,18 +63,18 @@ const int PROJECTION_NEAR = 16; · 7 unmodified lines
6363 const int PROJECTION_FAR = 32;
6464 const int PROJECTION_CLIPPED = 64;
6565
66−class OctreeProjectedPolygon {
66+class CubeProjectedPolygon {
6767
6868 public:
69− OctreeProjectedPolygon(const BoundingBox& box);
69+ CubeProjectedPolygon(const BoundingRectangle& box);
7070
71− OctreeProjectedPolygon(int vertexCount = 0) :
72− _vertexCount(vertexCount),
71+ CubeProjectedPolygon(int vertexCount = 0) :
72+ _vertexCount(vertexCount),
7373 _maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX),
7474 _distance(0)
7575 { }
76−
77− ~OctreeProjectedPolygon() { }
76+
77+ ~CubeProjectedPolygon() { }
7878 const ProjectedVertices& getVertices() const { return _vertices; }
7979 const glm::vec2& getVertex(int i) const { return _vertices[i]; }
8080 void setVertex(int vertex, const glm::vec2& point);
@@ -92,28 +92,28 @@ public: · 11 unmodified lines
9292
9393
9494 bool pointInside(const glm::vec2& point, bool* matchesVertex = NULL) const;
95− bool occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView = false) const;
96− bool occludes(const BoundingBox& occludee) const;
97− bool intersects(const OctreeProjectedPolygon& testee) const;
98− bool intersects(const BoundingBox& box) const;
99− bool matches(const OctreeProjectedPolygon& testee) const;
100− bool matches(const BoundingBox& testee) const;
101− bool intersectsOnAxes(const OctreeProjectedPolygon& testee) const;
102−
103− bool canMerge(const OctreeProjectedPolygon& that) const;
104− void merge(const OctreeProjectedPolygon& that); // replaces vertices of this with new merged version
105−
95+ bool occludes(const CubeProjectedPolygon& occludee, bool checkAllInView = false) const;
96+ bool occludes(const BoundingRectangle& occludee) const;
97+ bool intersects(const CubeProjectedPolygon& testee) const;
98+ bool intersects(const BoundingRectangle& box) const;
99+ bool matches(const CubeProjectedPolygon& testee) const;
100+ bool matches(const BoundingRectangle& testee) const;
101+ bool intersectsOnAxes(const CubeProjectedPolygon& testee) const;
102+
103+ bool canMerge(const CubeProjectedPolygon& that) const;
104+ void merge(const CubeProjectedPolygon& that); // replaces vertices of this with new merged version
105+
106106 float getMaxX() const { return _maxX; }
107107 float getMaxY() const { return _maxY; }
108108 float getMinX() const { return _minX; }
109109 float getMinY() const { return _minY; }
110−
111− BoundingBox getBoundingBox() const {
112− return BoundingBox(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY));
110+
111+ BoundingRectangle getBoundingBox() const {
112+ return BoundingRectangle(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY));
113113 }
114114
115115 void printDebugDetails() const;
116−
116+
117117 static long pointInside_calls;
118118 static long occludes_calls;
119119 static long intersects_calls;
@@ -132,4 +132,4 @@ private: · 12 unmodified lines
132132 };
133133
134134
135−#endif // hifi_OctreeProjectedPolygon_h
135+#endif // hifi_CubeProjectedPolygon_h
libraries/shared/src/PIDController.cpp+1−1
@@ -35,7 +35,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator · 34 unmodified lines
3535 updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue);
3636 }
3737 Q_ASSERT(!glm::isnan(computedValue));
38−
38+
3939 // update state for next time
4040 _lastError = error;
4141 _lastAccumulation = accumulatedError;
libraries/shared/src/Plane.cpprenamed from libraries/octree/src/Plane.cpp+5−5
@@ -1,6 +1,6 @@
11 //
22 // Plane.cpp
3−// libraries/octree/src/
3+// libraries/shared/src/
44 //
55 // Created by Brad Hefta-Gaub on 04/11/13.
66 // Copyright 2013 High Fidelity, Inc.
@@ -13,12 +13,12 @@ · 6 unmodified lines
1313 //
1414
1515 #include "Plane.h"
16−#include "OctreeLogging.h"
17−
1816
17+#include <stdio.h>
1918 #include <QtCore/QDebug>
2019
21−#include <stdio.h>
20+#include "SharedLogging.h"
21+
2222
2323 void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
2424 glm::vec3 linev1v2, linev1v3;
@@ -65,7 +65,7 @@ float Plane::distance(const glm::vec3 &point) const { · 40 unmodified lines
6565 }
6666
6767 void Plane::print() const {
68− qCDebug(octree, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f",
68+ qCDebug(shared, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f",
6969 (double)_point.x, (double)_point.y, (double)_point.z,
7070 (double)_normal.x, (double)_normal.y, (double)_normal.z, (double)_dCoefficient);
7171 }
libraries/shared/src/Plane.hrenamed from libraries/octree/src/Plane.h+5−4
@@ -1,6 +1,6 @@
11 //
22 // Plane.h
3−// libraries/octree/src/
3+// libraries/shared/src/
44 //
55 // Created by Brad Hefta-Gaub on 04/11/13.
66 // Copyright 2013 High Fidelity, Inc.
@@ -20,7 +20,7 @@ · 13 unmodified lines
2020 class Plane {
2121 public:
2222 Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); }
23− Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {};
23+ Plane() : _normal(0.0f), _point(0.0f), _dCoefficient(0.0f) {};
2424 ~Plane() {} ;
2525
2626 // methods for defining the plane
@@ -28,12 +28,13 @@ public: · 1 unmodified line
2828 void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point);
2929 void setCoefficients(float a, float b, float c, float d);
3030
31− // getters
31+ // getters
3232 const glm::vec3& getNormal() const { return _normal; };
3333 const glm::vec3& getPoint() const { return _point; };
3434 float getDCoefficient() const { return _dCoefficient; };
3535
3636 // utilities
37+ void invalidate() { _normal = glm::vec3(0.0f), _dCoefficient = 1.0e6f; } // distance() never less than 10^6
3738 float distance(const glm::vec3 &point) const;
3839 void print() const;
3940
@@ -44,4 +45,4 @@ private: · 4 unmodified lines
4445 };
4546
4647
47−#endif // hifi_Plane_h
48+#endif // hifi_Plane_h
libraries/shared/src/RenderArgs.h+22−10
@@ -14,12 +14,15 @@ · 13 unmodified lines
1414
1515 #include <functional>
1616 #include <memory>
17−#include "GLMHelpers.h"
17+#include <stack>
18+
19+#include <GLMHelpers.h>
20+#include <ViewFrustum.h>
21+
1822
1923
2024 class AABox;
2125 class OctreeRenderer;
22−class ViewFrustum;
2326
2427 namespace gpu {
2528 class Batch;
@@ -39,21 +42,21 @@ public: · 13 unmodified lines
3942 SHADOW,
4043 OTHER
4144 };
42−
45+
4346 struct Item {
4447 int _considered = 0;
4548 int _outOfView = 0;
4649 int _tooSmall = 0;
4750 int _rendered = 0;
4851 };
49−
52+
5053 int _materialSwitches = 0;
5154 int _trianglesRendered = 0;
52−
55+
5356 Item _item;
5457 Item _shadow;
5558 Item _other;
56−
59+
5760 Item& edit(Type type) {
5861 switch (type) {
5962 case SHADOW:
@@ -77,7 +80,6 @@ public: · 17 unmodified lines
7780
7881 RenderArgs(std::shared_ptr<gpu::Context> context = nullptr,
7982 OctreeRenderer* renderer = nullptr,
80− ViewFrustum* viewFrustum = nullptr,
8183 float sizeScale = 1.0f,
8284 int boundaryLevelAdjust = 0,
8385 RenderMode renderMode = DEFAULT_RENDER_MODE,
@@ -86,7 +88,6 @@ public: · 2 unmodified lines
8688 gpu::Batch* batch = nullptr) :
8789 _context(context),
8890 _renderer(renderer),
89− _viewFrustum(viewFrustum),
9091 _sizeScale(sizeScale),
9192 _boundaryLevelAdjust(boundaryLevelAdjust),
9293 _renderMode(renderMode),
@@ -95,11 +96,22 @@ public: · 2 unmodified lines
9596 _batch(batch) {
9697 }
9798
99+ bool hasViewFrustum() const { return _viewFrustums.size() > 0; }
100+ void setViewFrustum(const ViewFrustum& viewFrustum) {
101+ while (_viewFrustums.size() > 0) {
102+ _viewFrustums.pop();
103+ }
104+ _viewFrustums.push(viewFrustum);
105+ }
106+ const ViewFrustum& getViewFrustum() const { assert(_viewFrustums.size() > 0); return _viewFrustums.top(); }
107+ void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); }
108+ void popViewFrustum() { _viewFrustums.pop(); }
109+
98110 std::shared_ptr<gpu::Context> _context = nullptr;
99111 std::shared_ptr<gpu::Framebuffer> _blitFramebuffer = nullptr;
100112 std::shared_ptr<render::ShapePipeline> _pipeline = nullptr;
101113 OctreeRenderer* _renderer = nullptr;
102− ViewFrustum* _viewFrustum = nullptr;
114+ std::stack<ViewFrustum> _viewFrustums;
103115 glm::ivec4 _viewport{ 0.0f, 0.0f, 1.0f, 1.0f };
104116 glm::vec3 _boomOffset{ 0.0f, 0.0f, 1.0f };
105117 float _sizeScale = 1.0f;
@@ -108,7 +120,7 @@ public: · 2 unmodified lines
108120 RenderSide _renderSide = MONO;
109121 DebugFlags _debugFlags = RENDER_DEBUG_NONE;
110122 gpu::Batch* _batch = nullptr;
111−
123+
112124 std::shared_ptr<gpu::Texture> _whiteTexture;
113125
114126 RenderDetails _details;
libraries/shared/src/ViewFrustum.cpprenamed from libraries/octree/src/ViewFrustum.cpp+66−107
@@ -1,6 +1,6 @@
11 //
22 // ViewFrustum.cpp
3−// libraries/octree/src
3+// libraries/shared/src
44 //
55 // Created by Brad Hefta-Gaub on 04/11/13.
66 // Copyright 2013 High Fidelity, Inc.
@@ -17,13 +17,13 @@ · 10 unmodified lines
1717 #include <glm/gtx/vector_angle.hpp>
1818 #include <QtCore/QDebug>
1919
20−#include <NumericalConstants.h>
2120
2221 #include "GeometryUtil.h"
2322 #include "GLMHelpers.h"
23+#include "NumericalConstants.h"
24+#include "SharedLogging.h"
25+//#include "OctreeConstants.h"
2426 #include "ViewFrustum.h"
25−#include "OctreeLogging.h"
26−#include "OctreeConstants.h"
2727
2828 using namespace std;
2929
@@ -41,24 +41,24 @@ void ViewFrustum::setPosition(const glm::vec3& position) { · 11 unmodified lines
4141 }
4242
4343 // Order cooresponds to the order defined in the BoxVertex enum.
44−static const glm::vec4 NDC_VALUES[8] = {
45− glm::vec4(-1, -1, -1, 1),
46− glm::vec4(1, -1, -1, 1),
47− glm::vec4(1, 1, -1, 1),
48− glm::vec4(-1, 1, -1, 1),
49− glm::vec4(-1, -1, 1, 1),
50− glm::vec4(1, -1, 1, 1),
51− glm::vec4(1, 1, 1, 1),
52− glm::vec4(-1, 1, 1, 1),
44+static const glm::vec4 NDC_VALUES[NUM_FRUSTUM_CORNERS] = {
45+ glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f),
46+ glm::vec4(1.0f, -1.0f, -1.0f, 1.0f),
47+ glm::vec4(1.0f, 1.0f, -1.0f, 1.0f),
48+ glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f),
49+ glm::vec4(-1.0f, -1.0f, 1.0f, 1.0f),
50+ glm::vec4(1.0f, -1.0f, 1.0f, 1.0f),
51+ glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
52+ glm::vec4(-1.0f, 1.0f, 1.0f, 1.0f),
5353 };
5454
5555 void ViewFrustum::setProjection(const glm::mat4& projection) {
5656 _projection = projection;
57− _inverseProjection = glm::inverse(projection);
57+ glm::mat4 inverseProjection = glm::inverse(projection);
5858
5959 // compute our dimensions the usual way
60− for (int i = 0; i < 8; ++i) {
61− _corners[i] = _inverseProjection * NDC_VALUES[i];
60+ for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) {
61+ _corners[i] = inverseProjection * NDC_VALUES[i];
6262 _corners[i] /= _corners[i].w;
6363 }
6464 _nearClip = -_corners[BOTTOM_LEFT_NEAR].z;
@@ -66,12 +66,12 @@ void ViewFrustum::setProjection(const glm::mat4& projection) { · 1 unmodified line
6666 _aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) /
6767 (_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y);
6868
69− glm::vec4 top = _inverseProjection * vec4(0, 1, -1, 1);
69+ glm::vec4 top = inverseProjection * vec4(0.0f, 1.0f, -1.0f, 1.0f);
7070 top /= top.w;
71− _fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0, 0, -1), glm::normalize(vec3(top))))));
71+ _fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0.0f, 0.0f, -1.0f), glm::normalize(vec3(top))))));
7272 }
7373
74−// ViewFrustum::calculateViewFrustum()
74+// ViewFrustum::calculate()
7575 //
7676 // Description: this will calculate the view frustum bounds for a given position and direction
7777 //
@@ -84,7 +84,7 @@ void ViewFrustum::calculate() { · 6 unmodified lines
8484 // then transform them to world space
8585 glm::mat4 worldMatrix = glm::translate(_position) * glm::mat4(glm::mat3(_right, _up, -_direction));
8686 glm::vec4 v;
87− for (int i = 0; i < 8; ++i) {
87+ for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) {
8888 v = worldMatrix * _corners[i];
8989 v /= v.w;
9090 _cornersWorld[i] = glm::vec3(v);
@@ -133,7 +133,7 @@ const char* ViewFrustum::debugPlaneName (int plane) const { · 42 unmodified lines
133133 ViewFrustum::intersection ViewFrustum::calculateCubeFrustumIntersection(const AACube& cube) const {
134134 // only check against frustum
135135 ViewFrustum::intersection result = INSIDE;
136− for(int i=0; i < 6; i++) {
136+ for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
137137 const glm::vec3& normal = _planes[i].getNormal();
138138 // check distance to farthest cube point
139139 if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
@@ -178,7 +178,7 @@ ViewFrustum::intersection ViewFrustum::calculateCubeKeyholeIntersection(const AA · 38 unmodified lines
178178
179179 bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const {
180180 // only check against frustum
181− for(int i = 0; i < 6; ++i) {
181+ for(int i = 0; i < NUM_FRUSTUM_PLANES; ++i) {
182182 float distance = _planes[i].distance(point);
183183 if (distance < 0.0f) {
184184 return false;
@@ -189,7 +189,7 @@ bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const { · 4 unmodified lines
189189
190190 bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius) const {
191191 // only check against frustum
192− for(int i=0; i < 6; i++) {
192+ for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
193193 float distance = _planes[i].distance(center);
194194 if (distance < -radius) {
195195 // This is outside the regular frustum, so just return the value from checking the keyhole
@@ -201,7 +201,7 @@ bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius) · 5 unmodified lines
201201
202202 bool ViewFrustum::boxIntersectsFrustum(const AABox& box) const {
203203 // only check against frustum
204− for(int i=0; i < 6; i++) {
204+ for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
205205 const glm::vec3& normal = _planes[i].getNormal();
206206 // check distance to farthest box point
207207 if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
@@ -217,7 +217,7 @@ bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius) · 9 unmodified lines
217217 return true;
218218 }
219219 // check negative touches against frustum planes
220− for(int i=0; i < 6; i++) {
220+ for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
221221 if ( _planes[i].distance(center) < -radius) {
222222 return false;
223223 }
@@ -231,7 +231,7 @@ bool ViewFrustum::cubeIntersectsKeyhole(const AACube& cube) const { · 7 unmodified lines
231231 return true;
232232 }
233233 // check negative touches against frustum planes
234− for(int i=0; i < 6; i++) {
234+ for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
235235 const glm::vec3& normal = _planes[i].getNormal();
236236 if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
237237 return false;
@@ -246,7 +246,7 @@ bool ViewFrustum::boxIntersectsKeyhole(const AABox& box) const { · 8 unmodified lines
246246 return true;
247247 }
248248 // check negative touches against frustum planes
249− for(int i=0; i < 6; i++) {
249+ for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
250250 const glm::vec3& normal = _planes[i].getNormal();
251251 if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
252252 return false;
@@ -281,36 +281,36 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { · 28 unmodified lines
281281 testMatches(compareTo._focalLength, _focalLength);
282282
283283 if (!result && debug) {
284− qCDebug(octree, "ViewFrustum::matches()... result=%s", debug::valueOf(result));
285− qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
284+ qCDebug(shared, "ViewFrustum::matches()... result=%s", debug::valueOf(result));
285+ qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
286286 (testMatches(compareTo._position,_position) ? "MATCHES " : "NO MATCH"),
287287 (double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z,
288288 (double)_position.x, (double)_position.y, (double)_position.z);
289− qCDebug(octree, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f",
289+ qCDebug(shared, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f",
290290 (testMatches(compareTo._direction, _direction) ? "MATCHES " : "NO MATCH"),
291291 (double)compareTo._direction.x, (double)compareTo._direction.y, (double)compareTo._direction.z,
292292 (double)_direction.x, (double)_direction.y, (double)_direction.z );
293− qCDebug(octree, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f",
293+ qCDebug(shared, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f",
294294 (testMatches(compareTo._up, _up) ? "MATCHES " : "NO MATCH"),
295295 (double)compareTo._up.x, (double)compareTo._up.y, (double)compareTo._up.z,
296296 (double)_up.x, (double)_up.y, (double)_up.z );
297− qCDebug(octree, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f",
297+ qCDebug(shared, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f",
298298 (testMatches(compareTo._right, _right) ? "MATCHES " : "NO MATCH"),
299299 (double)compareTo._right.x, (double)compareTo._right.y, (double)compareTo._right.z,
300300 (double)_right.x, (double)_right.y, (double)_right.z );
301− qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
301+ qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
302302 (testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
303303 (double)compareTo._fieldOfView, (double)_fieldOfView);
304− qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
304+ qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
305305 (testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
306306 (double)compareTo._aspectRatio, (double)_aspectRatio);
307− qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f",
307+ qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f",
308308 (testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
309309 (double)compareTo._nearClip, (double)_nearClip);
310− qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f",
310+ qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f",
311311 (testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
312312 (double)compareTo._farClip, (double)_farClip);
313− qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f",
313+ qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f",
314314 (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"),
315315 (double)compareTo._focalLength, (double)_focalLength);
316316 }
@@ -342,34 +342,34 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const · 25 unmodified lines
342342
343343
344344 if (!result && debug) {
345− qCDebug(octree, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result));
346− qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
345+ qCDebug(shared, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result));
346+ qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
347347 (testMatches(compareTo._position,_position, POSITION_SIMILAR_ENOUGH) ?
348348 "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
349349 (double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z,
350350 (double)_position.x, (double)_position.y, (double)_position.z );
351351
352− qCDebug(octree, "%s -- positionDistance=%f",
352+ qCDebug(shared, "%s -- positionDistance=%f",
353353 (testMatches(0,positionDistance, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
354354 (double)positionDistance);
355355
356− qCDebug(octree, "%s -- angleOrientation=%f",
356+ qCDebug(shared, "%s -- angleOrientation=%f",
357357 (testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
358358 (double)angleOrientation);
359359
360− qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
360+ qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
361361 (testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
362362 (double)compareTo._fieldOfView, (double)_fieldOfView);
363− qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
363+ qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
364364 (testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
365365 (double)compareTo._aspectRatio, (double)_aspectRatio);
366− qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f",
366+ qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f",
367367 (testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
368368 (double)compareTo._nearClip, (double)_nearClip);
369− qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f",
369+ qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f",
370370 (testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
371371 (double)compareTo._farClip, (double)_farClip);
372− qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f",
372+ qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f",
373373 (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"),
374374 (double)compareTo._focalLength, (double)_focalLength);
375375 }
@@ -394,7 +394,7 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom · 18 unmodified lines
394394 // find the minimum and maximum z values, which will be our near and far clip distances
395395 nearValue = FLT_MAX;
396396 farValue = -FLT_MAX;
397− for (int i = 0; i < 8; i++) {
397+ for (int i = 0; i < NUM_FRUSTUM_CORNERS; i++) {
398398 nearValue = min(nearValue, -_corners[i].z);
399399 farValue = max(farValue, -_corners[i].z);
400400 }
@@ -427,17 +427,17 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom · 26 unmodified lines
427427 }
428428
429429 void ViewFrustum::printDebugDetails() const {
430− qCDebug(octree, "ViewFrustum::printDebugDetails()...");
431− qCDebug(octree, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z );
432− qCDebug(octree, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z );
433− qCDebug(octree, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z );
434− qCDebug(octree, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z );
435− qCDebug(octree, "_fieldOfView=%f", (double)_fieldOfView);
436− qCDebug(octree, "_aspectRatio=%f", (double)_aspectRatio);
437− qCDebug(octree, "_centerSphereRadius=%f", (double)_centerSphereRadius);
438− qCDebug(octree, "_nearClip=%f", (double)_nearClip);
439− qCDebug(octree, "_farClip=%f", (double)_farClip);
440− qCDebug(octree, "_focalLength=%f", (double)_focalLength);
430+ qCDebug(shared, "ViewFrustum::printDebugDetails()...");
431+ qCDebug(shared, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z );
432+ qCDebug(shared, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z );
433+ qCDebug(shared, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z );
434+ qCDebug(shared, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z );
435+ qCDebug(shared, "_fieldOfView=%f", (double)_fieldOfView);
436+ qCDebug(shared, "_aspectRatio=%f", (double)_aspectRatio);
437+ qCDebug(shared, "_centerSphereRadius=%f", (double)_centerSphereRadius);
438+ qCDebug(shared, "_nearClip=%f", (double)_nearClip);
439+ qCDebug(shared, "_farClip=%f", (double)_farClip);
440+ qCDebug(shared, "_focalLength=%f", (double)_focalLength);
441441 }
442442
443443 glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const {
@@ -536,7 +536,7 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT · 92 unmodified lines
536536 {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left
537537 };
538538
539−OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
539+CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
540540 const glm::vec3& bottomNearRight = box.getCorner();
541541 glm::vec3 topFarLeft = box.calcTopFarLeft();
542542
@@ -549,7 +549,7 @@ OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const · 6 unmodified lines
549549
550550 int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices
551551
552− OctreeProjectedPolygon projectedPolygon(vertexCount);
552+ CubeProjectedPolygon projectedPolygon(vertexCount);
553553
554554 bool pointInView = true;
555555 bool allPointsInView = false; // assume the best, but wait till we know we have a vertex
@@ -630,7 +630,7 @@ void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furth · 74 unmodified lines
630630 }
631631 }
632632
633−const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) {
633+const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) const {
634634 glm::vec3 normal = glm::normalize(_direction);
635635
636636 auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) {
@@ -662,51 +662,10 @@ void ViewFrustum::evalViewTransform(Transform& view) const { · 25 unmodified lines
662662 view.setRotation(getOrientation());
663663 }
664664
665−float ViewFrustum::calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale, int boundaryLevelAdjust) const {
666− float distanceToCamera = glm::length(bounds.calcCenter() - getPosition());
667− float largestDimension = bounds.getLargestDimension();
668−
669− const float maxScale = (float)TREE_SCALE;
670− float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
671−
672− static std::once_flag once;
673− static QMap<float, float> shouldRenderTable;
674− std::call_once(once, [&] {
675− float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
676− float scale = maxScale;
677− float factor = 1.0f;
678−
679− while (scale > SMALLEST_SCALE_IN_TABLE) {
680− scale /= 2.0f;
681− factor /= 2.0f;
682− shouldRenderTable[scale] = factor;
683− }
684− });
685−
686− float closestScale = maxScale;
687− float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
688− QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
689− if (lowerBound != shouldRenderTable.constEnd()) {
690− closestScale = lowerBound.key();
691− visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
692− }
693−
694− if (closestScale < largestDimension) {
695− visibleDistanceAtClosestScale *= 2.0f;
665+void ViewFrustum::invalidate() {
666+ // these setting should make nearly all intersection tests fail
667+ for (int i = 0; i < NUM_FRUSTUM_PLANES; ++i) {
668+ _planes[i].invalidate();
696669 }
697−
698− // FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return
699− // a floating point for objects that have small angular size to indicate that they may be rendered
700− // with lower preciscion
701− return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
702−}
703−
704−float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
705− return voxelSizeScale / powf(2, renderLevel);
706−}
707−
708−float ViewFrustum::getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) const {
709− const float maxScale = (float)TREE_SCALE;
710− float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
711− return atan(maxScale / visibleDistanceAtMaxScale);
670+ _centerSphereRadius = -1.0e6f; // -10^6 should be negative enough
712671 }
libraries/shared/src/ViewFrustum.hrenamed from libraries/octree/src/ViewFrustum.h+28−37
@@ -1,6 +1,6 @@
11 //
22 // ViewFrustum.h
3−// libraries/octree/src
3+// libraries/shared/src
44 //
55 // Created by Brad Hefta-Gaub on 04/11/13.
66 // Copyright 2013 High Fidelity, Inc.
@@ -17,21 +17,21 @@ · 10 unmodified lines
1717 #include <glm/glm.hpp>
1818 #include <glm/gtc/quaternion.hpp>
1919
20−#include <GLMHelpers.h>
21−#include <RegisteredMetaTypes.h>
22−
23−#include "Transform.h"
2420 #include "AABox.h"
2521 #include "AACube.h"
22+#include "CubeProjectedPolygon.h"
2623 #include "Plane.h"
27−#include "OctreeConstants.h"
28−#include "OctreeProjectedPolygon.h"
24+#include "RegisteredMetaTypes.h"
25+#include "Transform.h"
26+
27+const int NUM_FRUSTUM_CORNERS = 8;
28+const int NUM_FRUSTUM_PLANES = 6;
2929
3030 const float DEFAULT_CENTER_SPHERE_RADIUS = 3.0f;
3131 const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f;
3232 const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f;
3333 const float DEFAULT_NEAR_CLIP = 0.08f;
34−const float DEFAULT_FAR_CLIP = (float)HALF_TREE_SCALE;
34+const float DEFAULT_FAR_CLIP = 16384.0f;
3535
3636 // the "ViewFrustum" has a "keyhole" shape: a regular frustum for stuff that is "visible" with
3737 // a central sphere for stuff that is nearby (for physics simulation).
@@ -74,7 +74,7 @@ public: · 36 unmodified lines
7474 glm::vec3 bottomRight;
7575 // Get the corners depth units from frustum position, along frustum orientation
7676 };
77− const Corners getCorners(const float& depth);
77+ const Corners getCorners(const float& depth) const;
7878
7979 // getters for corners
8080 const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; }
@@ -123,7 +123,7 @@ public: · 42 unmodified lines
123123 void printDebugDetails() const;
124124
125125 glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
126− OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const;
126+ CubeProjectedPolygon getProjectedPolygon(const AACube& box) const;
127127 void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const;
128128
129129 float distanceToCamera(const glm::vec3& point) const;
@@ -131,44 +131,37 @@ public: · 1 unmodified line
131131 void evalProjectionMatrix(glm::mat4& proj) const;
132132 void evalViewTransform(Transform& view) const;
133133
134− /// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
135− /// level it returns 0.0f for things that are so small for the current settings that they could not be visible.
136− float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
137− int boundaryLevelAdjust = 0) const;
138−
139− float getAccuracyAngle(float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
140−
141134 enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
142135
143136 const ::Plane* getPlanes() const { return _planes; }
137+
138+ void invalidate(); // causes all reasonable intersection tests to fail
144139 private:
145− // camera location/orientation attributes
146− glm::vec3 _position; // the position in world-frame
147− glm::quat _orientation;
148140 glm::mat4 _view;
149−
150− // Lens attributes
151141 glm::mat4 _projection;
152142
153− // calculated for orientation
143+ ::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum
144+
145+ glm::vec3 _position; // position in world-frame
146+ glm::quat _orientation; // orientation in world-frame
147+
148+ // calculated from orientation
154149 glm::vec3 _direction = IDENTITY_FRONT;
155150 glm::vec3 _up = IDENTITY_UP;
156151 glm::vec3 _right = IDENTITY_RIGHT;
157152
153+ // calculated from projection
154+ glm::vec4 _corners[NUM_FRUSTUM_CORNERS];
155+ glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS];
158156 float _centerSphereRadius = DEFAULT_CENTER_SPHERE_RADIUS;
157+ float _width { 1.0f };
158+ float _height { 1.0f };
159+ float _aspectRatio { 1.0f };
160+ float _focalLength { 0.25f };
161+ float _fieldOfView { DEFAULT_FIELD_OF_VIEW_DEGREES };
159162
160− // Calculated values
161− glm::mat4 _inverseProjection;
162− float _width = 1.0f;
163− float _height = 1.0f;
164− float _aspectRatio = 1.0f;
165− float _nearClip = DEFAULT_NEAR_CLIP;
166− float _farClip = DEFAULT_FAR_CLIP;
167− float _focalLength = 0.25f;
168− float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
169− glm::vec4 _corners[8];
170− glm::vec3 _cornersWorld[8];
171− ::Plane _planes[6]; // plane normals point inside frustum
163+ float _nearClip { DEFAULT_NEAR_CLIP };
164+ float _farClip { DEFAULT_FAR_CLIP };
172165
173166 const char* debugPlaneName (int plane) const;
174167
@@ -177,6 +170,4 @@ private: · 2 unmodified lines
177170 };
178171 using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
179172
180−float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
181−
182173 #endif // hifi_ViewFrustum_h