From bcf2cc8074876a90766ff9a97fe2fac1edfdfce0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sat, 5 Mar 2016 10:38:23 -0800 Subject: [PATCH] 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