From 60a72c666012f240bc0fdd8ad83f3b8e4697bba6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 29 Feb 2016 14:58:38 -0800 Subject: [PATCH 01/14] getViewFrustum() provides const pointer --- interface/src/Application.cpp | 11 +---------- interface/src/Application.h | 1 - libraries/octree/src/OctreeRenderer.h | 6 +++--- libraries/octree/src/ViewFrustum.cpp | 2 +- libraries/octree/src/ViewFrustum.h | 2 +- libraries/render-utils/src/LightStage.cpp | 3 +-- libraries/render-utils/src/LightStage.h | 2 +- libraries/render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render/src/render/CullTask.cpp | 2 +- libraries/shared/src/RenderArgs.h | 4 ++-- 10 files changed, 12 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c2a4088dcc..5c6f0ff7ab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1512,6 +1512,7 @@ void Application::paintGL() { auto lodManager = DependencyManager::get(); + _viewFrustum.calculate(); RenderArgs renderArgs(_gpuContext, getEntities(), getViewFrustum(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); @@ -3874,16 +3875,6 @@ glm::vec3 Application::getAvatarPosition() const { return getMyAvatar()->getPosition(); } -ViewFrustum* Application::getViewFrustum() { -#ifdef DEBUG - if (QThread::currentThread() == activeRenderingThread) { - // FIXME, figure out a better way to do this - //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; - } -#endif - return &_viewFrustum; -} - const ViewFrustum* Application::getViewFrustum() const { #ifdef DEBUG if (QThread::currentThread() == activeRenderingThread) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 2911d42b65..2dde8f5371 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -128,7 +128,6 @@ public: Camera* getCamera() { return &_myCamera; } const Camera* getCamera() const { return &_myCamera; } // Represents the current view frustum of the avatar. - ViewFrustum* getViewFrustum(); const ViewFrustum* getViewFrustum() const; // Represents the view frustum of the current rendering pass, // which might be different from the viewFrustum, i.e. shadowmap diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 198de7ceed..2058fa982a 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -51,8 +51,8 @@ public: /// render the content of the octree virtual void render(RenderArgs* renderArgs); - ViewFrustum* getViewFrustum() const { return _viewFrustum; } - void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; } + const ViewFrustum* getViewFrustum() const { return _viewFrustum; } + void setViewFrustum(const ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; } static bool renderOperation(OctreeElementPointer element, void* extraData); @@ -75,7 +75,7 @@ protected: OctreePointer _tree; bool _managedTree; - ViewFrustum* _viewFrustum; + const ViewFrustum* _viewFrustum; SimpleMovingAverage _elementsPerPacket; SimpleMovingAverage _entitiesPerPacket; diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 228e4c7d35..202d4ac773 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -630,7 +630,7 @@ void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furth } } -const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) { +const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) const { glm::vec3 normal = glm::normalize(_direction); auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) { diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 412d0f82f2..531956dd62 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -74,7 +74,7 @@ public: glm::vec3 bottomRight; // Get the corners depth units from frustum position, along frustum orientation }; - const Corners getCorners(const float& depth); + const Corners getCorners(const float& depth) const; // getters for corners const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; } diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 0f1f396471..5e28bea4a6 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -20,7 +20,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); } -void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth) { +void LightStage::Shadow::setKeylightFrustum(const ViewFrustum* viewFrustum, float nearDepth, float farDepth) { assert(nearDepth < farDepth); // Orient the keylight frustum @@ -43,7 +43,6 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near const Transform view{ _frustum->getView()}; const Transform viewInverse{ view.getInverseMatrix() }; - viewFrustum->calculate(); auto nearCorners = viewFrustum->getCorners(nearDepth); auto farCorners = viewFrustum->getCorners(farDepth); diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index f776d8d817..14af861e35 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -28,7 +28,7 @@ public: Shadow(model::LightPointer light); - void setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth); + void setKeylightFrustum(const ViewFrustum* viewFrustum, float nearDepth, float farDepth); const std::shared_ptr getFrustum() const { return _frustum; } diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index d9e0c06a90..e2e543cc3e 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -146,7 +146,7 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render } // Cache old render args - ViewFrustum* viewFrustum = args->_viewFrustum; + const ViewFrustum* viewFrustum = args->_viewFrustum; RenderArgs::RenderMode mode = args->_renderMode; auto nearClip = viewFrustum->getNearClip(); diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 56805e8f83..33096f9b5f 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -26,7 +26,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; - ViewFrustum* frustum = args->_viewFrustum; + const ViewFrustum* frustum = args->_viewFrustum; details._considered += (int)inItems.size(); diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 341553b743..a08b15886a 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -77,7 +77,7 @@ public: RenderArgs(std::shared_ptr context = nullptr, OctreeRenderer* renderer = nullptr, - ViewFrustum* viewFrustum = nullptr, + const ViewFrustum* viewFrustum = nullptr, float sizeScale = 1.0f, int boundaryLevelAdjust = 0, RenderMode renderMode = DEFAULT_RENDER_MODE, @@ -99,7 +99,7 @@ public: std::shared_ptr _blitFramebuffer = nullptr; std::shared_ptr _pipeline = nullptr; OctreeRenderer* _renderer = nullptr; - ViewFrustum* _viewFrustum = nullptr; + const ViewFrustum* _viewFrustum = nullptr; glm::ivec4 _viewport{ 0.0f, 0.0f, 1.0f, 1.0f }; glm::vec3 _boomOffset{ 0.0f, 0.0f, 1.0f }; float _sizeScale = 1.0f; From d97bd2bc52251f5bc95120173d33767ce6792737 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 29 Feb 2016 16:02:14 -0800 Subject: [PATCH 02/14] remove cruft --- libraries/octree/src/ViewFrustum.cpp | 85 ---------------------------- libraries/octree/src/ViewFrustum.h | 2 - 2 files changed, 87 deletions(-) diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 202d4ac773..d2701202a9 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -440,27 +440,6 @@ void ViewFrustum::printDebugDetails() const { qCDebug(octree, "_focalLength=%f", (double)_focalLength); } -glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const { - - glm::vec4 pointVec4 = glm::vec4(point, 1.0f); - glm::vec4 projectedPointVec4 = _ourModelViewProjectionMatrix * pointVec4; - pointInView = (projectedPointVec4.w > 0.0f); // math! If the w result is negative then the point is behind the viewer - - // what happens with w is 0??? - float x = projectedPointVec4.x / projectedPointVec4.w; - float y = projectedPointVec4.y / projectedPointVec4.w; - glm::vec2 projectedPoint(x,y); - - // if the point is out of view we also need to flip the signs of x and y - if (!pointInView) { - projectedPoint.x = -x; - projectedPoint.y = -y; - } - - return projectedPoint; -} - - const int MAX_POSSIBLE_COMBINATIONS = 43; const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERTEX_COUNT+1] = { @@ -536,70 +515,6 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left }; -OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { - const glm::vec3& bottomNearRight = box.getCorner(); - glm::vec3 topFarLeft = box.calcTopFarLeft(); - - int lookUp = ((_position.x < bottomNearRight.x) ) // 1 = right | compute 6-bit - + ((_position.x > topFarLeft.x ) << 1) // 2 = left | code to - + ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera - + ((_position.y > topFarLeft.y ) << 3) // 8 = top | with respect to - + ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining - + ((_position.z > topFarLeft.z ) << 5); // 32 = back/far | planes - - int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices - - OctreeProjectedPolygon projectedPolygon(vertexCount); - - bool pointInView = true; - bool allPointsInView = false; // assume the best, but wait till we know we have a vertex - bool anyPointsInView = false; // assume the worst! - if (vertexCount) { - allPointsInView = true; // assume the best! - for(int i = 0; i < vertexCount; i++) { - int vertexNum = hullVertexLookup[lookUp][i+1]; - glm::vec3 point = box.getVertex((BoxVertex)vertexNum); - glm::vec2 projectedPoint = projectPoint(point, pointInView); - allPointsInView = allPointsInView && pointInView; - anyPointsInView = anyPointsInView || pointInView; - projectedPolygon.setVertex(i, projectedPoint); - } - - /*** - // Now that we've got the polygon, if it extends beyond the clipping window, then let's clip it - // NOTE: This clipping does not improve our overall performance. It basically causes more polygons to - // end up in the same quad/half and so the polygon lists get longer, and that's more calls to polygon.occludes() - if ( (projectedPolygon.getMaxX() > PolygonClip::RIGHT_OF_CLIPPING_WINDOW ) || - (projectedPolygon.getMaxY() > PolygonClip::TOP_OF_CLIPPING_WINDOW ) || - (projectedPolygon.getMaxX() < PolygonClip::LEFT_OF_CLIPPING_WINDOW ) || - (projectedPolygon.getMaxY() < PolygonClip::BOTTOM_OF_CLIPPING_WINDOW) ) { - - CoverageRegion::_clippedPolygons++; - - glm::vec2* clippedVertices; - int clippedVertexCount; - PolygonClip::clipToScreen(projectedPolygon.getVertices(), vertexCount, clippedVertices, clippedVertexCount); - - // Now reset the vertices of our projectedPolygon object - projectedPolygon.setVertexCount(clippedVertexCount); - for(int i = 0; i < clippedVertexCount; i++) { - projectedPolygon.setVertex(i, clippedVertices[i]); - } - delete[] clippedVertices; - - lookUp += PROJECTION_CLIPPED; - } - ***/ - } - // set the distance from our camera position, to the closest vertex - float distance = glm::distance(getPosition(), box.calcCenter()); - projectedPolygon.setDistance(distance); - projectedPolygon.setAnyInView(anyPointsInView); - projectedPolygon.setAllInView(allPointsInView); - projectedPolygon.setProjectionType(lookUp); // remember the projection type - return projectedPolygon; -} - // Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for // squares and square-roots. Just compares. diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 531956dd62..62527a8a6d 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -122,8 +122,6 @@ public: void printDebugDetails() const; - glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const; - OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const; void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; float distanceToCamera(const glm::vec3& point) const; From 21fa2948391725a8447944ee41d16e5d6132860a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 29 Feb 2016 16:53:06 -0800 Subject: [PATCH 03/14] remove cruft --- libraries/octree/src/ViewFrustum.cpp | 49 ---------------------------- libraries/octree/src/ViewFrustum.h | 4 --- 2 files changed, 53 deletions(-) diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index d2701202a9..7e71155df3 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -268,55 +268,6 @@ bool testMatches(float lhs, float rhs, float epsilon = EPSILON) { return (fabs(lhs - rhs) <= epsilon); } -bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { - bool result = - testMatches(compareTo._position, _position) && - testMatches(compareTo._direction, _direction) && - testMatches(compareTo._up, _up) && - testMatches(compareTo._right, _right) && - testMatches(compareTo._fieldOfView, _fieldOfView) && - testMatches(compareTo._aspectRatio, _aspectRatio) && - testMatches(compareTo._nearClip, _nearClip) && - testMatches(compareTo._farClip, _farClip) && - testMatches(compareTo._focalLength, _focalLength); - - if (!result && debug) { - qCDebug(octree, "ViewFrustum::matches()... result=%s", debug::valueOf(result)); - qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f", - (testMatches(compareTo._position,_position) ? "MATCHES " : "NO MATCH"), - (double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z, - (double)_position.x, (double)_position.y, (double)_position.z); - qCDebug(octree, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f", - (testMatches(compareTo._direction, _direction) ? "MATCHES " : "NO MATCH"), - (double)compareTo._direction.x, (double)compareTo._direction.y, (double)compareTo._direction.z, - (double)_direction.x, (double)_direction.y, (double)_direction.z ); - qCDebug(octree, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f", - (testMatches(compareTo._up, _up) ? "MATCHES " : "NO MATCH"), - (double)compareTo._up.x, (double)compareTo._up.y, (double)compareTo._up.z, - (double)_up.x, (double)_up.y, (double)_up.z ); - qCDebug(octree, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f", - (testMatches(compareTo._right, _right) ? "MATCHES " : "NO MATCH"), - (double)compareTo._right.x, (double)compareTo._right.y, (double)compareTo._right.z, - (double)_right.x, (double)_right.y, (double)_right.z ); - qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f", - (testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"), - (double)compareTo._fieldOfView, (double)_fieldOfView); - qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f", - (testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"), - (double)compareTo._aspectRatio, (double)_aspectRatio); - qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f", - (testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"), - (double)compareTo._nearClip, (double)_nearClip); - qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f", - (testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"), - (double)compareTo._farClip, (double)_farClip); - qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f", - (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"), - (double)compareTo._focalLength, (double)_focalLength); - } - return result; -} - bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const { // Compute distance between the two positions diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 62527a8a6d..0fce67ac1b 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -107,10 +107,6 @@ public: bool cubeIntersectsKeyhole(const AACube& cube) const; bool boxIntersectsKeyhole(const AABox& box) const; - // some frustum comparisons - bool matches(const ViewFrustum& compareTo, bool debug = false) const; - bool matches(const ViewFrustum* compareTo, bool debug = false) const { return matches(*compareTo, debug); } - bool isVerySimilar(const ViewFrustum& compareTo, bool debug = false) const; bool isVerySimilar(const ViewFrustum* compareTo, bool debug = false) const { return isVerySimilar(*compareTo, debug); } From bcf2cc8074876a90766ff9a97fe2fac1edfdfce0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sat, 5 Mar 2016 10:38:23 -0800 Subject: [PATCH 04/14] use references not pointers for ViewFrustums also unravelling some spaghetti: (1) split Octree stuff out of ViewFrustum (2) moved ViewFrustum from octree to shared lib (3) removed some cruft --- .../src/octree/OctreeQueryNode.h | 6 +- .../src/octree/OctreeSendThread.cpp | 16 +- interface/src/Application.cpp | 29 +-- interface/src/Application.h | 9 +- interface/src/LODManager.cpp | 5 +- interface/src/Stars.cpp | 4 +- interface/src/avatar/Avatar.cpp | 27 ++- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/Head.cpp | 2 +- interface/src/avatar/Head.h | 8 +- interface/src/avatar/MyAvatar.cpp | 12 +- interface/src/avatar/MyAvatar.h | 2 +- interface/src/ui/overlays/Grid3DOverlay.cpp | 2 +- .../src/ui/overlays/LocalModelsOverlay.cpp | 4 +- .../src/RenderableTextEntityItem.cpp | 2 +- libraries/entities/src/EntityTreeElement.cpp | 12 +- libraries/octree/src/Octree.cpp | 60 +++--- libraries/octree/src/Octree.h | 31 ++- libraries/octree/src/OctreeElement.cpp | 7 +- libraries/octree/src/OctreeElement.h | 4 +- libraries/octree/src/OctreeHeadlessViewer.cpp | 4 +- libraries/octree/src/OctreeHeadlessViewer.h | 3 +- libraries/octree/src/OctreeQuery.cpp | 1 - libraries/octree/src/OctreeRenderer.cpp | 6 +- libraries/octree/src/OctreeRenderer.h | 8 +- libraries/octree/src/OctreeUtils.cpp | 71 +++++++ libraries/octree/src/OctreeUtils.h | 30 +++ .../src/AbstractViewStateInterface.h | 6 +- .../src/AmbientOcclusionEffect.cpp | 8 +- .../render-utils/src/AntialiasingEffect.cpp | 8 +- .../render-utils/src/DebugDeferredBuffer.cpp | 12 +- .../src/DeferredLightingEffect.cpp | 10 +- libraries/render-utils/src/HitEffect.cpp | 10 +- libraries/render-utils/src/LightStage.cpp | 8 +- libraries/render-utils/src/LightStage.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 22 +-- .../render-utils/src/RenderShadowTask.cpp | 11 +- libraries/render/src/render/CullTask.cpp | 36 ++-- .../render/src/render/DrawSceneOctree.cpp | 15 +- libraries/render/src/render/DrawStatus.cpp | 6 +- libraries/render/src/render/DrawTask.cpp | 2 +- libraries/{octree => shared}/src/Plane.cpp | 12 +- libraries/{octree => shared}/src/Plane.h | 9 +- libraries/shared/src/RenderArgs.h | 33 +++- .../{octree => shared}/src/ViewFrustum.cpp | 181 ++++++------------ .../{octree => shared}/src/ViewFrustum.h | 46 ++--- 46 files changed, 413 insertions(+), 391 deletions(-) create mode 100644 libraries/octree/src/OctreeUtils.cpp create mode 100644 libraries/octree/src/OctreeUtils.h rename libraries/{octree => shared}/src/Plane.cpp (93%) rename libraries/{octree => shared}/src/Plane.h (83%) rename libraries/{octree => shared}/src/ViewFrustum.cpp (75%) rename libraries/{octree => shared}/src/ViewFrustum.h (83%) diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 0ec876e674..22d04d81f6 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -44,7 +44,7 @@ public: bool packetIsDuplicate() const; bool shouldSuppressDuplicatePacket(); - + unsigned int getAvailable() const { return _octreePacket->bytesAvailableForWrite(); } int getMaxSearchLevel() const { return _maxSearchLevel; } void resetMaxSearchLevel() { _maxSearchLevel = 1; } @@ -56,8 +56,8 @@ public: OctreeElementBag elementBag; OctreeElementExtraEncodeData extraEncodeData; - ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; } - ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; } + const ViewFrustum& getCurrentViewFrustum() const { return _currentViewFrustum; } + const ViewFrustum& getLastKnownViewFrustum() const { return _lastKnownViewFrustum; } // These are not classic setters because they are calculating and maintaining state // which is set asynchronously through the network receive diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index ec812db8e8..7701cedd94 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -332,8 +332,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* _packetData.changeSettings(true, targetSize); // FIXME - eventually support only compressed packets - const ViewFrustum* lastViewFrustum = viewFrustumChanged ? &nodeData->getLastKnownViewFrustum() : NULL; - // If the current view frustum has changed OR we have nothing to send, then search against // the current view frustum for things to send. if (viewFrustumChanged || nodeData->elementBag.isEmpty()) { @@ -411,7 +409,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* quint64 lockWaitEnd = usecTimestampNow(); lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart); quint64 encodeStart = usecTimestampNow(); - + OctreeElementPointer subTree = nodeData->elementBag.extract(); if (!subTree) { return; @@ -420,18 +418,22 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* float octreeSizeScale = nodeData->getOctreeSizeScale(); int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust(); - int boundaryLevelAdjust = boundaryLevelAdjustClient + + int boundaryLevelAdjust = boundaryLevelAdjustClient + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); - EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), - WANT_EXISTS_BITS, DONT_CHOP, viewFrustumChanged, lastViewFrustum, + EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP, + viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale, nodeData->getLastTimeBagEmpty(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(), &nodeData->extraEncodeData); + params.viewFrustum = nodeData->getCurrentViewFrustum(); + if (viewFrustumChanged) { + params.lastViewFrustum = nodeData->getLastKnownViewFrustum(); + } // Our trackSend() function is implemented by the server subclass, and will be called back - // during the encodeTreeBitstream() as new entities/data elements are sent + // during the encodeTreeBitstream() as new entities/data elements are sent params.trackSend = [this, node](const QUuid& dataID, quint64 dataEdited) { _myServer->trackSend(dataID, dataEdited, node->getUUID()); }; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5c6f0ff7ab..994bb89556 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1513,9 +1513,10 @@ void Application::paintGL() { _viewFrustum.calculate(); - RenderArgs renderArgs(_gpuContext, getEntities(), getViewFrustum(), lodManager->getOctreeSizeScale(), + RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); + renderArgs.setViewFrustum(getViewFrustum()); PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -1682,7 +1683,7 @@ void Application::paintGL() { renderArgs._context->enableStereo(true); mat4 eyeOffsets[2]; mat4 eyeProjections[2]; - auto baseProjection = renderArgs._viewFrustum->getProjection(); + auto baseProjection = renderArgs.getViewFrustum().getProjection(); auto hmdInterface = DependencyManager::get(); float IPDScale = hmdInterface->getIPDScale(); mat4 headPose = displayPlugin->getHeadPose(); @@ -3862,7 +3863,7 @@ PickRay Application::computePickRay(float x, float y) const { getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction); } else { pickPoint /= getCanvasSize(); - getViewFrustum()->computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction); + getViewFrustum().computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction); } return result; } @@ -3875,34 +3876,24 @@ glm::vec3 Application::getAvatarPosition() const { return getMyAvatar()->getPosition(); } -const ViewFrustum* Application::getViewFrustum() const { +const ViewFrustum& Application::getViewFrustum() const { #ifdef DEBUG if (QThread::currentThread() == activeRenderingThread) { // FIXME, figure out a better way to do this //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; } #endif - return &_viewFrustum; + return _viewFrustum; } -ViewFrustum* Application::getDisplayViewFrustum() { +const ViewFrustum& Application::getDisplayViewFrustum() const { #ifdef DEBUG if (QThread::currentThread() != activeRenderingThread) { // FIXME, figure out a better way to do this // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; } #endif - return &_displayViewFrustum; -} - -const ViewFrustum* Application::getDisplayViewFrustum() const { -#ifdef DEBUG - if (QThread::currentThread() != activeRenderingThread) { - // FIXME, figure out a better way to do this - // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; - } -#endif - return &_displayViewFrustum; + return _displayViewFrustum; } // WorldBox Render Data & rendering functions @@ -3967,7 +3958,7 @@ namespace render { auto skybox = skyStage->getSkybox(); if (skybox) { PerformanceTimer perfTimer("skybox"); - skybox->render(batch, *(args->_viewFrustum)); + skybox->render(batch, args->getViewFrustum()); break; } } @@ -4079,7 +4070,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se { PerformanceTimer perfTimer("EngineRun"); - renderArgs->_viewFrustum = getDisplayViewFrustum(); + renderArgs->setViewFrustum(getDisplayViewFrustum()); _renderEngine->getRenderContext()->args = renderArgs; // Before the deferred pass, let's try to use the render engine diff --git a/interface/src/Application.h b/interface/src/Application.h index 2dde8f5371..3f26f7bc38 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -128,13 +128,12 @@ public: Camera* getCamera() { return &_myCamera; } const Camera* getCamera() const { return &_myCamera; } // Represents the current view frustum of the avatar. - const ViewFrustum* getViewFrustum() const; + const ViewFrustum& getViewFrustum() const; // Represents the view frustum of the current rendering pass, // which might be different from the viewFrustum, i.e. shadowmap // passes, mirror window passes, etc - ViewFrustum* getDisplayViewFrustum(); - const ViewFrustum* getDisplayViewFrustum() const; - ViewFrustum* getShadowViewFrustum() override { return &_shadowViewFrustum; } + const ViewFrustum& getDisplayViewFrustum() const; + const ViewFrustum& getShadowViewFrustum() override { return _shadowViewFrustum; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } EntityTreeRenderer* getEntities() const { return DependencyManager::get().data(); } QUndoStack* getUndoStack() { return &_undoStack; } @@ -168,7 +167,7 @@ public: virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override; - virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); } + virtual const ViewFrustum& getCurrentViewFrustum() override { return getDisplayViewFrustum(); } virtual QThread* getMainThread() override { return thread(); } virtual PickRay computePickRay(float x, float y) const override; virtual glm::vec3 getAvatarPosition() const override; diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 64b506059c..bf756a55a5 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include "Application.h" @@ -216,7 +217,7 @@ QString LODManager::getLODFeedbackText() { bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { // FIXME - eventually we want to use the render accuracy as an indicator for the level of detail // to use in rendering. - float renderAccuracy = args->_viewFrustum->calculateRenderAccuracy(bounds, args->_sizeScale, args->_boundaryLevelAdjust); + float renderAccuracy = calculateRenderAccuracy(args->getViewFrustum().getPosition(), bounds, args->_sizeScale, args->_boundaryLevelAdjust); return (renderAccuracy > 0.0f); }; @@ -228,7 +229,6 @@ void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; } - void LODManager::loadSettings() { setDesktopLODDecreaseFPS(desktopLODDecreaseFPS.get()); setHMDLODDecreaseFPS(hmdLODDecreaseFPS.get()); @@ -239,4 +239,3 @@ void LODManager::saveSettings() { hmdLODDecreaseFPS.set(getHMDLODDecreaseFPS()); } - diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index 7e2deef494..9510710eb3 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -194,8 +194,8 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { gpu::Batch& batch = *renderArgs->_batch; batch.setViewTransform(Transform()); - batch.setProjectionTransform(renderArgs->_viewFrustum->getProjection()); - batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->_viewFrustum->getOrientation()) * + batch.setProjectionTransform(renderArgs->getViewFrustum().getProjection()); + batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->getViewFrustum().getOrientation()) * quat(vec3(TILT, 0, 0)))); batch.setResourceTexture(0, textureCache->getWhiteTexture()); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2cacb81ce4..f753309ffc 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -171,7 +172,8 @@ void Avatar::simulate(float deltaTime) { // update the shouldAnimate flag to match whether or not we will render the avatar. const float MINIMUM_VISIBILITY_FOR_ON = 0.4f; const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f; - float visibility = qApp->getViewFrustum()->calculateRenderAccuracy(getBounds(), DependencyManager::get()->getOctreeSizeScale()); + float visibility = calculateRenderAccuracy(qApp->getViewFrustum().getPosition(), + getBounds(), DependencyManager::get()->getOctreeSizeScale()); if (!_shouldAnimate) { if (visibility > MINIMUM_VISIBILITY_FOR_ON) { _shouldAnimate = true; @@ -381,17 +383,13 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } } - // simple frustum check - float boundingRadius = getBoundingRadius(); - ViewFrustum* frustum = nullptr; - if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) { - frustum = qApp->getShadowViewFrustum(); - } else { - frustum = qApp->getDisplayViewFrustum(); - } - - if (!frustum->sphereIntersectsFrustum(getPosition(), boundingRadius)) { - return; + { // simple frustum check + const ViewFrustum& frustum = renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE ? + qApp->getShadowViewFrustum() : + qApp->getDisplayViewFrustum(); + if (!frustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())) { + return; + } } glm::vec3 toTarget = cameraPosition - getPosition(); @@ -413,7 +411,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { : GLOW_FROM_AVERAGE_LOUDNESS; // render body - renderBody(renderArgs, frustum, glowLevel); + renderBody(renderArgs, glowLevel); if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) { // add local lights @@ -502,9 +500,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { auto cameraMode = qApp->getCamera()->getMode(); if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) { - auto& frustum = *renderArgs->_viewFrustum; + auto frustum = renderArgs->getViewFrustum(); auto textPosition = getDisplayNamePosition(); - if (frustum.pointIntersectsFrustum(textPosition)) { renderDisplayName(batch, frustum, textPosition); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index cb35fbb5eb..265b529b8a 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -232,7 +232,7 @@ protected: Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const; void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const; - virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f); + virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f); virtual bool shouldRenderHead(const RenderArgs* renderArgs) const; virtual void fixupModelsInScene(); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b7247334fc..8a58e5d740 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -316,7 +316,7 @@ void Head::relaxLean(float deltaTime) { _deltaLeanForward *= relaxationFactor; } -void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum) { +void Head::render(RenderArgs* renderArgs, float alpha) { } void Head::renderLookAts(RenderArgs* renderArgs) { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index d0bd4fdb77..4c0a516ecc 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -28,11 +28,13 @@ class Avatar; class Head : public HeadData { public: explicit Head(Avatar* owningAvatar); - + + Head(Avatar* owningAvatar); + void init(); void reset(); void simulate(float deltaTime, bool isMine, bool billboard = false); - void render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum); + void render(RenderArgs* renderArgs, float alpha); void setScale(float scale); void setPosition(glm::vec3 position) { _position = position; } void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; } @@ -44,7 +46,7 @@ public: /// \return orientationBase+Delta glm::quat getFinalOrientationInLocalFrame() const; - + /// \return orientationBody * (orientationBase+Delta) glm::quat getFinalOrientationInWorldFrame() const; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index bad60643ec..2208e827a0 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -546,7 +546,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { head->setDeltaYaw(estimatedRotation.y); head->setDeltaRoll(estimatedRotation.z); } else { - float magnifyFieldOfView = qApp->getViewFrustum()->getFieldOfView() / _realWorldFieldOfView.get(); + float magnifyFieldOfView = qApp->getViewFrustum().getFieldOfView() / _realWorldFieldOfView.get(); head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView); head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView); head->setDeltaRoll(estimatedRotation.z); @@ -936,8 +936,8 @@ void MyAvatar::updateLookAtTargetAvatar() { glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); auto humanSystem = qApp->getViewFrustum(); - glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal); - glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal); + glm::vec3 humanLeftEye = humanSystem.getPosition() + (humanSystem.getOrientation() * leftEyeHeadLocal); + glm::vec3 humanRightEye = humanSystem.getPosition() + (humanSystem.getOrientation() * rightEyeHeadLocal); auto hmdInterface = DependencyManager::get(); float ipdScale = hmdInterface->getIPDScale(); @@ -951,7 +951,7 @@ void MyAvatar::updateLookAtTargetAvatar() { } // And now we can finally add that offset to the camera. - glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset; + glm::vec3 corrected = qApp->getViewFrustum().getPosition() + gazeOffset; avatar->getHead()->setCorrectedLookAtPosition(corrected); @@ -1259,7 +1259,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved); } -void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) { +void MyAvatar::renderBody(RenderArgs* renderArgs, float glowLevel) { if (!_skeletonModel->isRenderable()) { return; // wait until all models are loaded @@ -1269,7 +1269,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl // Render head so long as the camera isn't inside it if (shouldRenderHead(renderArgs)) { - getHead()->render(renderArgs, 1.0f, renderFrustum); + getHead()->render(renderArgs, 1.0f); } // This is drawing the lookat vectors from our avatar to wherever we're looking. diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fee1a9add3..d6f209a2eb 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -306,7 +306,7 @@ private: void simulate(float deltaTime); void updateFromTrackers(float deltaTime); virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override; - virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f) override; + virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f) override; virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override; void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); } bool getShouldRenderLocally() const { return _shouldRender; } diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 39106ad61e..edc27e35f2 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -65,7 +65,7 @@ void Grid3DOverlay::render(RenderArgs* args) { // Get the camera position rounded to the nearest major grid line // This grid is for UI and should lie on worldlines auto cameraPosition = - (float)_majorGridEvery * glm::round(args->_viewFrustum->getPosition() / (float)_majorGridEvery); + (float)_majorGridEvery * glm::round(args->getViewFrustum().getPosition() / (float)_majorGridEvery); position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z); } diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index 38e11562da..ba82ba780a 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -37,10 +37,10 @@ void LocalModelsOverlay::render(RenderArgs* args) { auto batch = args ->_batch; Transform transform = Transform(); - transform.setTranslation(args->_viewFrustum->getPosition() + getPosition()); + transform.setTranslation(args->getViewFrustum().getPosition() + getPosition()); batch->setViewTransform(transform); _entityTreeRenderer->render(args); - transform.setTranslation(args->_viewFrustum->getPosition()); + transform.setTranslation(args->getViewFrustum().getPosition()); batch->setViewTransform(transform); } } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 5cf31c15e0..6773a906fe 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -51,7 +51,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) { } if (getFaceCamera()) { //rotate about vertical to face the camera - glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition(); + glm::vec3 dPosition = args->getViewFrustum().getPosition() - getPosition(); // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 8270dc7e69..88227416d3 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "EntitiesLogging.h" #include "EntityItemProperties.h" @@ -297,7 +298,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID()); } - if (includeThisEntity && params.viewFrustum) { + if (includeThisEntity) { // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of // simulation changing what's visible. consider the case where the entity contains an angular velocity @@ -305,7 +306,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData // frustum culling on rendering. bool success; AACube entityCube = entity->getQueryAACube(success); - if (!success || !params.viewFrustum->cubeIntersectsKeyhole(entityCube)) { + if (!success || !params.viewFrustum.cubeIntersectsKeyhole(entityCube)) { includeThisEntity = false; // out of view, don't include it } else { // Check the size of the entity, it's possible that a "too small to see" entity is included in a @@ -322,9 +323,10 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData // AABox. If this happens, fall back to the queryAACube. entityBounds = AABox(entityCube); } - auto renderAccuracy = params.viewFrustum->calculateRenderAccuracy(entityBounds, - params.octreeElementSizeScale, - params.boundaryLevelAdjust); + auto renderAccuracy = calculateRenderAccuracy(params.viewFrustum.getPosition(), + entityBounds, + params.octreeElementSizeScale, + params.boundaryLevelAdjust); if (renderAccuracy <= 0.0f) { includeThisEntity = false; // too small, don't include it diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 051e4f8791..39be760944 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -40,12 +41,12 @@ #include #include #include -#include +#include #include "OctreeConstants.h" #include "OctreeElementBag.h" #include "Octree.h" -#include "ViewFrustum.h" +#include "OctreeUtils.h" #include "OctreeLogging.h" @@ -898,7 +899,7 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element, } // If we're at a element that is out of view, then we can return, because no nodes below us will be in view! - if (params.viewFrustum && !element->isInView(*params.viewFrustum)) { + if (!params.recurseEverything && !element->isInView(params.viewFrustum)) { params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW; return bytesWritten; } @@ -1014,15 +1015,12 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, } ViewFrustum::intersection nodeLocationThisView = ViewFrustum::INSIDE; // assume we're inside - - // caller can pass NULL as viewFrustum if they want everything - if (params.viewFrustum) { - float distance = element->distanceToCamera(*params.viewFrustum); + if (!params.recurseEverything) { float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust, params.octreeElementSizeScale); // If we're too far away for our render level, then just return - if (distance >= boundaryDistance) { + if (element->distanceToCamera(params.viewFrustum) >= boundaryDistance) { if (params.stats) { params.stats->skippedDistance(element); } @@ -1034,7 +1032,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // if we are INSIDE, INTERSECT, or OUTSIDE if (parentLocationThisView != ViewFrustum::INSIDE) { assert(parentLocationThisView != ViewFrustum::OUTSIDE); // we shouldn't be here if our parent was OUTSIDE! - nodeLocationThisView = element->computeViewIntersection(*params.viewFrustum); + nodeLocationThisView = element->computeViewIntersection(params.viewFrustum); } // 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, // because we don't send nodes from the previously know in view frustum. bool wasInView = false; - if (params.deltaViewFrustum && params.lastViewFrustum) { - ViewFrustum::intersection location = element->computeViewIntersection(*params.lastViewFrustum); + if (params.deltaView) { + ViewFrustum::intersection location = element->computeViewIntersection(params.lastViewFrustum); // If we're a leaf, then either intersect or inside is considered "formerly in view" if (element->isLeaf()) { @@ -1067,10 +1065,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // to it, and so therefore it may now be visible from an LOD perspective, in which case we don't consider it // as "was in view"... if (wasInView) { - float distance = element->distanceToCamera(*params.lastViewFrustum); float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust, params.octreeElementSizeScale); - if (distance >= boundaryDistance) { + if (element->distanceToCamera(params.lastViewFrustum) >= boundaryDistance) { // This would have been invisible... but now should be visible (we wouldn't be here otherwise)... wasInView = false; } @@ -1078,9 +1075,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, } // If we were previously in the view, then we normally will return out of here and stop recursing. But - // if we're in deltaViewFrustum mode, and this element has changed since it was last sent, then we do + // if we're in deltaView mode, and this element has changed since it was last sent, then we do // need to send it. - if (wasInView && !(params.deltaViewFrustum && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) { + if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) { if (params.stats) { params.stats->skippedWasInView(element); } @@ -1090,7 +1087,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed, // then we can also bail early and save bits - if (!params.forceSendScene && !params.deltaViewFrustum && + if (!params.forceSendScene && !params.deltaView && !element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) { if (params.stats) { params.stats->skippedNoChange(element); @@ -1179,10 +1176,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, int originalIndex = indexOfChildren[i]; bool childIsInView = (childElement && - ( !params.viewFrustum || // no view frustum was given, everything is assumed in view - (nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are + (params.recurseEverything || + (nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are (nodeLocationThisView == ViewFrustum::INTERSECT && - childElement->isInView(*params.viewFrustum)) // the parent intersects and the child is in view + childElement->isInView(params.viewFrustum)) // the parent intersects and the child is in view )); if (!childIsInView) { @@ -1192,12 +1189,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, } } else { // Before we consider this further, let's see if it's in our LOD scope... - float distance = distancesToChildren[i]; - float boundaryDistance = !params.viewFrustum ? 1 : - boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust, + float boundaryDistance = params.recurseEverything ? 1 : + boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust, params.octreeElementSizeScale); - if (!(distance < boundaryDistance)) { + if (!(distancesToChildren[i] < boundaryDistance)) { // don't need to check childElement here, because we can't get here with no childElement if (params.stats) { params.stats->skippedDistance(childElement); @@ -1215,10 +1211,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, bool childIsOccluded = false; // assume it's not occluded - bool shouldRender = !params.viewFrustum - ? true - : childElement->calculateShouldRender(params.viewFrustum, - params.octreeElementSizeScale, params.boundaryLevelAdjust); + bool shouldRender = params.recurseEverything || + childElement->calculateShouldRender(params.viewFrustum, + params.octreeElementSizeScale, params.boundaryLevelAdjust); // track some stats if (params.stats) { @@ -1236,8 +1231,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, if (shouldRender && !childIsOccluded) { bool childWasInView = false; - if (childElement && params.deltaViewFrustum && params.lastViewFrustum) { - ViewFrustum::intersection location = childElement->computeViewIntersection(*params.lastViewFrustum); + if (childElement && params.deltaView) { + ViewFrustum::intersection location = childElement->computeViewIntersection(params.lastViewFrustum); // If we're a leaf, then either intersect or inside is considered "formerly in view" if (childElement->isLeaf()) { @@ -1251,7 +1246,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // Or if we were previously in the view, but this element has changed since it was last sent, then we do // need to send it. if (!childWasInView || - (params.deltaViewFrustum && + (params.deltaView && childElement->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){ childrenDataBits += (1 << (7 - originalIndex)); @@ -1456,7 +1451,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, // called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep // recursing, by returning TRUE in recurseChildrenWithData(). - if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenDataBits, originalIndex)) { + if (params.recurseEverything || recurseChildrenWithData() || !oneAtBit(childrenDataBits, originalIndex)) { // Allow the datatype a chance to determine if it really wants to recurse this tree. Usually this // 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) bool lastPacketWritten = false; while (OctreeElementPointer subTree = elementBag.extract()) { - EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, NO_EXISTS_BITS); + EncodeBitstreamParams params(INT_MAX, NO_EXISTS_BITS); + params.recurseEverything = true; withReadLock([&] { params.extraEncodeData = &extraEncodeData; bytesWritten = encodeTreeBitstream(subTree, &packetData, elementBag, params); diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 81a721c54e..456b086341 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -20,9 +20,9 @@ #include #include +#include #include "JurisdictionMap.h" -#include "ViewFrustum.h" #include "OctreeElement.h" #include "OctreeElementBag.h" #include "OctreePacketData.h" @@ -61,22 +61,22 @@ const int LOW_RES_MOVING_ADJUST = 1; const quint64 IGNORE_LAST_SENT = 0; #define IGNORE_SCENE_STATS NULL -#define IGNORE_VIEW_FRUSTUM NULL #define IGNORE_COVERAGE_MAP NULL #define IGNORE_JURISDICTION_MAP NULL class EncodeBitstreamParams { public: + ViewFrustum viewFrustum; + ViewFrustum lastViewFrustum; + quint64 lastViewFrustumSent; int maxEncodeLevel; int maxLevelReached; - const ViewFrustum* viewFrustum; bool includeExistsBits; int chopLevels; - bool deltaViewFrustum; - const ViewFrustum* lastViewFrustum; + bool deltaView; + bool recurseEverything { false }; int boundaryLevelAdjust; float octreeElementSizeScale; - quint64 lastViewFrustumSent; bool forceSendScene; OctreeSceneStats* stats; JurisdictionMap* jurisdictionMap; @@ -99,11 +99,9 @@ public: EncodeBitstreamParams( int maxEncodeLevel = INT_MAX, - const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM, bool includeExistsBits = WANT_EXISTS_BITS, int chopLevels = 0, - bool deltaViewFrustum = false, - const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM, + bool useDeltaView = false, int boundaryLevelAdjust = NO_BOUNDARY_ADJUST, float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE, quint64 lastViewFrustumSent = IGNORE_LAST_SENT, @@ -111,22 +109,24 @@ public: OctreeSceneStats* stats = IGNORE_SCENE_STATS, JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP, OctreeElementExtraEncodeData* extraEncodeData = NULL) : + viewFrustum(), + lastViewFrustum(), + lastViewFrustumSent(lastViewFrustumSent), maxEncodeLevel(maxEncodeLevel), maxLevelReached(0), - viewFrustum(viewFrustum), includeExistsBits(includeExistsBits), chopLevels(chopLevels), - deltaViewFrustum(deltaViewFrustum), - lastViewFrustum(lastViewFrustum), + deltaView(useDeltaView), boundaryLevelAdjust(boundaryLevelAdjust), octreeElementSizeScale(octreeElementSizeScale), - lastViewFrustumSent(lastViewFrustumSent), forceSendScene(forceSendScene), stats(stats), jurisdictionMap(jurisdictionMap), extraEncodeData(extraEncodeData), stopReason(UNKNOWN) - {} + { + lastViewFrustum.invalidate(); + } void displayStopReason() { printf("StopReason: "); @@ -341,7 +341,7 @@ public: bool getIsClient() const { return !_isServer; } /// Is this a client based tree. Allows guards for certain operations void setIsClient(bool isClient) { _isServer = !isClient; } - + virtual void dumpTree() { } virtual void pruneTree() { } @@ -352,7 +352,6 @@ public: virtual quint64 getAverageCreateTime() const { return 0; } virtual quint64 getAverageLoggingTime() const { return 0; } - signals: void importSize(float x, float y, float z); void importProgress(int progress); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index db0948b8b6..48f6e08303 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -22,10 +22,11 @@ #include "AACube.h" #include "OctalCode.h" +#include "Octree.h" #include "OctreeConstants.h" #include "OctreeElement.h" -#include "Octree.h" #include "OctreeLogging.h" +#include "OctreeUtils.h" #include "SharedUtil.h" AtomicUIntStat OctreeElement::_octreeMemoryUsage { 0 }; @@ -471,11 +472,11 @@ ViewFrustum::intersection OctreeElement::computeViewIntersection(const ViewFrust // Since, if we know the camera position and orientation, we can know which of the corners is the "furthest" // corner. We can use we can use this corner as our "voxel position" to do our distance calculations off of. // By doing this, we don't need to test each child voxel's position vs the LOD boundary -bool OctreeElement::calculateShouldRender(const ViewFrustum* viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const { +bool OctreeElement::calculateShouldRender(const ViewFrustum& viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const { bool shouldRender = false; if (hasContent()) { - float furthestDistance = furthestDistanceToCamera(*viewFrustum); + float furthestDistance = furthestDistanceToCamera(viewFrustum); float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust, voxelScaleSize); bool inChildBoundary = (furthestDistance <= childBoundary); if (hasDetailedContent() && inChildBoundary) { diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 398f1827b7..61211a40d8 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -21,9 +21,9 @@ #include #include +#include #include "AACube.h" -#include "ViewFrustum.h" #include "OctreeConstants.h" using AtomicUIntStat = std::atomic; @@ -139,7 +139,7 @@ public: float distanceToCamera(const ViewFrustum& viewFrustum) const; float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const; - bool calculateShouldRender(const ViewFrustum* viewFrustum, + bool calculateShouldRender(const ViewFrustum& viewFrustum, float voxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const; // points are assumed to be in Voxel Coordinates (not TREE_SCALE'd) diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index 33c12b1fe5..4a0a76cd02 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -14,14 +14,12 @@ #include "OctreeLogging.h" #include "OctreeHeadlessViewer.h" -OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer() -{ +OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer() { _viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); } void OctreeHeadlessViewer::init() { OctreeRenderer::init(); - setViewFrustum(&_viewFrustum); } void OctreeHeadlessViewer::queryOctree() { diff --git a/libraries/octree/src/OctreeHeadlessViewer.h b/libraries/octree/src/OctreeHeadlessViewer.h index 780b68b848..b43dceeba6 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.h +++ b/libraries/octree/src/OctreeHeadlessViewer.h @@ -14,6 +14,7 @@ #include #include +#include #include "JurisdictionListener.h" #include "Octree.h" @@ -22,7 +23,6 @@ #include "OctreeRenderer.h" #include "OctreeSceneStats.h" #include "Octree.h" -#include "ViewFrustum.h" // Generic client side Octree renderer class. class OctreeHeadlessViewer : public OctreeRenderer { @@ -66,7 +66,6 @@ public slots: unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); } private: - ViewFrustum _viewFrustum; JurisdictionListener* _jurisdictionListener = nullptr; OctreeQuery _octreeQuery; diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index a69d88c693..60e4b5fb3a 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -120,4 +120,3 @@ glm::vec3 OctreeQuery::calculateCameraDirection() const { glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FRONT, 0.0f)); return direction; } - diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index bcf7c301c7..c001bdfc35 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -23,7 +23,7 @@ OctreeRenderer::OctreeRenderer() : _tree(NULL), _managedTree(false), - _viewFrustum(NULL) + _viewFrustum() { } @@ -201,9 +201,9 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer bool OctreeRenderer::renderOperation(OctreeElementPointer element, void* extraData) { RenderArgs* args = static_cast(extraData); - if (element->isInView(*args->_viewFrustum)) { + if (element->isInView(args->getViewFrustum())) { if (element->hasContent()) { - if (element->calculateShouldRender(args->_viewFrustum, args->_sizeScale, args->_boundaryLevelAdjust)) { + if (element->calculateShouldRender(args->getViewFrustum(), args->_sizeScale, args->_boundaryLevelAdjust)) { args->_renderer->renderElement(element, args); } else { return false; // if we shouldn't render, then we also should stop recursing. diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 2058fa982a..cd4ddc4801 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -20,10 +20,10 @@ #include #include #include +#include #include "Octree.h" #include "OctreePacketData.h" -#include "ViewFrustum.h" class OctreeRenderer; @@ -51,8 +51,8 @@ public: /// render the content of the octree virtual void render(RenderArgs* renderArgs); - const ViewFrustum* getViewFrustum() const { return _viewFrustum; } - void setViewFrustum(const ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; } + const ViewFrustum& getViewFrustum() const { return _viewFrustum; } + void setViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustum = viewFrustum; } static bool renderOperation(OctreeElementPointer element, void* extraData); @@ -75,7 +75,7 @@ protected: OctreePointer _tree; bool _managedTree; - const ViewFrustum* _viewFrustum; + ViewFrustum _viewFrustum; SimpleMovingAverage _elementsPerPacket; SimpleMovingAverage _entitiesPerPacket; diff --git a/libraries/octree/src/OctreeUtils.cpp b/libraries/octree/src/OctreeUtils.cpp new file mode 100644 index 0000000000..c55016d8e2 --- /dev/null +++ b/libraries/octree/src/OctreeUtils.cpp @@ -0,0 +1,71 @@ +// +// OctreeUtils.cpp +// libraries/octree/src +// +// Created by Andrew Meadows 2016.03.04 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "OctreeUtils.h" + +#include + +#include + +#include + + +float calculateRenderAccuracy(const glm::vec3& position, + const AABox& bounds, + float octreeSizeScale, + int boundaryLevelAdjust) { + float largestDimension = bounds.getLargestDimension(); + + const float maxScale = (float)TREE_SCALE; + float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; + + static std::once_flag once; + static QMap shouldRenderTable; + std::call_once(once, [&] { + float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small + float scale = maxScale; + float factor = 1.0f; + + while (scale > SMALLEST_SCALE_IN_TABLE) { + scale /= 2.0f; + factor /= 2.0f; + shouldRenderTable[scale] = factor; + } + }); + + float closestScale = maxScale; + float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale; + QMap::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension); + if (lowerBound != shouldRenderTable.constEnd()) { + closestScale = lowerBound.key(); + visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value(); + } + + if (closestScale < largestDimension) { + visibleDistanceAtClosestScale *= 2.0f; + } + + // FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return + // a floating point for objects that have small angular size to indicate that they may be rendered + // with lower preciscion + float distanceToCamera = glm::length(bounds.calcCenter() - position); + return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f; +} + +float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) { + return voxelSizeScale / powf(2.0f, renderLevel); +} + +float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) { + const float maxScale = (float)TREE_SCALE; + float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; + return atan(maxScale / visibleDistanceAtMaxScale); +} diff --git a/libraries/octree/src/OctreeUtils.h b/libraries/octree/src/OctreeUtils.h new file mode 100644 index 0000000000..279eb51509 --- /dev/null +++ b/libraries/octree/src/OctreeUtils.h @@ -0,0 +1,30 @@ +// +// OctreeUtils.h +// libraries/octree/src +// +// Created by Andrew Meadows 2016.03.04 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_OctreeUtils_h +#define hifi_OctreeUtils_h + +#include "OctreeConstants.h" + +class AABox; + +/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple +/// level it returns 0.0f for things that are so small for the current settings that they could not be visible. +float calculateRenderAccuracy(const glm::vec3& position, + const AABox& bounds, + float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, + int boundaryLevelAdjust = 0); + +float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale); + +float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust); + +#endif // hifi_OctreeUtils_h diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 7c7c263562..c068baf453 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -29,13 +29,13 @@ class PickRay; class AbstractViewStateInterface { public: /// gets the current view frustum for rendering the view state - virtual ViewFrustum* getCurrentViewFrustum() = 0; + virtual const ViewFrustum& getCurrentViewFrustum() = 0; /// gets the shadow view frustum for rendering the view state - virtual ViewFrustum* getShadowViewFrustum() = 0; + virtual const ViewFrustum& getShadowViewFrustum() = 0; virtual QThread* getMainThread() = 0; - + virtual PickRay computePickRay(float x, float y) const = 0; virtual glm::vec3 getAvatarPosition() const = 0; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index aae66f7098..3b0e4c8d18 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -284,7 +284,7 @@ void AmbientOcclusionEffect::updateGaussianDistribution() { void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; @@ -309,7 +309,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext auto resolutionLevel = getResolutionLevel(); // Update the depth info with near and far (same for stereo) - setDepthInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip()); + setDepthInfo(args->getViewFrustum().getNearClip(), args->getViewFrustum().getFarClip()); _frameTransformBuffer.edit().pixelInfo = args->_viewport; //_parametersBuffer.edit()._ditheringInfo.y += 0.25f; @@ -319,7 +319,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext if (!isStereo) { // Eval the mono projection mat4 monoProjMat; - args->_viewFrustum->evalProjectionMatrix(monoProjMat); + args->getViewFrustum().evalProjectionMatrix(monoProjMat); _frameTransformBuffer.edit().projection[0] = monoProjMat; _frameTransformBuffer.edit().stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f); @@ -365,7 +365,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext // Pyramid pass batch.setFramebuffer(pyramidFBO); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->_viewFrustum->getFarClip(), 0.0f, 0.0f, 0.0f)); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->getViewFrustum().getFarClip(), 0.0f, 0.0f, 0.0f)); batch.setPipeline(pyramidPipeline); batch.setResourceTexture(AmbientOcclusionEffect_DepthMapSlot, depthBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 1f00d468b0..fc09f8431d 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -94,7 +94,7 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; @@ -118,8 +118,8 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); @@ -134,7 +134,7 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + args->getViewFrustum().computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); // float depthScale = (farVal - nearVal) / farVal; // float nearScale = -1.0f / nearVal; diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index c9ea223b3f..12d3774ffd 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -275,7 +275,7 @@ void DebugDeferredBuffer::configure(const Config& config) { void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -283,20 +283,20 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren const auto framebufferCache = DependencyManager::get(); const auto textureCache = DependencyManager::get(); const auto& lightStage = DependencyManager::get()->getLightStage(); - + glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); // TODO REMOVE: Temporary until UI auto first = _customPipelines.begin()->first; - + batch.setPipeline(getPipeline(_mode, first)); - + batch.setResourceTexture(Albedo, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture()); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index ac24b09c40..1d9ce65581 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -218,15 +218,15 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo float tHeight = args->_viewport.w / (float)framebufferSize.height(); // The view frustum is the mono frustum base - auto viewFrustum = args->_viewFrustum; + auto viewFrustum = args->getViewFrustum(); // Eval the mono projection mat4 monoProjMat; - viewFrustum->evalProjectionMatrix(monoProjMat); + viewFrustum.evalProjectionMatrix(monoProjMat); // The mono view transform Transform monoViewTransform; - viewFrustum->evalViewTransform(monoViewTransform); + viewFrustum.evalViewTransform(monoViewTransform); // THe mono view matrix coming from the mono view transform glm::mat4 monoViewMat; @@ -296,8 +296,8 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight); } - auto eyePoint = viewFrustum->getPosition(); - float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft()); + auto eyePoint = viewFrustum.getPosition(); + float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft()); for (int side = 0; side < numPasses; side++) { diff --git a/libraries/render-utils/src/HitEffect.cpp b/libraries/render-utils/src/HitEffect.cpp index 8f1e9259d4..febfd1942e 100644 --- a/libraries/render-utils/src/HitEffect.cpp +++ b/libraries/render-utils/src/HitEffect.cpp @@ -62,19 +62,19 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() { void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - + glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - + batch.setPipeline(getHitEffectPipeline()); glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 5e28bea4a6..fc6c3ff514 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -20,7 +20,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); } -void LightStage::Shadow::setKeylightFrustum(const ViewFrustum* viewFrustum, float nearDepth, float farDepth) { +void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth) { assert(nearDepth < farDepth); // Orient the keylight frustum @@ -38,13 +38,13 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum* viewFrustum, floa _frustum->setOrientation(orientation); // Position the keylight frustum - _frustum->setPosition(viewFrustum->getPosition() - (nearDepth + farDepth)*direction); + _frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction); const Transform view{ _frustum->getView()}; const Transform viewInverse{ view.getInverseMatrix() }; - auto nearCorners = viewFrustum->getCorners(nearDepth); - auto farCorners = viewFrustum->getCorners(farDepth); + auto nearCorners = viewFrustum.getCorners(nearDepth); + auto farCorners = viewFrustum.getCorners(farDepth); vec3 min{ viewInverse.transform(nearCorners.bottomLeft) }; vec3 max{ min }; diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 14af861e35..9ed9789965 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -28,7 +28,7 @@ public: Shadow(model::LightPointer light); - void setKeylightFrustum(const ViewFrustum* viewFrustum, float nearDepth, float farDepth); + void setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth); const std::shared_ptr getFrustum() const { return _frustum; } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 81da0e320a..000446d9df 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -163,7 +163,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend // Is it possible that we render without a viewFrustum ? - if (!(renderContext->args && renderContext->args->_viewFrustum)) { + if (!(renderContext->args && renderContext->args->hasViewFrustum())) { return; } @@ -174,7 +174,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); auto config = std::static_pointer_cast(renderContext->jobConfig); @@ -187,8 +187,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); @@ -240,7 +240,7 @@ DrawOverlay3D::DrawOverlay3D(bool opaque) : void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const render::ItemBounds& inItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); auto config = std::static_pointer_cast(renderContext->jobConfig); @@ -268,8 +268,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); @@ -290,7 +290,7 @@ const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() { void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); // from the touched pixel generate the stencil buffer RenderArgs* args = renderContext->args; @@ -316,7 +316,7 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -334,8 +334,8 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index e2e543cc3e..f695e2d04c 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -34,7 +34,7 @@ using namespace render; void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ShapeBounds& inShapes) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); const auto& lightStage = DependencyManager::get()->getLightStage(); const auto globalLight = lightStage.lights[0]; @@ -146,16 +146,15 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render } // Cache old render args - const ViewFrustum* viewFrustum = args->_viewFrustum; RenderArgs::RenderMode mode = args->_renderMode; - auto nearClip = viewFrustum->getNearClip(); + auto nearClip = args->getViewFrustum().getNearClip(); float nearDepth = -args->_boomOffset.z; const int SHADOW_FAR_DEPTH = 20; - globalLight->shadow.setKeylightFrustum(viewFrustum, nearDepth, nearClip + SHADOW_FAR_DEPTH); + globalLight->shadow.setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH); // Set the keylight render args - args->_viewFrustum = globalLight->shadow.getFrustum().get(); + args->pushViewFrustum(*(globalLight->shadow.getFrustum())); args->_renderMode = RenderArgs::SHADOW_RENDER_MODE; // TODO: Allow runtime manipulation of culling ShouldRenderFunctor @@ -165,6 +164,6 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render } // Reset the render args - args->_viewFrustum = viewFrustum; + args->popViewFrustum(); args->_renderMode = mode; }; diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 33096f9b5f..e27895352f 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -23,10 +24,10 @@ using namespace render; void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, const ItemBounds& inItems, ItemBounds& outItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; - const ViewFrustum* frustum = args->_viewFrustum; + const ViewFrustum& frustum = args->getViewFrustum(); details._considered += (int)inItems.size(); @@ -42,7 +43,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc bool inView; { PerformanceTimer perfTimer("boxIntersectsFrustum"); - inView = frustum->boxIntersectsFrustum(item.bound); + inView = frustum.boxIntersectsFrustum(item.bound); } if (inView) { bool bigEnoughToRender; @@ -64,7 +65,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc void FetchNonspatialItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); auto& scene = sceneContext->_scene; outItems.clear(); @@ -85,7 +86,7 @@ void FetchSpatialTree::configure(const Config& config) { void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemSpatialTree::ItemSelection& outSelection) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; @@ -93,22 +94,18 @@ void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const Render outSelection.clear(); // Eventually use a frozen frustum - auto queryFrustum = *args->_viewFrustum; + auto queryFrustum = args->getViewFrustum(); if (_freezeFrustum) { if (_justFrozeFrustum) { _justFrozeFrustum = false; - _frozenFrutstum = *args->_viewFrustum; + _frozenFrutstum = args->getViewFrustum(); } queryFrustum = _frozenFrutstum; } // Octree selection! - - float angle = glm::degrees(queryFrustum.getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust)); - - + float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust)); scene->getSpatialTree().selectCellItems(outSelection, _filter, queryFrustum, angle); - } void CullSpatialSelection::configure(const Config& config) { @@ -120,7 +117,7 @@ void CullSpatialSelection::configure(const Config& config) { void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection, ItemBounds& outItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; @@ -128,13 +125,12 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re details._considered += (int)inSelection.numItems(); // Eventually use a frozen frustum - auto argFrustum = args->_viewFrustum; if (_freezeFrustum) { if (_justFrozeFrustum) { _justFrozeFrustum = false; - _frozenFrutstum = *args->_viewFrustum; + _frozenFrutstum = args->getViewFrustum(); } - args->_viewFrustum = &_frozenFrutstum; // replace the true view frustum by the frozen one + args->pushViewFrustum(_frozenFrutstum); // replace the true view frustum by the frozen one } // Culling Frustum / solidAngle test helper class @@ -151,8 +147,8 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re _renderDetails(renderDetails) { // FIXME: Keep this code here even though we don't use it yet - /*_eyePos = _args->_viewFrustum->getPosition(); - float a = glm::degrees(_args->_viewFrustum->getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust)); + /*_eyePos = _args->getViewFrustum().getPosition(); + float a = glm::degrees(Octree::getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust)); auto angle = std::min(glm::radians(45.0f), a); // no worse than 45 degrees angle = std::max(glm::radians(1.0f / 60.0f), a); // no better than 1 minute of degree auto tanAlpha = tan(angle); @@ -161,7 +157,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re } bool frustumTest(const AABox& bound) { - if (!_args->_viewFrustum->boxIntersectsFrustum(bound)) { + if (!_args->getViewFrustum().boxIntersectsFrustum(bound)) { _renderDetails._outOfView++; return false; } @@ -305,7 +301,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re // Restore frustum if using the frozen one: if (_freezeFrustum) { - args->_viewFrustum = argFrustum; + args->popViewFrustum(); } std::static_pointer_cast(renderContext->jobConfig)->numItems = (int)outItems.size(); diff --git a/libraries/render/src/render/DrawSceneOctree.cpp b/libraries/render/src/render/DrawSceneOctree.cpp index 9b22649a8d..efcb4eea37 100644 --- a/libraries/render/src/render/DrawSceneOctree.cpp +++ b/libraries/render/src/render/DrawSceneOctree.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -86,7 +87,7 @@ void DrawSceneOctree::configure(const Config& config) { void DrawSceneOctree::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; @@ -97,8 +98,8 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext, gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(projMat); @@ -148,7 +149,7 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext, } // Draw the LOD Reticle { - float angle = glm::degrees(args->_viewFrustum->getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust)); + float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust)); Transform crosshairModel; crosshairModel.setTranslation(glm::vec3(0.0, 0.0, -1000.0)); 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) { void DrawItemSelection::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(projMat); diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 584f41499a..c2724fce42 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -107,7 +107,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; const int NUM_STATUS_VEC4_PER_ITEM = 2; @@ -183,8 +183,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(projMat); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 6d43d169c3..e3cfc9fa63 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -120,7 +120,7 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; // render lights diff --git a/libraries/octree/src/Plane.cpp b/libraries/shared/src/Plane.cpp similarity index 93% rename from libraries/octree/src/Plane.cpp rename to libraries/shared/src/Plane.cpp index 8e782dd087..bd7937471c 100644 --- a/libraries/octree/src/Plane.cpp +++ b/libraries/shared/src/Plane.cpp @@ -1,6 +1,6 @@ // // Plane.cpp -// libraries/octree/src/ +// libraries/shared/src/ // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. @@ -13,12 +13,12 @@ // #include "Plane.h" -#include "OctreeLogging.h" - - -#include #include +#include + +#include "SharedLogging.h" + void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { glm::vec3 linev1v2, linev1v3; @@ -65,7 +65,7 @@ float Plane::distance(const glm::vec3 &point) const { } void Plane::print() const { - qCDebug(octree, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f", + qCDebug(shared, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f", (double)_point.x, (double)_point.y, (double)_point.z, (double)_normal.x, (double)_normal.y, (double)_normal.z, (double)_dCoefficient); } diff --git a/libraries/octree/src/Plane.h b/libraries/shared/src/Plane.h similarity index 83% rename from libraries/octree/src/Plane.h rename to libraries/shared/src/Plane.h index db809ad542..c903ad9db7 100644 --- a/libraries/octree/src/Plane.h +++ b/libraries/shared/src/Plane.h @@ -1,6 +1,6 @@ // // Plane.h -// libraries/octree/src/ +// libraries/shared/src/ // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. @@ -20,7 +20,7 @@ class Plane { public: Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); } - Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {}; + Plane() : _normal(0.0f), _point(0.0f), _dCoefficient(0.0f) {}; ~Plane() {} ; // methods for defining the plane @@ -28,12 +28,13 @@ public: void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point); void setCoefficients(float a, float b, float c, float d); - // getters + // getters const glm::vec3& getNormal() const { return _normal; }; const glm::vec3& getPoint() const { return _point; }; float getDCoefficient() const { return _dCoefficient; }; // utilities + void invalidate() { _normal = glm::vec3(0.0f), _dCoefficient = 1.0e6f; } // distance() never less than 10^6 float distance(const glm::vec3 &point) const; void print() const; @@ -44,4 +45,4 @@ private: }; -#endif // hifi_Plane_h \ No newline at end of file +#endif // hifi_Plane_h diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index a08b15886a..8c66a6a19b 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -14,12 +14,15 @@ #include #include -#include "GLMHelpers.h" +#include + +#include +#include + class AABox; class OctreeRenderer; -class ViewFrustum; namespace gpu { class Batch; @@ -39,21 +42,21 @@ public: SHADOW, OTHER }; - + struct Item { int _considered = 0; int _outOfView = 0; int _tooSmall = 0; int _rendered = 0; }; - + int _materialSwitches = 0; int _trianglesRendered = 0; - + Item _item; Item _shadow; Item _other; - + Item& edit(Type type) { switch (type) { case SHADOW: @@ -77,7 +80,6 @@ public: RenderArgs(std::shared_ptr context = nullptr, OctreeRenderer* renderer = nullptr, - const ViewFrustum* viewFrustum = nullptr, float sizeScale = 1.0f, int boundaryLevelAdjust = 0, RenderMode renderMode = DEFAULT_RENDER_MODE, @@ -86,7 +88,7 @@ public: gpu::Batch* batch = nullptr) : _context(context), _renderer(renderer), - _viewFrustum(viewFrustum), + _viewFrustums(), _sizeScale(sizeScale), _boundaryLevelAdjust(boundaryLevelAdjust), _renderMode(renderMode), @@ -95,11 +97,22 @@ public: _batch(batch) { } + bool hasViewFrustum() const { return _viewFrustums.size() > 0; } + void setViewFrustum(const ViewFrustum& viewFrustum) { + while (_viewFrustums.size() > 0) { + _viewFrustums.pop(); + } + _viewFrustums.push(viewFrustum); + } + const ViewFrustum& getViewFrustum() const { assert(_viewFrustums.size() > 0); return _viewFrustums.top(); } + void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); } + void popViewFrustum() { _viewFrustums.pop(); } + std::shared_ptr _context = nullptr; std::shared_ptr _blitFramebuffer = nullptr; std::shared_ptr _pipeline = nullptr; OctreeRenderer* _renderer = nullptr; - const ViewFrustum* _viewFrustum = nullptr; + std::stack _viewFrustums; glm::ivec4 _viewport{ 0.0f, 0.0f, 1.0f, 1.0f }; glm::vec3 _boomOffset{ 0.0f, 0.0f, 1.0f }; float _sizeScale = 1.0f; @@ -108,7 +121,7 @@ public: RenderSide _renderSide = MONO; DebugFlags _debugFlags = RENDER_DEBUG_NONE; gpu::Batch* _batch = nullptr; - + std::shared_ptr _whiteTexture; RenderDetails _details; diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp similarity index 75% rename from libraries/octree/src/ViewFrustum.cpp rename to libraries/shared/src/ViewFrustum.cpp index 7e71155df3..3e52a9f2c8 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -1,6 +1,6 @@ // // ViewFrustum.cpp -// libraries/octree/src +// libraries/shared/src // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. @@ -17,13 +17,13 @@ #include #include -#include #include "GeometryUtil.h" #include "GLMHelpers.h" +#include "NumericalConstants.h" +#include "SharedLogging.h" +//#include "OctreeConstants.h" #include "ViewFrustum.h" -#include "OctreeLogging.h" -#include "OctreeConstants.h" using namespace std; @@ -41,15 +41,15 @@ void ViewFrustum::setPosition(const glm::vec3& position) { } // Order cooresponds to the order defined in the BoxVertex enum. -static const glm::vec4 NDC_VALUES[8] = { - glm::vec4(-1, -1, -1, 1), - glm::vec4(1, -1, -1, 1), - glm::vec4(1, 1, -1, 1), - glm::vec4(-1, 1, -1, 1), - glm::vec4(-1, -1, 1, 1), - glm::vec4(1, -1, 1, 1), - glm::vec4(1, 1, 1, 1), - glm::vec4(-1, 1, 1, 1), +static const glm::vec4 NDC_VALUES[NUM_FRUSTUM_CORNERS] = { + glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f), + glm::vec4(1.0f, -1.0f, -1.0f, 1.0f), + glm::vec4(1.0f, 1.0f, -1.0f, 1.0f), + glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f), + glm::vec4(-1.0f, -1.0f, 1.0f, 1.0f), + glm::vec4(1.0f, -1.0f, 1.0f, 1.0f), + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), + glm::vec4(-1.0f, 1.0f, 1.0f, 1.0f), }; void ViewFrustum::setProjection(const glm::mat4& projection) { @@ -57,7 +57,7 @@ void ViewFrustum::setProjection(const glm::mat4& projection) { _inverseProjection = glm::inverse(projection); // compute our dimensions the usual way - for (int i = 0; i < 8; ++i) { + for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) { _corners[i] = _inverseProjection * NDC_VALUES[i]; _corners[i] /= _corners[i].w; } @@ -66,9 +66,9 @@ void ViewFrustum::setProjection(const glm::mat4& projection) { _aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) / (_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y); - glm::vec4 top = _inverseProjection * vec4(0, 1, -1, 1); + glm::vec4 top = _inverseProjection * vec4(0.0f, 1.0f, -1.0f, 1.0f); top /= top.w; - _fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0, 0, -1), glm::normalize(vec3(top)))))); + _fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0.0f, 0.0f, -1.0f), glm::normalize(vec3(top)))))); } // ViewFrustum::calculateViewFrustum() @@ -84,7 +84,7 @@ void ViewFrustum::calculate() { // then transform them to world space glm::mat4 worldMatrix = glm::translate(_position) * glm::mat4(glm::mat3(_right, _up, -_direction)); glm::vec4 v; - for (int i = 0; i < 8; ++i) { + for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) { v = worldMatrix * _corners[i]; v /= v.w; _cornersWorld[i] = glm::vec3(v); @@ -133,7 +133,7 @@ const char* ViewFrustum::debugPlaneName (int plane) const { ViewFrustum::intersection ViewFrustum::calculateCubeFrustumIntersection(const AACube& cube) const { // only check against frustum ViewFrustum::intersection result = INSIDE; - for(int i=0; i < 6; i++) { + for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) { const glm::vec3& normal = _planes[i].getNormal(); // check distance to farthest cube point if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) { @@ -178,7 +178,7 @@ ViewFrustum::intersection ViewFrustum::calculateCubeKeyholeIntersection(const AA bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const { // only check against frustum - for(int i = 0; i < 6; ++i) { + for(int i = 0; i < NUM_FRUSTUM_PLANES; ++i) { float distance = _planes[i].distance(point); if (distance < 0.0f) { return false; @@ -189,7 +189,7 @@ bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const { bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius) const { // only check against frustum - for(int i=0; i < 6; i++) { + for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) { float distance = _planes[i].distance(center); if (distance < -radius) { // 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) bool ViewFrustum::boxIntersectsFrustum(const AABox& box) const { // only check against frustum - for(int i=0; i < 6; i++) { + for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) { const glm::vec3& normal = _planes[i].getNormal(); // check distance to farthest box point if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) { @@ -217,7 +217,7 @@ bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius) return true; } // check negative touches against frustum planes - for(int i=0; i < 6; i++) { + for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) { if ( _planes[i].distance(center) < -radius) { return false; } @@ -231,7 +231,7 @@ bool ViewFrustum::cubeIntersectsKeyhole(const AACube& cube) const { return true; } // check negative touches against frustum planes - for(int i=0; i < 6; i++) { + for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) { const glm::vec3& normal = _planes[i].getNormal(); if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) { return false; @@ -246,7 +246,7 @@ bool ViewFrustum::boxIntersectsKeyhole(const AABox& box) const { return true; } // check negative touches against frustum planes - for(int i=0; i < 6; i++) { + for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) { const glm::vec3& normal = _planes[i].getNormal(); if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) { return false; @@ -293,34 +293,34 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const if (!result && debug) { - qCDebug(octree, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result)); - qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f", + qCDebug(shared, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result)); + qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f", (testMatches(compareTo._position,_position, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"), (double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z, (double)_position.x, (double)_position.y, (double)_position.z ); - qCDebug(octree, "%s -- positionDistance=%f", + qCDebug(shared, "%s -- positionDistance=%f", (testMatches(0,positionDistance, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"), (double)positionDistance); - qCDebug(octree, "%s -- angleOrientation=%f", + qCDebug(shared, "%s -- angleOrientation=%f", (testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"), (double)angleOrientation); - qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f", + qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f", (testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"), (double)compareTo._fieldOfView, (double)_fieldOfView); - qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f", + qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f", (testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"), (double)compareTo._aspectRatio, (double)_aspectRatio); - qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f", + qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f", (testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"), (double)compareTo._nearClip, (double)_nearClip); - qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f", + qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f", (testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"), (double)compareTo._farClip, (double)_farClip); - qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f", + qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f", (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"), (double)compareTo._focalLength, (double)_focalLength); } @@ -345,7 +345,7 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom // find the minimum and maximum z values, which will be our near and far clip distances nearValue = FLT_MAX; farValue = -FLT_MAX; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < NUM_FRUSTUM_CORNERS; i++) { nearValue = min(nearValue, -_corners[i].z); farValue = max(farValue, -_corners[i].z); } @@ -378,94 +378,19 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom } void ViewFrustum::printDebugDetails() const { - qCDebug(octree, "ViewFrustum::printDebugDetails()..."); - qCDebug(octree, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z ); - qCDebug(octree, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z ); - qCDebug(octree, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z ); - qCDebug(octree, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z ); - qCDebug(octree, "_fieldOfView=%f", (double)_fieldOfView); - qCDebug(octree, "_aspectRatio=%f", (double)_aspectRatio); - qCDebug(octree, "_centerSphereRadius=%f", (double)_centerSphereRadius); - qCDebug(octree, "_nearClip=%f", (double)_nearClip); - qCDebug(octree, "_farClip=%f", (double)_farClip); - qCDebug(octree, "_focalLength=%f", (double)_focalLength); + qCDebug(shared, "ViewFrustum::printDebugDetails()..."); + qCDebug(shared, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z ); + qCDebug(shared, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z ); + qCDebug(shared, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z ); + qCDebug(shared, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z ); + qCDebug(shared, "_fieldOfView=%f", (double)_fieldOfView); + qCDebug(shared, "_aspectRatio=%f", (double)_aspectRatio); + qCDebug(shared, "_centerSphereRadius=%f", (double)_centerSphereRadius); + qCDebug(shared, "_nearClip=%f", (double)_nearClip); + qCDebug(shared, "_farClip=%f", (double)_farClip); + qCDebug(shared, "_focalLength=%f", (double)_focalLength); } -const int MAX_POSSIBLE_COMBINATIONS = 43; - -const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERTEX_COUNT+1] = { - // Number of vertices in shadow polygon for the visible faces, then a list of the index of each vertice from the AACube - -//0 - {0}, // inside - {4, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR}, // right - {4, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, // left - {0}, // n/a - -//4 - {4, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR}, // bottom -//5 - {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR },//bottom, right - {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, },//bottom, left - {0}, // n/a -//8 - {4, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // top - {6, TOP_RIGHT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // top, right - {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // top, left - {0}, // n/a - {0}, // n/a - {0}, // n/a - {0}, // n/a - {0}, // n/a -//16 - {4, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front or near - - {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front, right - {6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, }, // front, left - {0}, // n/a -//20 - {6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front,bottom - -//21 - {6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, //front,bottom,right -//22 - {6, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, //front,bottom,left - {0}, // n/a - - {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // front, top - - {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR }, // front, top, right - - {6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR }, // front, top, left - {0}, // n/a - {0}, // n/a - {0}, // n/a - {0}, // n/a - {0}, // n/a -//32 - {4, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR }, // back - {6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR}, // back, right -//34 - {6, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, TOP_RIGHT_FAR }, // back, left - - - {0}, // n/a -//36 - {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR}, // back, bottom - {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR},//back, bottom, right - -// 38 - {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR },//back, bottom, left - {0}, // n/a - -// 40 - {6, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR}, // back, top - - {6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR}, // back, top, right -//42 - {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left -}; - // Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for // squares and square-roots. Just compares. @@ -528,11 +453,19 @@ void ViewFrustum::evalViewTransform(Transform& view) const { view.setRotation(getOrientation()); } -float ViewFrustum::calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale, int boundaryLevelAdjust) const { +void ViewFrustum::invalidate() { + // these setting should make nearly all intersection tests fail + for (int i = 0; i < NUM_FRUSTUM_PLANES; ++i) { + _planes[i].invalidate(); + } + _centerSphereRadius = -1.0e6f; // -10^6 should be negative enough +} + +/* +float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale, float maxScale, int boundaryLevelAdjust) const { float distanceToCamera = glm::length(bounds.calcCenter() - getPosition()); float largestDimension = bounds.getLargestDimension(); - const float maxScale = (float)TREE_SCALE; float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; static std::once_flag once; @@ -571,8 +504,8 @@ float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeSc return voxelSizeScale / powf(2, renderLevel); } -float ViewFrustum::getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) const { - const float maxScale = (float)TREE_SCALE; +float getAccuracyAngle(float octreeSizeScale, float maxScale, int boundaryLevelAdjust) const { float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; return atan(maxScale / visibleDistanceAtMaxScale); } +*/ diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h similarity index 83% rename from libraries/octree/src/ViewFrustum.h rename to libraries/shared/src/ViewFrustum.h index 0fce67ac1b..897f0c77d7 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -1,6 +1,6 @@ // // ViewFrustum.h -// libraries/octree/src +// libraries/shared/src // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. @@ -17,21 +17,22 @@ #include #include -#include -#include +//#include -#include "Transform.h" #include "AABox.h" #include "AACube.h" #include "Plane.h" -#include "OctreeConstants.h" -#include "OctreeProjectedPolygon.h" +#include "RegisteredMetaTypes.h" +#include "Transform.h" + +const int NUM_FRUSTUM_CORNERS = 8; +const int NUM_FRUSTUM_PLANES = 6; const float DEFAULT_CENTER_SPHERE_RADIUS = 3.0f; const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f; const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f; const float DEFAULT_NEAR_CLIP = 0.08f; -const float DEFAULT_FAR_CLIP = (float)HALF_TREE_SCALE; +const float DEFAULT_FAR_CLIP = 16384.0f; // the "ViewFrustum" has a "keyhole" shape: a regular frustum for stuff that is "visible" with // a central sphere for stuff that is nearby (for physics simulation). @@ -125,16 +126,11 @@ public: void evalProjectionMatrix(glm::mat4& proj) const; void evalViewTransform(Transform& view) const; - /// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple - /// level it returns 0.0f for things that are so small for the current settings that they could not be visible. - float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, - int boundaryLevelAdjust = 0) const; - - float getAccuracyAngle(float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const; - enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES }; const ::Plane* getPlanes() const { return _planes; } + + void invalidate(); // causes all reasonable intersection tests to fail private: // camera location/orientation attributes glm::vec3 _position; // the position in world-frame @@ -153,16 +149,16 @@ private: // Calculated values glm::mat4 _inverseProjection; - float _width = 1.0f; - float _height = 1.0f; - float _aspectRatio = 1.0f; - float _nearClip = DEFAULT_NEAR_CLIP; - float _farClip = DEFAULT_FAR_CLIP; - float _focalLength = 0.25f; - float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES; - glm::vec4 _corners[8]; - glm::vec3 _cornersWorld[8]; - ::Plane _planes[6]; // plane normals point inside frustum + float _width { 1.0f }; + float _height { 1.0f }; + float _aspectRatio { 1.0f }; + float _nearClip { DEFAULT_NEAR_CLIP }; + float _farClip { DEFAULT_FAR_CLIP }; + float _focalLength { 0.25f }; + float _fieldOfView { DEFAULT_FIELD_OF_VIEW_DEGREES }; + glm::vec4 _corners[NUM_FRUSTUM_CORNERS]; + glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS]; + ::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum const char* debugPlaneName (int plane) const; @@ -171,6 +167,4 @@ private: }; using ViewFrustumPointer = std::shared_ptr; -float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale); - #endif // hifi_ViewFrustum_h From 71b2d647e85defbfd3430a1f79700c4591dbcc98 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 7 Mar 2016 10:04:54 -0800 Subject: [PATCH 05/14] add locks and explicitly copy ViewFrustums --- .../src/octree/OctreeQueryNode.cpp | 48 +++++--- .../src/octree/OctreeQueryNode.h | 8 +- .../src/octree/OctreeSendThread.cpp | 4 +- interface/src/Application.cpp | 109 ++++++++++++------ interface/src/Application.h | 9 +- interface/src/avatar/Avatar.cpp | 22 ++-- interface/src/avatar/Head.h | 2 - interface/src/avatar/MyAvatar.cpp | 14 ++- .../src/AbstractViewStateInterface.h | 8 +- .../render-utils/src/RenderDeferredTask.cpp | 6 +- libraries/render/src/render/SortTask.cpp | 4 +- 11 files changed, 148 insertions(+), 86 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 55eddf9e13..364cbf33c1 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -141,6 +141,16 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by } } +void OctreeQueryNode::copyCurrentViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _currentViewFrustum; +} + +void OctreeQueryNode::copyLastKnownViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _lastKnownViewFrustum; +} + bool OctreeQueryNode::updateCurrentViewFrustum() { // if shutting down, return immediately if (_isShuttingDown) { @@ -171,11 +181,13 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { } - // if there has been a change, then recalculate - if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) { - _currentViewFrustum = newestViewFrustum; - _currentViewFrustum.calculate(); - currentViewFrustumChanged = true; + { // if there has been a change, then recalculate + QMutexLocker viewLocker(&_viewMutex); + if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) { + _currentViewFrustum = newestViewFrustum; + _currentViewFrustum.calculate(); + currentViewFrustumChanged = true; + } } // Also check for LOD changes from the client @@ -219,11 +231,14 @@ void OctreeQueryNode::updateLastKnownViewFrustum() { return; } - bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum); + { + QMutexLocker viewLocker(&_viewMutex); + bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum); - if (frustumChanges) { - // save our currentViewFrustum into our lastKnownViewFrustum - _lastKnownViewFrustum = _currentViewFrustum; + if (frustumChanges) { + // save our currentViewFrustum into our lastKnownViewFrustum + _lastKnownViewFrustum = _currentViewFrustum; + } } // save that we know the view has been sent. @@ -237,15 +252,13 @@ bool OctreeQueryNode::moveShouldDump() const { return false; } + QMutexLocker viewLocker(&_viewMutex); glm::vec3 oldPosition = _lastKnownViewFrustum.getPosition(); glm::vec3 newPosition = _currentViewFrustum.getPosition(); // theoretically we could make this slightly larger but relative to avatar scale. const float MAXIMUM_MOVE_WITHOUT_DUMP = 0.0f; - if (glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP) { - return true; - } - return false; + return glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP; } void OctreeQueryNode::dumpOutOfView() { @@ -257,8 +270,13 @@ void OctreeQueryNode::dumpOutOfView() { int stillInView = 0; int outOfView = 0; OctreeElementBag tempBag; + ViewFrustum viewCopy; + { + QMutexLocker viewLocker(&_viewMutex); + viewCopy = _currentViewFrustum; + } while (OctreeElementPointer elementToCheck = elementBag.extract()) { - if (elementToCheck->isInView(_currentViewFrustum)) { + if (elementToCheck->isInView(viewCopy)) { tempBag.insert(elementToCheck); stillInView++; } else { @@ -267,7 +285,7 @@ void OctreeQueryNode::dumpOutOfView() { } if (stillInView > 0) { while (OctreeElementPointer elementToKeepInBag = tempBag.extract()) { - if (elementToKeepInBag->isInView(_currentViewFrustum)) { + if (elementToKeepInBag->isInView(viewCopy)) { elementBag.insert(elementToKeepInBag); } } diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 22d04d81f6..96f46cb2fa 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -56,8 +56,8 @@ public: OctreeElementBag elementBag; OctreeElementExtraEncodeData extraEncodeData; - const ViewFrustum& getCurrentViewFrustum() const { return _currentViewFrustum; } - const ViewFrustum& getLastKnownViewFrustum() const { return _lastKnownViewFrustum; } + void copyCurrentViewFrustum(ViewFrustum& viewOut) const; + void copyLastKnownViewFrustum(ViewFrustum& viewOut) const; // These are not classic setters because they are calculating and maintaining state // which is set asynchronously through the network receive @@ -114,6 +114,8 @@ private: int _maxSearchLevel { 1 }; int _maxLevelReachedInLastSearch { 1 }; + + mutable QMutex _viewMutex { QMutex::Recursive }; ViewFrustum _currentViewFrustum; ViewFrustum _lastKnownViewFrustum; quint64 _lastTimeBagEmpty { 0 }; @@ -139,7 +141,7 @@ private: QQueue _nackedSequenceNumbers; quint64 _sceneSendStartTime = 0; - + std::array _lastOctreePayload; }; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 7701cedd94..709cdd5d07 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -427,9 +427,9 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData->getLastTimeBagEmpty(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(), &nodeData->extraEncodeData); - params.viewFrustum = nodeData->getCurrentViewFrustum(); + nodeData->copyCurrentViewFrustum(params.viewFrustum); if (viewFrustumChanged) { - params.lastViewFrustum = nodeData->getLastKnownViewFrustum(); + nodeData->copyLastKnownViewFrustum(params.lastViewFrustum); } // Our trackSend() function is implemented by the server subclass, and will be called back diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 994bb89556..19b0e432e1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1511,12 +1511,17 @@ void Application::paintGL() { auto lodManager = DependencyManager::get(); - - _viewFrustum.calculate(); + { + QMutexLocker viewLocker(&_viewMutex); + _viewFrustum.calculate(); + } RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); - renderArgs.setViewFrustum(getViewFrustum()); + { + QMutexLocker viewLocker(&_viewMutex); + renderArgs.setViewFrustum(_viewFrustum); + } PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -1813,7 +1818,10 @@ void Application::resizeGL() { _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); // Possible change in aspect ratio - loadViewFrustum(_myCamera, _viewFrustum); + { + QMutexLocker viewLocker(&_viewMutex); + loadViewFrustum(_myCamera, _viewFrustum); + } auto offscreenUi = DependencyManager::get(); auto uiSize = displayPlugin->getRecommendedUiSize(); @@ -2140,6 +2148,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_J: if (isShifted) { + QMutexLocker viewLocker(&_viewMutex); _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); @@ -2149,6 +2158,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_M: if (isShifted) { + QMutexLocker viewLocker(&_viewMutex); _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); @@ -2997,7 +3007,10 @@ void Application::init() { DependencyManager::get()->sendDomainServerCheckIn(); getEntities()->init(); - getEntities()->setViewFrustum(getViewFrustum()); + { + QMutexLocker viewLocker(&_viewMutex); + getEntities()->setViewFrustum(_viewFrustum); + } ObjectMotionState::setShapeManager(&_shapeManager); _physicsEngine->init(); @@ -3017,7 +3030,10 @@ void Application::init() { getEntities()->connectSignalsToSlots(entityScriptingInterface.data()); _entityClipboardRenderer.init(); - _entityClipboardRenderer.setViewFrustum(getViewFrustum()); + { + QMutexLocker viewLocker(&_viewMutex); + _entityClipboardRenderer.setViewFrustum(_viewFrustum); + } _entityClipboardRenderer.setTree(_entityClipboard); // Make sure any new sounds are loaded as soon as know about them. @@ -3220,9 +3236,12 @@ void Application::resetPhysicsReadyInformation() { void Application::reloadResourceCaches() { resetPhysicsReadyInformation(); + { + QMutexLocker viewLocker(&_viewMutex); + _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE)); + _viewFrustum.setOrientation(glm::quat()); + } // Clear entities out of view frustum - _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE)); - _viewFrustum.setOrientation(glm::quat()); queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions); DependencyManager::get()->clearCache(); @@ -3511,7 +3530,7 @@ void Application::update(float deltaTime) { // actually need to calculate the view frustum planes to send these details // to the server. { - PerformanceTimer perfTimer("loadViewFrustum"); + QMutexLocker viewLocker(&_viewMutex); loadViewFrustum(_myCamera, _viewFrustum); } @@ -3520,6 +3539,7 @@ void Application::update(float deltaTime) { // Update my voxel servers with my current voxel query... { PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + QMutexLocker viewLocker(&_viewMutex); PerformanceTimer perfTimer("queryOctree"); quint64 sinceLastQuery = now - _lastQueriedTime; const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; @@ -3631,14 +3651,19 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node //qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView(); bool wantExtraDebugging = getLogger()->extraDebugging(); - _octreeQuery.setCameraPosition(_viewFrustum.getPosition()); - _octreeQuery.setCameraOrientation(_viewFrustum.getOrientation()); - _octreeQuery.setCameraFov(_viewFrustum.getFieldOfView()); - _octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio()); - _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); - _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); + ViewFrustum viewFrustumCopy; + { + QMutexLocker viewLocker(&_viewMutex); + viewFrustumCopy = _viewFrustum; + } + _octreeQuery.setCameraPosition(viewFrustumCopy.getPosition()); + _octreeQuery.setCameraOrientation(viewFrustumCopy.getOrientation()); + _octreeQuery.setCameraFov(viewFrustumCopy.getFieldOfView()); + _octreeQuery.setCameraAspectRatio(viewFrustumCopy.getAspectRatio()); + _octreeQuery.setCameraNearClip(viewFrustumCopy.getNearClip()); + _octreeQuery.setCameraFarClip(viewFrustumCopy.getFarClip()); _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); - _octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius()); + _octreeQuery.setCameraCenterRadius(viewFrustumCopy.getCenterRadius()); auto lodManager = DependencyManager::get(); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); @@ -3674,7 +3699,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node rootDetails.y * TREE_SCALE, rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE), rootDetails.s * TREE_SCALE); - if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) { + if (viewFrustumCopy.cubeIntersectsKeyhole(serverBounds)) { inViewServers++; } } @@ -3740,7 +3765,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node rootDetails.s * TREE_SCALE); - inView = _viewFrustum.cubeIntersectsKeyhole(serverBounds); + inView = viewFrustumCopy.cubeIntersectsKeyhole(serverBounds); } else { if (wantExtraDebugging) { qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!"; @@ -3835,6 +3860,7 @@ QRect Application::getDesirableApplicationGeometry() const { // or the "myCamera". // void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { + PerformanceTimer perfTimer("loadViewFrustum"); PROFILE_RANGE(__FUNCTION__); // We will use these below, from either the camera or head vectors calculated above viewFrustum.setProjection(camera.getProjection()); @@ -3863,7 +3889,8 @@ PickRay Application::computePickRay(float x, float y) const { getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction); } else { pickPoint /= getCanvasSize(); - getViewFrustum().computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction); + QMutexLocker viewLocker(&_viewMutex); + _viewFrustum.computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction); } return result; } @@ -3876,24 +3903,19 @@ glm::vec3 Application::getAvatarPosition() const { return getMyAvatar()->getPosition(); } -const ViewFrustum& Application::getViewFrustum() const { -#ifdef DEBUG - if (QThread::currentThread() == activeRenderingThread) { - // FIXME, figure out a better way to do this - //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; - } -#endif - return _viewFrustum; +void Application::copyViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _viewFrustum; } -const ViewFrustum& Application::getDisplayViewFrustum() const { -#ifdef DEBUG - if (QThread::currentThread() != activeRenderingThread) { - // FIXME, figure out a better way to do this - // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; - } -#endif - return _displayViewFrustum; +void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _displayViewFrustum; +} + +void Application::copyShadowViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _shadowViewFrustum; } // WorldBox Render Data & rendering functions @@ -4002,7 +4024,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); // load the view frustum - loadViewFrustum(theCamera, _displayViewFrustum); + { + QMutexLocker viewLocker(&_viewMutex); + loadViewFrustum(theCamera, _displayViewFrustum); + } // TODO fix shadows and make them use the GPU library @@ -4070,7 +4095,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se { PerformanceTimer perfTimer("EngineRun"); - renderArgs->setViewFrustum(getDisplayViewFrustum()); + { + QMutexLocker viewLocker(&_viewMutex); + renderArgs->setViewFrustum(_displayViewFrustum); + } _renderEngine->getRenderContext()->args = renderArgs; // Before the deferred pass, let's try to use the render engine @@ -4496,6 +4524,11 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface()); } +void Application::copyCurrentViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _displayViewFrustum; +} + bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); if (urlString.startsWith(HIFI_URL_SCHEME)) { @@ -5200,10 +5233,10 @@ void Application::updateInputModes() { } mat4 Application::getEyeProjection(int eye) const { + QMutexLocker viewLocker(&_viewMutex); if (isHMDMode()) { return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection()); } - return _viewFrustum.getProjection(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 3f26f7bc38..018265db4a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -128,12 +128,12 @@ public: Camera* getCamera() { return &_myCamera; } const Camera* getCamera() const { return &_myCamera; } // Represents the current view frustum of the avatar. - const ViewFrustum& getViewFrustum() const; + void copyViewFrustum(ViewFrustum& viewOut) const; // Represents the view frustum of the current rendering pass, // which might be different from the viewFrustum, i.e. shadowmap // passes, mirror window passes, etc - const ViewFrustum& getDisplayViewFrustum() const; - const ViewFrustum& getShadowViewFrustum() override { return _shadowViewFrustum; } + void copyDisplayViewFrustum(ViewFrustum& viewOut) const; + void copyShadowViewFrustum(ViewFrustum& viewOut) const override; const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } EntityTreeRenderer* getEntities() const { return DependencyManager::get().data(); } QUndoStack* getUndoStack() { return &_undoStack; } @@ -167,7 +167,7 @@ public: virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override; - virtual const ViewFrustum& getCurrentViewFrustum() override { return getDisplayViewFrustum(); } + virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override; virtual QThread* getMainThread() override { return thread(); } virtual PickRay computePickRay(float x, float y) const override; virtual glm::vec3 getAvatarPosition() const override; @@ -412,6 +412,7 @@ private: EntityTreeRenderer _entityClipboardRenderer; EntityTreePointer _entityClipboard; + mutable QMutex _viewMutex { QMutex::Recursive }; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) ViewFrustum _displayViewFrustum; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f753309ffc..356b940713 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -172,7 +172,9 @@ void Avatar::simulate(float deltaTime) { // update the shouldAnimate flag to match whether or not we will render the avatar. const float MINIMUM_VISIBILITY_FOR_ON = 0.4f; const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f; - float visibility = calculateRenderAccuracy(qApp->getViewFrustum().getPosition(), + ViewFrustum viewFrustum; + qApp->copyViewFrustum(viewFrustum); + float visibility = calculateRenderAccuracy(viewFrustum.getPosition(), getBounds(), DependencyManager::get()->getOctreeSizeScale()); if (!_shouldAnimate) { if (visibility > MINIMUM_VISIBILITY_FOR_ON) { @@ -186,8 +188,9 @@ void Avatar::simulate(float deltaTime) { // simple frustum check float boundingRadius = getBoundingRadius(); - bool avatarPositionInView = qApp->getDisplayViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius); - bool avatarMeshInView = qApp->getDisplayViewFrustum()->boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound()); + qApp->copyDisplayViewFrustum(viewFrustum); + bool avatarPositionInView = viewFrustum.sphereIntersectsFrustum(getPosition(), boundingRadius); + bool avatarMeshInView = viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound()); if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) { { @@ -384,9 +387,12 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } { // simple frustum check - const ViewFrustum& frustum = renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE ? - qApp->getShadowViewFrustum() : - qApp->getDisplayViewFrustum(); + ViewFrustum frustum; + if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) { + qApp->copyShadowViewFrustum(frustum); + } else { + qApp->copyDisplayViewFrustum(frustum); + } if (!frustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())) { return; } @@ -500,7 +506,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { auto cameraMode = qApp->getCamera()->getMode(); if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) { - auto frustum = renderArgs->getViewFrustum(); + ViewFrustum frustum = renderArgs->getViewFrustum(); auto textPosition = getDisplayNamePosition(); if (frustum.pointIntersectsFrustum(textPosition)) { renderDisplayName(batch, frustum, textPosition); @@ -550,7 +556,7 @@ void Avatar::fixupModelsInScene() { scene->enqueuePendingChanges(pendingChanges); } -void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) { +void Avatar::renderBody(RenderArgs* renderArgs, float glowLevel) { fixupModelsInScene(); getHead()->renderLookAts(renderArgs); } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 4c0a516ecc..ef9584f1a7 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -29,8 +29,6 @@ class Head : public HeadData { public: explicit Head(Avatar* owningAvatar); - Head(Avatar* owningAvatar); - void init(); void reset(); void simulate(float deltaTime, bool isMine, bool billboard = false); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2208e827a0..d4e024e49e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -546,7 +546,9 @@ void MyAvatar::updateFromTrackers(float deltaTime) { head->setDeltaYaw(estimatedRotation.y); head->setDeltaRoll(estimatedRotation.z); } else { - float magnifyFieldOfView = qApp->getViewFrustum().getFieldOfView() / _realWorldFieldOfView.get(); + ViewFrustum viewFrustum; + qApp->copyViewFrustum(viewFrustum); + float magnifyFieldOfView = viewFrustum.getFieldOfView() / _realWorldFieldOfView.get(); head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView); head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView); head->setDeltaRoll(estimatedRotation.z); @@ -929,15 +931,17 @@ void MyAvatar::updateLookAtTargetAvatar() { // (We will be adding that offset to the camera position, after making some other adjustments.) glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); + ViewFrustum viewFrustum; + qApp->copyViewFrustum(viewFrustum); + // scale gazeOffset by IPD, if wearing an HMD. if (qApp->isHMDMode()) { glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); - auto humanSystem = qApp->getViewFrustum(); - glm::vec3 humanLeftEye = humanSystem.getPosition() + (humanSystem.getOrientation() * leftEyeHeadLocal); - glm::vec3 humanRightEye = humanSystem.getPosition() + (humanSystem.getOrientation() * rightEyeHeadLocal); + glm::vec3 humanLeftEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * leftEyeHeadLocal); + glm::vec3 humanRightEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * rightEyeHeadLocal); auto hmdInterface = DependencyManager::get(); float ipdScale = hmdInterface->getIPDScale(); @@ -951,7 +955,7 @@ void MyAvatar::updateLookAtTargetAvatar() { } // And now we can finally add that offset to the camera. - glm::vec3 corrected = qApp->getViewFrustum().getPosition() + gazeOffset; + glm::vec3 corrected = viewFrustum.getPosition() + gazeOffset; avatar->getHead()->setCorrectedLookAtPosition(corrected); diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index c068baf453..81790728f8 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -28,11 +28,11 @@ class PickRay; /// Interface provided by Application to other objects that need access to the current view state details class AbstractViewStateInterface { public: - /// gets the current view frustum for rendering the view state - virtual const ViewFrustum& getCurrentViewFrustum() = 0; + /// copies the current view frustum for rendering the view state + virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0; - /// gets the shadow view frustum for rendering the view state - virtual const ViewFrustum& getShadowViewFrustum() = 0; + /// copies the shadow view frustum for rendering the view state + virtual void copyShadowViewFrustum(ViewFrustum& viewOut) const = 0; virtual QThread* getMainThread() = 0; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 000446d9df..444c52623e 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -202,7 +202,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); auto config = std::static_pointer_cast(renderContext->jobConfig); @@ -215,8 +215,8 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R glm::mat4 projMat; Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index d2fda542b1..9c288f96ff 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -42,7 +42,7 @@ struct BackToFrontSort { void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) { assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args->hasViewFrustum()); auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->args; @@ -60,7 +60,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende for (auto itemDetails : inItems) { auto item = scene->getItem(itemDetails.id); auto bound = itemDetails.bound; // item.getBound(); - float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter()); + float distance = args->getViewFrustum().distanceToCamera(bound.calcCenter()); itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound)); } From 2cbc771eba52088fc883b90e1d94f6300c3b415a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 7 Mar 2016 11:20:34 -0800 Subject: [PATCH 06/14] reorder data members, remove cruft, 744->616 bytes --- libraries/shared/src/ViewFrustum.cpp | 60 ++-------------------------- libraries/shared/src/ViewFrustum.h | 29 ++++++-------- 2 files changed, 16 insertions(+), 73 deletions(-) diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 3e52a9f2c8..0412994f28 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -54,11 +54,11 @@ static const glm::vec4 NDC_VALUES[NUM_FRUSTUM_CORNERS] = { void ViewFrustum::setProjection(const glm::mat4& projection) { _projection = projection; - _inverseProjection = glm::inverse(projection); + glm::mat4 inverseProjection = glm::inverse(projection); // compute our dimensions the usual way for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) { - _corners[i] = _inverseProjection * NDC_VALUES[i]; + _corners[i] = inverseProjection * NDC_VALUES[i]; _corners[i] /= _corners[i].w; } _nearClip = -_corners[BOTTOM_LEFT_NEAR].z; @@ -66,12 +66,12 @@ void ViewFrustum::setProjection(const glm::mat4& projection) { _aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) / (_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y); - glm::vec4 top = _inverseProjection * vec4(0.0f, 1.0f, -1.0f, 1.0f); + glm::vec4 top = inverseProjection * vec4(0.0f, 1.0f, -1.0f, 1.0f); top /= top.w; _fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0.0f, 0.0f, -1.0f), glm::normalize(vec3(top)))))); } -// ViewFrustum::calculateViewFrustum() +// ViewFrustum::calculate() // // Description: this will calculate the view frustum bounds for a given position and direction // @@ -112,9 +112,6 @@ void ViewFrustum::calculate() { // Projection matrix : Field of View, ratio, display range : near to far glm::vec3 lookAt = _position + _direction; glm::mat4 view = glm::lookAt(_position, lookAt, _up); - - // Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it) - _ourModelViewProjectionMatrix = _projection * view; // Remember, matrix multiplication is the other way around } //enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; @@ -460,52 +457,3 @@ void ViewFrustum::invalidate() { } _centerSphereRadius = -1.0e6f; // -10^6 should be negative enough } - -/* -float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale, float maxScale, int boundaryLevelAdjust) const { - float distanceToCamera = glm::length(bounds.calcCenter() - getPosition()); - float largestDimension = bounds.getLargestDimension(); - - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; - - static std::once_flag once; - static QMap shouldRenderTable; - std::call_once(once, [&] { - float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small - float scale = maxScale; - float factor = 1.0f; - - while (scale > SMALLEST_SCALE_IN_TABLE) { - scale /= 2.0f; - factor /= 2.0f; - shouldRenderTable[scale] = factor; - } - }); - - float closestScale = maxScale; - float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale; - QMap::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension); - if (lowerBound != shouldRenderTable.constEnd()) { - closestScale = lowerBound.key(); - visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value(); - } - - if (closestScale < largestDimension) { - visibleDistanceAtClosestScale *= 2.0f; - } - - // FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return - // a floating point for objects that have small angular size to indicate that they may be rendered - // with lower preciscion - return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f; -} - -float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) { - return voxelSizeScale / powf(2, renderLevel); -} - -float getAccuracyAngle(float octreeSizeScale, float maxScale, int boundaryLevelAdjust) const { - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; - return atan(maxScale / visibleDistanceAtMaxScale); -} -*/ diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 897f0c77d7..fc091d4bc3 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -132,38 +132,33 @@ public: void invalidate(); // causes all reasonable intersection tests to fail private: - // camera location/orientation attributes - glm::vec3 _position; // the position in world-frame - glm::quat _orientation; glm::mat4 _view; - - // Lens attributes glm::mat4 _projection; - // calculated for orientation + ::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum + + glm::vec3 _position; // position in world-frame + glm::quat _orientation; // orientation in world-frame + + // calculated from orientation glm::vec3 _direction = IDENTITY_FRONT; glm::vec3 _up = IDENTITY_UP; glm::vec3 _right = IDENTITY_RIGHT; + // calculated from projection + glm::vec4 _corners[NUM_FRUSTUM_CORNERS]; + glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS]; float _centerSphereRadius = DEFAULT_CENTER_SPHERE_RADIUS; - - // Calculated values - glm::mat4 _inverseProjection; float _width { 1.0f }; float _height { 1.0f }; float _aspectRatio { 1.0f }; - float _nearClip { DEFAULT_NEAR_CLIP }; - float _farClip { DEFAULT_FAR_CLIP }; float _focalLength { 0.25f }; float _fieldOfView { DEFAULT_FIELD_OF_VIEW_DEGREES }; - glm::vec4 _corners[NUM_FRUSTUM_CORNERS]; - glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS]; - ::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum + + float _nearClip { DEFAULT_NEAR_CLIP }; + float _farClip { DEFAULT_FAR_CLIP }; const char* debugPlaneName (int plane) const; - - // Used to project points - glm::mat4 _ourModelViewProjectionMatrix; }; using ViewFrustumPointer = std::shared_ptr; From 7d6424bdcc903faff096c7b8504b919b13a06c86 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 7 Mar 2016 15:18:33 -0800 Subject: [PATCH 07/14] Head::render() was cruft --- interface/src/avatar/Head.cpp | 3 --- interface/src/avatar/Head.h | 1 - interface/src/avatar/MyAvatar.cpp | 7 +------ libraries/entities/src/EntityTreeElement.cpp | 2 +- 4 files changed, 2 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 8a58e5d740..1e274562b2 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -316,9 +316,6 @@ void Head::relaxLean(float deltaTime) { _deltaLeanForward *= relaxationFactor; } -void Head::render(RenderArgs* renderArgs, float alpha) { -} - void Head::renderLookAts(RenderArgs* renderArgs) { renderLookAts(renderArgs, _leftEyePosition, _rightEyePosition); } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index ef9584f1a7..1f1483d8ed 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -32,7 +32,6 @@ public: void init(); void reset(); void simulate(float deltaTime, bool isMine, bool billboard = false); - void render(RenderArgs* renderArgs, float alpha); void setScale(float scale); void setPosition(glm::vec3 position) { _position = position; } void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d4e024e49e..52ad98b29f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1271,11 +1271,6 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, float glowLevel) { fixupModelsInScene(); - // Render head so long as the camera isn't inside it - if (shouldRenderHead(renderArgs)) { - getHead()->render(renderArgs, 1.0f); - } - // This is drawing the lookat vectors from our avatar to wherever we're looking. if (qApp->isHMDMode()) { glm::vec3 cameraPosition = qApp->getCamera()->getPosition(); @@ -1356,7 +1351,6 @@ void MyAvatar::destroyAnimGraph() { void MyAvatar::preRender(RenderArgs* renderArgs) { render::ScenePointer scene = qApp->getMain3DScene(); - const bool shouldDrawHead = shouldRenderHead(renderArgs); if (_skeletonModel->initWhenReady(scene)) { initHeadBones(); @@ -1408,6 +1402,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { DebugDraw::getInstance().updateMyAvatarPos(getPosition()); DebugDraw::getInstance().updateMyAvatarRot(getOrientation()); + const bool shouldDrawHead = shouldRenderHead(renderArgs); if (shouldDrawHead != _prevShouldDrawHead) { _skeletonModel->setCauterizeBones(!shouldDrawHead); } diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 88227416d3..870c4a88d1 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -298,7 +298,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID()); } - if (includeThisEntity) { + if (includeThisEntity || params.recurseEverything) { // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of // simulation changing what's visible. consider the case where the entity contains an angular velocity From 64c2e2d1757d3c59784c7fabf515bbecf12bb692 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 7 Mar 2016 15:49:11 -0800 Subject: [PATCH 08/14] remove warning about unused variable --- libraries/shared/src/ViewFrustum.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 0412994f28..d6ba9e1dce 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -107,11 +107,6 @@ void ViewFrustum::calculate() { _planes[RIGHT_PLANE].set3Points(_cornersWorld[BOTTOM_RIGHT_FAR], _cornersWorld[BOTTOM_RIGHT_NEAR], _cornersWorld[TOP_RIGHT_FAR]); _planes[NEAR_PLANE].set3Points(_cornersWorld[BOTTOM_RIGHT_NEAR], _cornersWorld[BOTTOM_LEFT_NEAR], _cornersWorld[TOP_LEFT_NEAR]); _planes[FAR_PLANE].set3Points(_cornersWorld[BOTTOM_LEFT_FAR], _cornersWorld[BOTTOM_RIGHT_FAR], _cornersWorld[TOP_RIGHT_FAR]); - - // Also calculate our projection matrix in case people want to project points... - // Projection matrix : Field of View, ratio, display range : near to far - glm::vec3 lookAt = _position + _direction; - glm::mat4 view = glm::lookAt(_position, lookAt, _up); } //enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; From 01950fba965df58c0ff45d73f53f4bb1b6fa4790 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 9 Mar 2016 11:50:34 -0800 Subject: [PATCH 09/14] recover unused code that may prove useful someday --- .../src/CubeProjectedPolygon.cpp} | 96 ++++---- .../src/CubeProjectedPolygon.h} | 76 +++--- libraries/shared/src/ViewFrustum.cpp | 217 ++++++++++++++++++ libraries/shared/src/ViewFrustum.h | 10 + 4 files changed, 313 insertions(+), 86 deletions(-) rename libraries/{octree/src/OctreeProjectedPolygon.cpp => shared/src/CubeProjectedPolygon.cpp} (93%) rename libraries/{octree/src/OctreeProjectedPolygon.h => shared/src/CubeProjectedPolygon.h} (64%) diff --git a/libraries/octree/src/OctreeProjectedPolygon.cpp b/libraries/shared/src/CubeProjectedPolygon.cpp similarity index 93% rename from libraries/octree/src/OctreeProjectedPolygon.cpp rename to libraries/shared/src/CubeProjectedPolygon.cpp index b8e2d4d999..04d6e8bb4e 100644 --- a/libraries/octree/src/OctreeProjectedPolygon.cpp +++ b/libraries/shared/src/CubeProjectedPolygon.cpp @@ -1,6 +1,6 @@ // -// OctreeProjectedPolygon.cpp -// libraries/octree/src +// CubeProjectedPolygon.cpp +// libraries/shared/src // // Created by Brad Hefta-Gaub on 06/11/13. // Copyright 2013 High Fidelity, Inc. @@ -15,50 +15,50 @@ #include "GeometryUtil.h" #include "SharedUtil.h" -#include "OctreeLogging.h" -#include "OctreeProjectedPolygon.h" +#include "SharedLogging.h" +#include "CubeProjectedPolygon.h" -glm::vec2 BoundingBox::getVertex(int vertexNumber) const { +glm::vec2 BoundingRectangle::getVertex(int vertexNumber) const { switch (vertexNumber) { - case BoundingBox::BOTTOM_LEFT: + case BoundingRectangle::BOTTOM_LEFT: return corner; - case BoundingBox::TOP_LEFT: + case BoundingRectangle::TOP_LEFT: return glm::vec2(corner.x, corner.y + size.y); - case BoundingBox::BOTTOM_RIGHT: + case BoundingRectangle::BOTTOM_RIGHT: return glm::vec2(corner.x + size.x, corner.y); - case BoundingBox::TOP_RIGHT: + case BoundingRectangle::TOP_RIGHT: return corner + size; } assert(false); // not allowed return glm::vec2(0,0); } -BoundingBox BoundingBox::topHalf() const { +BoundingRectangle BoundingRectangle::topHalf() const { float halfY = size.y/2.0f; - BoundingBox result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY)); + BoundingRectangle result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY)); return result; } -BoundingBox BoundingBox::bottomHalf() const { +BoundingRectangle BoundingRectangle::bottomHalf() const { float halfY = size.y/2.0f; - BoundingBox result(corner, glm::vec2(size.x, halfY)); + BoundingRectangle result(corner, glm::vec2(size.x, halfY)); return result; } -BoundingBox BoundingBox::leftHalf() const { +BoundingRectangle BoundingRectangle::leftHalf() const { float halfX = size.x/2.0f; - BoundingBox result(corner, glm::vec2(halfX, size.y)); + BoundingRectangle result(corner, glm::vec2(halfX, size.y)); return result; } -BoundingBox BoundingBox::rightHalf() const { +BoundingRectangle BoundingRectangle::rightHalf() const { float halfX = size.x/2.0f; - BoundingBox result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y)); + BoundingRectangle result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y)); return result; } -bool BoundingBox::contains(const BoundingBox& box) const { +bool BoundingRectangle::contains(const BoundingRectangle& box) const { return ( _set && (box.corner.x >= corner.x) && (box.corner.y >= corner.y) && @@ -67,7 +67,7 @@ bool BoundingBox::contains(const BoundingBox& box) const { ); } -bool BoundingBox::contains(const glm::vec2& point) const { +bool BoundingRectangle::contains(const glm::vec2& point) const { return ( _set && (point.x > corner.x) && (point.y > corner.y) && @@ -76,7 +76,7 @@ bool BoundingBox::contains(const glm::vec2& point) const { ); } -void BoundingBox::explandToInclude(const BoundingBox& box) { +void BoundingRectangle::explandToInclude(const BoundingRectangle& box) { if (!_set) { corner = box.corner; size = box.size; @@ -94,20 +94,20 @@ void BoundingBox::explandToInclude(const BoundingBox& box) { } -void BoundingBox::printDebugDetails(const char* label) const { - qCDebug(octree, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]", - (label ? label : "BoundingBox"), +void BoundingRectangle::printDebugDetails(const char* label) const { + qCDebug(shared, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]", + (label ? label : "BoundingRectangle"), debug::valueOf(_set), (double)corner.x, (double)corner.y, (double)size.x, (double)size.y, (double)corner.x, (double)corner.y, (double)(corner.x+size.x), (double)(corner.y+size.y)); } -long OctreeProjectedPolygon::pointInside_calls = 0; -long OctreeProjectedPolygon::occludes_calls = 0; -long OctreeProjectedPolygon::intersects_calls = 0; +long CubeProjectedPolygon::pointInside_calls = 0; +long CubeProjectedPolygon::occludes_calls = 0; +long CubeProjectedPolygon::intersects_calls = 0; -OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) : +CubeProjectedPolygon::CubeProjectedPolygon(const BoundingRectangle& box) : _vertexCount(4), _maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX), _distance(0) @@ -118,7 +118,7 @@ OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) : } -void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) { +void CubeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) { _vertices[vertex] = point; // keep track of our bounding box @@ -138,9 +138,9 @@ void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) { } // can be optimized with new pointInside() -bool OctreeProjectedPolygon::occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView) const { +bool CubeProjectedPolygon::occludes(const CubeProjectedPolygon& occludee, bool checkAllInView) const { - OctreeProjectedPolygon::occludes_calls++; + CubeProjectedPolygon::occludes_calls++; // if we are completely out of view, then we definitely don't occlude! // 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 return false; // if we got this far, then we're not occluded } -bool OctreeProjectedPolygon::occludes(const BoundingBox& boxOccludee) const { - OctreeProjectedPolygon testee(boxOccludee); +bool CubeProjectedPolygon::occludes(const BoundingRectangle& boxOccludee) const { + CubeProjectedPolygon testee(boxOccludee); return occludes(testee); } -bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const { +bool CubeProjectedPolygon::matches(const CubeProjectedPolygon& testee) const { if (testee.getVertexCount() != getVertexCount()) { return false; } @@ -231,14 +231,14 @@ bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const return true; // all of our vertices match, therefore we're the same } -bool OctreeProjectedPolygon::matches(const BoundingBox& box) const { - OctreeProjectedPolygon testee(box); +bool CubeProjectedPolygon::matches(const BoundingRectangle& box) const { + CubeProjectedPolygon testee(box); return matches(testee); } -bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const { +bool CubeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const { - OctreeProjectedPolygon::pointInside_calls++; + CubeProjectedPolygon::pointInside_calls++; // first check the bounding boxes, the point must be fully within the boounding box of this polygon if ((point.x > getMaxX()) || @@ -264,23 +264,23 @@ bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVe return true; } -void OctreeProjectedPolygon::printDebugDetails() const { - qCDebug(octree, "OctreeProjectedPolygon..." +void CubeProjectedPolygon::printDebugDetails() const { + qCDebug(shared, "CubeProjectedPolygon..." " minX=%f maxX=%f minY=%f maxY=%f", (double)getMinX(), (double)getMaxX(), (double)getMinY(), (double)getMaxY()); - qCDebug(octree, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance()); + qCDebug(shared, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance()); for (int i = 0; i < getVertexCount(); i++) { glm::vec2 point = getVertex(i); - qCDebug(octree, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y); + qCDebug(shared, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y); } } -bool OctreeProjectedPolygon::intersects(const BoundingBox& box) const { - OctreeProjectedPolygon testee(box); +bool CubeProjectedPolygon::intersects(const BoundingRectangle& box) const { + CubeProjectedPolygon testee(box); return intersects(testee); } -bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) const { - OctreeProjectedPolygon::intersects_calls++; +bool CubeProjectedPolygon::intersects(const CubeProjectedPolygon& testee) const { + CubeProjectedPolygon::intersects_calls++; return intersectsOnAxes(testee) && testee.intersectsOnAxes(*this); } @@ -294,7 +294,7 @@ bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) co // Note: this only works on convex polygons // // -bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& testee) const { +bool CubeProjectedPolygon::intersectsOnAxes(const CubeProjectedPolygon& testee) const { // consider each edge of this polygon as a potential separating axis for (int i = 0; i < getVertexCount(); i++) { @@ -324,7 +324,7 @@ bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& test return true; } -bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const { +bool CubeProjectedPolygon::canMerge(const CubeProjectedPolygon& that) const { // RIGHT/NEAR // LEFT/NEAR @@ -642,7 +642,7 @@ bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const } -void OctreeProjectedPolygon::merge(const OctreeProjectedPolygon& that) { +void CubeProjectedPolygon::merge(const CubeProjectedPolygon& that) { // RIGHT/NEAR // LEFT/NEAR diff --git a/libraries/octree/src/OctreeProjectedPolygon.h b/libraries/shared/src/CubeProjectedPolygon.h similarity index 64% rename from libraries/octree/src/OctreeProjectedPolygon.h rename to libraries/shared/src/CubeProjectedPolygon.h index a8507e8fb2..6eb35e100b 100644 --- a/libraries/octree/src/OctreeProjectedPolygon.h +++ b/libraries/shared/src/CubeProjectedPolygon.h @@ -1,55 +1,55 @@ // -// OctreeProjectedPolygon.h -// libraries/octree/src +// CubeProjectedPolygon.h +// libraries/shared/src // // Created by Brad Hefta-Gaub on 06/11/13. // Copyright 2013 High Fidelity, Inc. // -// The projected shadow (on the 2D view plane) for a voxel +// The projected shadow (on the 2D view plane) for a cube // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_OctreeProjectedPolygon_h -#define hifi_OctreeProjectedPolygon_h +#ifndef hifi_CubeProjectedPolygon_h +#define hifi_CubeProjectedPolygon_h #include // there's a max of 6 vertices of a project polygon, and a max of twice that when clipped to the screen -const int MAX_PROJECTED_POLYGON_VERTEX_COUNT = 6; -const int MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT = MAX_PROJECTED_POLYGON_VERTEX_COUNT * 2; +const int MAX_PROJECTED_POLYGON_VERTEX_COUNT = 6; +const int MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT = MAX_PROJECTED_POLYGON_VERTEX_COUNT * 2; typedef glm::vec2 ProjectedVertices[MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT]; -class BoundingBox { +class BoundingRectangle { public: enum { BOTTOM_LEFT, BOTTOM_RIGHT, TOP_RIGHT, TOP_LEFT, VERTEX_COUNT }; - BoundingBox(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {} - BoundingBox() : _set(false) {} + BoundingRectangle(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {} + BoundingRectangle() : _set(false) {} glm::vec2 corner; glm::vec2 size; - bool contains(const BoundingBox& box) const; + bool contains(const BoundingRectangle& box) const; bool contains(const glm::vec2& point) const; bool pointInside(const glm::vec2& point) const { return contains(point); } - void explandToInclude(const BoundingBox& box); + void explandToInclude(const BoundingRectangle& box); float area() const { return size.x * size.y; } int getVertexCount() const { return VERTEX_COUNT; } glm::vec2 getVertex(int vertexNumber) const; - BoundingBox topHalf() const; - BoundingBox bottomHalf() const; - BoundingBox leftHalf() const; - BoundingBox rightHalf() const; + BoundingRectangle topHalf() const; + BoundingRectangle bottomHalf() const; + BoundingRectangle leftHalf() const; + BoundingRectangle rightHalf() const; float getMaxX() const { return corner.x + size.x; } float getMaxY() const { return corner.y + size.y; } float getMinX() const { return corner.x; } float getMinY() const { return corner.y; } - + void printDebugDetails(const char* label=NULL) const; private: bool _set; @@ -63,18 +63,18 @@ const int PROJECTION_NEAR = 16; const int PROJECTION_FAR = 32; const int PROJECTION_CLIPPED = 64; -class OctreeProjectedPolygon { +class CubeProjectedPolygon { public: - OctreeProjectedPolygon(const BoundingBox& box); + CubeProjectedPolygon(const BoundingRectangle& box); - OctreeProjectedPolygon(int vertexCount = 0) : - _vertexCount(vertexCount), + CubeProjectedPolygon(int vertexCount = 0) : + _vertexCount(vertexCount), _maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX), _distance(0) { } - - ~OctreeProjectedPolygon() { } + + ~CubeProjectedPolygon() { } const ProjectedVertices& getVertices() const { return _vertices; } const glm::vec2& getVertex(int i) const { return _vertices[i]; } void setVertex(int vertex, const glm::vec2& point); @@ -92,28 +92,28 @@ public: bool pointInside(const glm::vec2& point, bool* matchesVertex = NULL) const; - bool occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView = false) const; - bool occludes(const BoundingBox& occludee) const; - bool intersects(const OctreeProjectedPolygon& testee) const; - bool intersects(const BoundingBox& box) const; - bool matches(const OctreeProjectedPolygon& testee) const; - bool matches(const BoundingBox& testee) const; - bool intersectsOnAxes(const OctreeProjectedPolygon& testee) const; + bool occludes(const CubeProjectedPolygon& occludee, bool checkAllInView = false) const; + bool occludes(const BoundingRectangle& occludee) const; + bool intersects(const CubeProjectedPolygon& testee) const; + bool intersects(const BoundingRectangle& box) const; + bool matches(const CubeProjectedPolygon& testee) const; + bool matches(const BoundingRectangle& testee) const; + bool intersectsOnAxes(const CubeProjectedPolygon& testee) const; + + bool canMerge(const CubeProjectedPolygon& that) const; + void merge(const CubeProjectedPolygon& that); // replaces vertices of this with new merged version - bool canMerge(const OctreeProjectedPolygon& that) const; - void merge(const OctreeProjectedPolygon& that); // replaces vertices of this with new merged version - float getMaxX() const { return _maxX; } float getMaxY() const { return _maxY; } float getMinX() const { return _minX; } float getMinY() const { return _minY; } - - BoundingBox getBoundingBox() const { - return BoundingBox(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY)); + + BoundingRectangle getBoundingBox() const { + return BoundingRectangle(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY)); } void printDebugDetails() const; - + static long pointInside_calls; static long occludes_calls; static long intersects_calls; @@ -132,4 +132,4 @@ private: }; -#endif // hifi_OctreeProjectedPolygon_h +#endif // hifi_CubeProjectedPolygon_h diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index d6ba9e1dce..4a7d4eff95 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -107,6 +107,14 @@ void ViewFrustum::calculate() { _planes[RIGHT_PLANE].set3Points(_cornersWorld[BOTTOM_RIGHT_FAR], _cornersWorld[BOTTOM_RIGHT_NEAR], _cornersWorld[TOP_RIGHT_FAR]); _planes[NEAR_PLANE].set3Points(_cornersWorld[BOTTOM_RIGHT_NEAR], _cornersWorld[BOTTOM_LEFT_NEAR], _cornersWorld[TOP_LEFT_NEAR]); _planes[FAR_PLANE].set3Points(_cornersWorld[BOTTOM_LEFT_FAR], _cornersWorld[BOTTOM_RIGHT_FAR], _cornersWorld[TOP_RIGHT_FAR]); + + // Also calculate our projection matrix in case people want to project points... + // Projection matrix : Field of View, ratio, display range : near to far + glm::vec3 lookAt = _position + _direction; + glm::mat4 view = glm::lookAt(_position, lookAt, _up); + + // Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it) + _ourModelViewProjectionMatrix = _projection * view; // Remember, matrix multiplication is the other way around } //enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; @@ -260,6 +268,55 @@ bool testMatches(float lhs, float rhs, float epsilon = EPSILON) { return (fabs(lhs - rhs) <= epsilon); } +bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { + bool result = + testMatches(compareTo._position, _position) && + testMatches(compareTo._direction, _direction) && + testMatches(compareTo._up, _up) && + testMatches(compareTo._right, _right) && + testMatches(compareTo._fieldOfView, _fieldOfView) && + testMatches(compareTo._aspectRatio, _aspectRatio) && + testMatches(compareTo._nearClip, _nearClip) && + testMatches(compareTo._farClip, _farClip) && + testMatches(compareTo._focalLength, _focalLength); + + if (!result && debug) { + qCDebug(shared, "ViewFrustum::matches()... result=%s", debug::valueOf(result)); + qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f", + (testMatches(compareTo._position,_position) ? "MATCHES " : "NO MATCH"), + (double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z, + (double)_position.x, (double)_position.y, (double)_position.z); + qCDebug(shared, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f", + (testMatches(compareTo._direction, _direction) ? "MATCHES " : "NO MATCH"), + (double)compareTo._direction.x, (double)compareTo._direction.y, (double)compareTo._direction.z, + (double)_direction.x, (double)_direction.y, (double)_direction.z ); + qCDebug(shared, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f", + (testMatches(compareTo._up, _up) ? "MATCHES " : "NO MATCH"), + (double)compareTo._up.x, (double)compareTo._up.y, (double)compareTo._up.z, + (double)_up.x, (double)_up.y, (double)_up.z ); + qCDebug(shared, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f", + (testMatches(compareTo._right, _right) ? "MATCHES " : "NO MATCH"), + (double)compareTo._right.x, (double)compareTo._right.y, (double)compareTo._right.z, + (double)_right.x, (double)_right.y, (double)_right.z ); + qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f", + (testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"), + (double)compareTo._fieldOfView, (double)_fieldOfView); + qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f", + (testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"), + (double)compareTo._aspectRatio, (double)_aspectRatio); + qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f", + (testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"), + (double)compareTo._nearClip, (double)_nearClip); + qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f", + (testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"), + (double)compareTo._farClip, (double)_farClip); + qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f", + (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"), + (double)compareTo._focalLength, (double)_focalLength); + } + return result; +} + bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const { // Compute distance between the two positions @@ -383,6 +440,166 @@ void ViewFrustum::printDebugDetails() const { qCDebug(shared, "_focalLength=%f", (double)_focalLength); } +glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const { + + glm::vec4 pointVec4 = glm::vec4(point, 1.0f); + glm::vec4 projectedPointVec4 = _ourModelViewProjectionMatrix * pointVec4; + pointInView = (projectedPointVec4.w > 0.0f); // math! If the w result is negative then the point is behind the viewer + + // what happens with w is 0??? + float x = projectedPointVec4.x / projectedPointVec4.w; + float y = projectedPointVec4.y / projectedPointVec4.w; + glm::vec2 projectedPoint(x,y); + + // if the point is out of view we also need to flip the signs of x and y + if (!pointInView) { + projectedPoint.x = -x; + projectedPoint.y = -y; + } + + return projectedPoint; +} + + +const int MAX_POSSIBLE_COMBINATIONS = 43; + +const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERTEX_COUNT+1] = { + // Number of vertices in shadow polygon for the visible faces, then a list of the index of each vertice from the AACube + +//0 + {0}, // inside + {4, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR}, // right + {4, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, // left + {0}, // n/a + +//4 + {4, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR}, // bottom +//5 + {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR },//bottom, right + {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, },//bottom, left + {0}, // n/a +//8 + {4, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // top + {6, TOP_RIGHT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // top, right + {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // top, left + {0}, // n/a + {0}, // n/a + {0}, // n/a + {0}, // n/a + {0}, // n/a +//16 + {4, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front or near + + {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front, right + {6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, }, // front, left + {0}, // n/a +//20 + {6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front,bottom + +//21 + {6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, //front,bottom,right +//22 + {6, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, //front,bottom,left + {0}, // n/a + + {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // front, top + + {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR }, // front, top, right + + {6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR }, // front, top, left + {0}, // n/a + {0}, // n/a + {0}, // n/a + {0}, // n/a + {0}, // n/a +//32 + {4, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR }, // back + {6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR}, // back, right +//34 + {6, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, TOP_RIGHT_FAR }, // back, left + + + {0}, // n/a +//36 + {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR}, // back, bottom + {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR},//back, bottom, right + +// 38 + {6, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR },//back, bottom, left + {0}, // n/a + +// 40 + {6, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR}, // back, top + + {6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, TOP_RIGHT_NEAR}, // back, top, right +//42 + {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left +}; + +CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { + const glm::vec3& bottomNearRight = box.getCorner(); + glm::vec3 topFarLeft = box.calcTopFarLeft(); + + int lookUp = ((_position.x < bottomNearRight.x) ) // 1 = right | compute 6-bit + + ((_position.x > topFarLeft.x ) << 1) // 2 = left | code to + + ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera + + ((_position.y > topFarLeft.y ) << 3) // 8 = top | with respect to + + ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining + + ((_position.z > topFarLeft.z ) << 5); // 32 = back/far | planes + + int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices + + CubeProjectedPolygon projectedPolygon(vertexCount); + + bool pointInView = true; + bool allPointsInView = false; // assume the best, but wait till we know we have a vertex + bool anyPointsInView = false; // assume the worst! + if (vertexCount) { + allPointsInView = true; // assume the best! + for(int i = 0; i < vertexCount; i++) { + int vertexNum = hullVertexLookup[lookUp][i+1]; + glm::vec3 point = box.getVertex((BoxVertex)vertexNum); + glm::vec2 projectedPoint = projectPoint(point, pointInView); + allPointsInView = allPointsInView && pointInView; + anyPointsInView = anyPointsInView || pointInView; + projectedPolygon.setVertex(i, projectedPoint); + } + + /*** + // Now that we've got the polygon, if it extends beyond the clipping window, then let's clip it + // NOTE: This clipping does not improve our overall performance. It basically causes more polygons to + // end up in the same quad/half and so the polygon lists get longer, and that's more calls to polygon.occludes() + if ( (projectedPolygon.getMaxX() > PolygonClip::RIGHT_OF_CLIPPING_WINDOW ) || + (projectedPolygon.getMaxY() > PolygonClip::TOP_OF_CLIPPING_WINDOW ) || + (projectedPolygon.getMaxX() < PolygonClip::LEFT_OF_CLIPPING_WINDOW ) || + (projectedPolygon.getMaxY() < PolygonClip::BOTTOM_OF_CLIPPING_WINDOW) ) { + + CoverageRegion::_clippedPolygons++; + + glm::vec2* clippedVertices; + int clippedVertexCount; + PolygonClip::clipToScreen(projectedPolygon.getVertices(), vertexCount, clippedVertices, clippedVertexCount); + + // Now reset the vertices of our projectedPolygon object + projectedPolygon.setVertexCount(clippedVertexCount); + for(int i = 0; i < clippedVertexCount; i++) { + projectedPolygon.setVertex(i, clippedVertices[i]); + } + delete[] clippedVertices; + + lookUp += PROJECTION_CLIPPED; + } + ***/ + } + // set the distance from our camera position, to the closest vertex + float distance = glm::distance(getPosition(), box.calcCenter()); + projectedPolygon.setDistance(distance); + projectedPolygon.setAnyInView(anyPointsInView); + projectedPolygon.setAllInView(allPointsInView); + projectedPolygon.setProjectionType(lookUp); // remember the projection type + return projectedPolygon; +} + // Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for // squares and square-roots. Just compares. diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index fc091d4bc3..6d0bdb0fda 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -21,6 +21,7 @@ #include "AABox.h" #include "AACube.h" +#include "CubeProjectedPolygon.h" #include "Plane.h" #include "RegisteredMetaTypes.h" #include "Transform.h" @@ -108,6 +109,10 @@ public: bool cubeIntersectsKeyhole(const AACube& cube) const; bool boxIntersectsKeyhole(const AABox& box) const; + // some frustum comparisons + bool matches(const ViewFrustum& compareTo, bool debug = false) const; + bool matches(const ViewFrustum* compareTo, bool debug = false) const { return matches(*compareTo, debug); } + bool isVerySimilar(const ViewFrustum& compareTo, bool debug = false) const; bool isVerySimilar(const ViewFrustum* compareTo, bool debug = false) const { return isVerySimilar(*compareTo, debug); } @@ -119,6 +124,8 @@ public: void printDebugDetails() const; + glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const; + CubeProjectedPolygon getProjectedPolygon(const AACube& box) const; void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; float distanceToCamera(const glm::vec3& point) const; @@ -159,6 +166,9 @@ private: float _farClip { DEFAULT_FAR_CLIP }; const char* debugPlaneName (int plane) const; + + // Used to project points + glm::mat4 _ourModelViewProjectionMatrix; }; using ViewFrustumPointer = std::shared_ptr; From eeb100b62fd27be551bba0d75a3293626e64d04a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 May 2016 16:04:01 -0700 Subject: [PATCH 10/14] use glm::isnan() instead of isnan() from math.h --- libraries/shared/src/PIDController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/PIDController.cpp b/libraries/shared/src/PIDController.cpp index 0d1d267dea..790c26ac25 100644 --- a/libraries/shared/src/PIDController.cpp +++ b/libraries/shared/src/PIDController.cpp @@ -35,7 +35,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue); } Q_ASSERT(!glm::isnan(computedValue)); - + // update state for next time _lastError = error; _lastAccumulation = accumulatedError; From d1591e03b9ac4282b99d6f93574a94d79ac02e3f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 May 2016 17:08:31 -0700 Subject: [PATCH 11/14] fix typo --- libraries/render/src/render/SortTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index 9c288f96ff..28860aa410 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -1,5 +1,5 @@ // -// CullTask.cpp +// SortTask.cpp // render/src/render // // Created by Sam Gateau on 2/2/16. From 635e2e78e3661f40351c8b2d947caa42a0c32934 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 May 2016 18:43:08 -0700 Subject: [PATCH 12/14] minor cleanup --- interface/src/Application.cpp | 31 +++++++++++++------------------ interface/src/Application.h | 2 +- interface/src/avatar/Avatar.cpp | 2 +- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 19b0e432e1..83cd577b52 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3651,19 +3651,16 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node //qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView(); bool wantExtraDebugging = getLogger()->extraDebugging(); - ViewFrustum viewFrustumCopy; - { - QMutexLocker viewLocker(&_viewMutex); - viewFrustumCopy = _viewFrustum; - } - _octreeQuery.setCameraPosition(viewFrustumCopy.getPosition()); - _octreeQuery.setCameraOrientation(viewFrustumCopy.getOrientation()); - _octreeQuery.setCameraFov(viewFrustumCopy.getFieldOfView()); - _octreeQuery.setCameraAspectRatio(viewFrustumCopy.getAspectRatio()); - _octreeQuery.setCameraNearClip(viewFrustumCopy.getNearClip()); - _octreeQuery.setCameraFarClip(viewFrustumCopy.getFarClip()); + ViewFrustum viewFrustum; + copyViewFrustum(viewFrustum); + _octreeQuery.setCameraPosition(viewFrustum.getPosition()); + _octreeQuery.setCameraOrientation(viewFrustum.getOrientation()); + _octreeQuery.setCameraFov(viewFrustum.getFieldOfView()); + _octreeQuery.setCameraAspectRatio(viewFrustum.getAspectRatio()); + _octreeQuery.setCameraNearClip(viewFrustum.getNearClip()); + _octreeQuery.setCameraFarClip(viewFrustum.getFarClip()); _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); - _octreeQuery.setCameraCenterRadius(viewFrustumCopy.getCenterRadius()); + _octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius()); auto lodManager = DependencyManager::get(); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); @@ -3699,7 +3696,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node rootDetails.y * TREE_SCALE, rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE), rootDetails.s * TREE_SCALE); - if (viewFrustumCopy.cubeIntersectsKeyhole(serverBounds)) { + if (viewFrustum.cubeIntersectsKeyhole(serverBounds)) { inViewServers++; } } @@ -3765,11 +3762,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node rootDetails.s * TREE_SCALE); - inView = viewFrustumCopy.cubeIntersectsKeyhole(serverBounds); - } else { - if (wantExtraDebugging) { - qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!"; - } + inView = viewFrustum.cubeIntersectsKeyhole(serverBounds); + } else if (wantExtraDebugging) { + qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!"; } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 018265db4a..0fca44c9b6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -167,7 +167,7 @@ public: virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override; - virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override; + virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); } virtual QThread* getMainThread() override { return thread(); } virtual PickRay computePickRay(float x, float y) const override; virtual glm::vec3 getAvatarPosition() const override; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 356b940713..edb63022b0 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -506,7 +506,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { auto cameraMode = qApp->getCamera()->getMode(); if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) { - ViewFrustum frustum = renderArgs->getViewFrustum(); + auto& frustum = renderArgs->getViewFrustum(); auto textPosition = getDisplayNamePosition(); if (frustum.pointIntersectsFrustum(textPosition)) { renderDisplayName(batch, frustum, textPosition); From 778820edb4c4fe85630ae8407524a69633e0839c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 May 2016 09:07:03 -0700 Subject: [PATCH 13/14] fix broken dupe method implementation --- interface/src/Application.cpp | 5 ----- interface/src/Application.h | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 83cd577b52..16d9e0c108 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4519,11 +4519,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface()); } -void Application::copyCurrentViewFrustum(ViewFrustum& viewOut) const { - QMutexLocker viewLocker(&_viewMutex); - viewOut = _displayViewFrustum; -} - bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); if (urlString.startsWith(HIFI_URL_SCHEME)) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 0fca44c9b6..ea5f637d96 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -167,7 +167,7 @@ public: virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override; - virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); } + virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override { copyDisplayViewFrustum(viewOut); } virtual QThread* getMainThread() override { return thread(); } virtual PickRay computePickRay(float x, float y) const override; virtual glm::vec3 getAvatarPosition() const override; From db9a4d6b8f99adc47505efe2756a0569a2b334ef Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 10 May 2016 07:49:11 -0700 Subject: [PATCH 14/14] cleanup for code review --- assignment-client/src/octree/OctreeQueryNode.cpp | 5 +---- libraries/octree/src/Octree.h | 2 -- libraries/octree/src/OctreeRenderer.cpp | 3 +-- libraries/shared/src/RenderArgs.h | 1 - libraries/shared/src/ViewFrustum.h | 2 -- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 364cbf33c1..fa844dc0f8 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -271,10 +271,7 @@ void OctreeQueryNode::dumpOutOfView() { int outOfView = 0; OctreeElementBag tempBag; ViewFrustum viewCopy; - { - QMutexLocker viewLocker(&_viewMutex); - viewCopy = _currentViewFrustum; - } + copyCurrentViewFrustum(viewCopy); while (OctreeElementPointer elementToCheck = elementBag.extract()) { if (elementToCheck->isInView(viewCopy)) { tempBag.insert(elementToCheck); diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 456b086341..2f0ce3b807 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -109,8 +109,6 @@ public: OctreeSceneStats* stats = IGNORE_SCENE_STATS, JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP, OctreeElementExtraEncodeData* extraEncodeData = NULL) : - viewFrustum(), - lastViewFrustum(), lastViewFrustumSent(lastViewFrustumSent), maxEncodeLevel(maxEncodeLevel), maxLevelReached(0), diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index c001bdfc35..a81f946680 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -22,8 +22,7 @@ OctreeRenderer::OctreeRenderer() : _tree(NULL), - _managedTree(false), - _viewFrustum() + _managedTree(false) { } diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 8c66a6a19b..e8f0002fed 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -88,7 +88,6 @@ public: gpu::Batch* batch = nullptr) : _context(context), _renderer(renderer), - _viewFrustums(), _sizeScale(sizeScale), _boundaryLevelAdjust(boundaryLevelAdjust), _renderMode(renderMode), diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 6d0bdb0fda..48d45ab455 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -17,8 +17,6 @@ #include #include -//#include - #include "AABox.h" #include "AACube.h" #include "CubeProjectedPolygon.h"