From 88af387214546ae4b56186e0c109219f940df040 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 18 Jan 2016 10:10:24 -0800 Subject: [PATCH] cleanup --- interface/src/LODManager.cpp | 85 ++------------------ interface/src/LODManager.h | 1 - libraries/entities/src/EntityTreeElement.cpp | 32 +++++--- libraries/octree/src/OctreeConstants.h | 6 ++ libraries/octree/src/ViewFrustum.cpp | 5 +- libraries/octree/src/ViewFrustum.h | 6 +- 6 files changed, 43 insertions(+), 92 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index d8815be640..4dec925530 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -25,7 +25,7 @@ Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DO // pid: renderDistance is adjusted by a PID such that frame rate targets are met. // acuity: a pseudo-acuity target is held, or adjusted to match minimum frame rates (and a PID controlls avatar rendering distance) // If unspecified, acuity is used only if user has specified non-default minumum frame rates. -Setting::Handle lodPreference("lodPreference", (int)LODManager::LODPreference::unspecified); +Setting::Handle lodPreference("lodPreference", (int)LODManager::LODPreference::acuity); const float SMALLEST_REASONABLE_HORIZON = 50.0f; // meters Setting::Handle renderDistanceInverseHighLimit("renderDistanceInverseHighLimit", 1.0f / SMALLEST_REASONABLE_HORIZON); void LODManager::setRenderDistanceInverseHighLimit(float newValue) { @@ -274,92 +274,23 @@ void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, flo } bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { - float distanceToCamera = glm::length(bounds.calcCenter() - args->_viewFrustum->getPosition()); - float largestDimension = bounds.getLargestDimension(); + // NOTE: this branch of code is the alternate form of LOD that uses PID controllers. if (!getUseAcuity()) { + float distanceToCamera = glm::length(bounds.calcCenter() - args->_viewFrustum->getPosition()); + float largestDimension = bounds.getLargestDimension(); const float scenerySize = 300; // meters bool isRendered = (largestDimension > scenerySize) || // render scenery regardless of distance (distanceToCamera < renderDistance + largestDimension); renderedCount += isRendered ? 1 : 0; return isRendered; } - - const float maxScale = (float)TREE_SCALE; - const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it. - float octreeSizeScale = args->_sizeScale; - int boundaryLevelAdjust = args->_boundaryLevelAdjust; - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio; - - static bool shouldRenderTableNeedsBuilding = true; - static QMap shouldRenderTable; - if (shouldRenderTableNeedsBuilding) { - 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; - } - - shouldRenderTableNeedsBuilding = false; - } - 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; - } - - return distanceToCamera <= visibleDistanceAtClosestScale; + // 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); + return (renderAccuracy > 0.0f); }; -// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells -// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it. -bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) { - const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it. - float octreeSizeScale = getOctreeSizeScale(); - int boundaryLevelAdjust = getBoundaryLevelAdjust(); - float maxScale = (float)TREE_SCALE; - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio; - - if (_shouldRenderTableNeedsRebuilding) { - _shouldRenderTable.clear(); - - float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small - float scale = maxScale; - float visibleDistanceAtScale = visibleDistanceAtMaxScale; - - while (scale > SMALLEST_SCALE_IN_TABLE) { - scale /= 2.0f; - visibleDistanceAtScale /= 2.0f; - _shouldRenderTable[scale] = visibleDistanceAtScale; - } - _shouldRenderTableNeedsRebuilding = false; - } - - float closestScale = maxScale; - float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale; - QMap::const_iterator lowerBound = _shouldRenderTable.lowerBound(largestDimension); - if (lowerBound != _shouldRenderTable.constEnd()) { - closestScale = lowerBound.key(); - visibleDistanceAtClosestScale = lowerBound.value(); - } - - if (closestScale < largestDimension) { - visibleDistanceAtClosestScale *= 2.0f; - } - - return (distanceToCamera <= visibleDistanceAtClosestScale); -} - void LODManager::setOctreeSizeScale(float sizeScale) { _octreeSizeScale = sizeScale; calculateAvatarLODDistanceMultiplier(); diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 6b141004e5..d8fcc50cac 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -104,7 +104,6 @@ public: QString getLODStatsRenderText(); static bool shouldRender(const RenderArgs* args, const AABox& bounds); - bool shouldRenderMesh(float largestDimension, float distanceToCamera); void autoAdjustLOD(float currentFPS); void loadSettings(); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 6d47a286d2..4842197201 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -308,19 +308,27 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData includeThisEntity = false; // out of view, don't include it } - // Now check the size of the entity, it's possible that a "too small to see" entity is included in a larger - // octree cell because of it's position (for example if it crosses the boundary of a cell it pops to the next - // higher cell. So we want to check to see that the entity is large enough to be seen before we consider - // including it. + // Now check the size of the entity, it's possible that a "too small to see" entity is included in a + // larger octree cell because of it's position (for example if it crosses the boundary of a cell it + // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen + // before we consider including it. if (includeThisEntity) { AABox entityBounds = entity->getAABox(success); if (success) { - auto renderAccuracy = params.viewFrustum->calculateRenderAccuracy(entityBounds, params.octreeElementSizeScale, params.boundaryLevelAdjust); - qDebug() << "checking entity:" << entity->getID() << " entityBounds:" << entityBounds << "---renderAccuracy:" << renderAccuracy - << " [ sizeScale:" << params.octreeElementSizeScale << "levelAdjust:" << params.boundaryLevelAdjust << " ]"; + auto renderAccuracy = params.viewFrustum->calculateRenderAccuracy(entityBounds, + params.octreeElementSizeScale, params.boundaryLevelAdjust); + if (renderAccuracy <= 0.0f) { includeThisEntity = false; // too small, don't include it - qDebug() << "returning FALSE... too small..."; + + #ifdef WANT_LOD_DEBUGGING + qDebug() << "skipping entity - TOO SMALL - \n" + << "......id:" << entity->getID() << "\n" + << "....name:" << entity->getName() << "\n" + << "..bounds:" << entityBounds << "\n" + << "....cell:" << getAACube(); + #endif + } } else { includeThisEntity = false; // couldn't get box, don't include it @@ -329,7 +337,13 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData } if (includeThisEntity) { - qDebug() << "including entity:" << entity->getID() << " octree cell:" << getAACube(); + #ifdef WANT_LOD_DEBUGGING + qDebug() << "including entity - \n" + << "......id:" << entity->getID() << "\n" + << "....name:" << entity->getName() << "\n" + << "..bounds:" << entityBounds << "\n" + << "....cell:" << getAACube(); + #endif indexesOfEntitiesToInclude << i; numberOfEntities++; } diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index 0b05a8606c..ea1ea63353 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -23,6 +23,12 @@ const int HALF_TREE_SCALE = TREE_SCALE / 2; // This controls the LOD. Larger number will make smaller voxels visible at greater distance. const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * 400.0f; +// Since entities like models live inside of octree cells, and they themselves can have very small mesh parts, +// we want to have some constant that controls have big a mesh part must be to render even if the octree cell itself +// would be visible. This constanct controls that. It basically means you must be this many times closer to a mesh +// than an octree cell to see the mesh. +const float OCTREE_TO_MESH_RATIO = 4.0f; + // This is used in the LOD Tools to translate between the size scale slider and the values used to set the OctreeSizeScale const float MAX_LOD_SIZE_MULTIPLIER = 4000.0f; diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 63cad25b8b..126eea4f27 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -751,15 +751,12 @@ void ViewFrustum::evalViewTransform(Transform& view) const { view.setRotation(getOrientation()); } -// 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 ViewFrustum::calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale, int boundaryLevelAdjust) const { float distanceToCamera = glm::length(bounds.calcCenter() - getPosition()); float largestDimension = bounds.getLargestDimension(); const float maxScale = (float)TREE_SCALE; - const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it. - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio; + float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; static bool shouldRenderTableNeedsBuilding = true; static QMap shouldRenderTable; diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 0d6170e3ed..43f594b54c 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -107,7 +107,11 @@ public: void evalProjectionMatrix(glm::mat4& proj) const; void evalViewTransform(Transform& view) const; - float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) 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; private: // Used for keyhole calculations