Merge pull request #3602 from ZappoMan/frustumCullModelParts

More Model::render() improvements
This commit is contained in:
AndrewMeadows 2014-10-16 11:04:57 -07:00
commit e75d2a167a
11 changed files with 152 additions and 87 deletions

View file

@ -122,7 +122,8 @@ Menu::Menu() :
_hasLoginDialogDisplayed(false), _hasLoginDialogDisplayed(false),
_snapshotsLocation(), _snapshotsLocation(),
_scriptsLocation(), _scriptsLocation(),
_walletPrivateKey() _walletPrivateKey(),
_shouldRenderTableNeedsRebuilding(true)
{ {
Application *appInstance = Application::getInstance(); Application *appInstance = Application::getInstance();
@ -419,10 +420,12 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false);
QMenu* modelDebugMenu = developerMenu->addMenu("Models"); QMenu* modelDebugMenu = developerMenu->addMenu("Models");
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DontCullMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelBounds, 0, false); addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelBounds, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementProxy, 0, false); addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementProxy, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false); addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false);
QMenu* modelCullingMenu = modelDebugMenu->addMenu("Culling");
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false);
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels"); QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels");
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
@ -1547,6 +1550,7 @@ void Menu::autoAdjustLOD(float currentFPS) {
&& _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { && _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
_voxelSizeScale *= ADJUST_LOD_DOWN_BY; _voxelSizeScale *= ADJUST_LOD_DOWN_BY;
if (_voxelSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { if (_voxelSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
_voxelSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; _voxelSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
} }
@ -1569,6 +1573,7 @@ void Menu::autoAdjustLOD(float currentFPS) {
} }
if (changed) { if (changed) {
_shouldRenderTableNeedsRebuilding = true;
if (_lodToolsDialog) { if (_lodToolsDialog) {
_lodToolsDialog->reloadSliders(); _lodToolsDialog->reloadSliders();
} }
@ -1583,14 +1588,56 @@ void Menu::resetLODAdjust() {
void Menu::setVoxelSizeScale(float sizeScale) { void Menu::setVoxelSizeScale(float sizeScale) {
_voxelSizeScale = sizeScale; _voxelSizeScale = sizeScale;
_shouldRenderTableNeedsRebuilding = true;
bumpSettings(); bumpSettings();
} }
void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) { void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
_boundaryLevelAdjust = boundaryLevelAdjust; _boundaryLevelAdjust = boundaryLevelAdjust;
_shouldRenderTableNeedsRebuilding = true;
bumpSettings(); bumpSettings();
} }
// TODO: This is essentially the same logic used to render voxels, but since models are more detailed then voxels
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) {
const float voxelToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
float voxelSizeScale = getVoxelSizeScale();
int boundaryLevelAdjust = getBoundaryLevelAdjust();
float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, voxelSizeScale) / voxelToMeshRatio;
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<float, float>::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 Menu::lodTools() { void Menu::lodTools() {
if (!_lodToolsDialog) { if (!_lodToolsDialog) {
_lodToolsDialog = new LodToolsDialog(Application::getInstance()->getGLWidget()); _lodToolsDialog = new LodToolsDialog(Application::getInstance()->getGLWidget());

View file

@ -143,6 +143,8 @@ public:
void setBoundaryLevelAdjust(int boundaryLevelAdjust); void setBoundaryLevelAdjust(int boundaryLevelAdjust);
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
SpeechRecognizer* getSpeechRecognizer() { return &_speechRecognizer; } SpeechRecognizer* getSpeechRecognizer() { return &_speechRecognizer; }
#endif #endif
@ -310,6 +312,9 @@ private:
QString _snapshotsLocation; QString _snapshotsLocation;
QString _scriptsLocation; QString _scriptsLocation;
QByteArray _walletPrivateKey; QByteArray _walletPrivateKey;
bool _shouldRenderTableNeedsRebuilding;
QMap<float, float> _shouldRenderTable;
}; };
@ -367,7 +372,8 @@ namespace MenuOption {
const QString Collisions = "Collisions"; const QString Collisions = "Collisions";
const QString Console = "Console..."; const QString Console = "Console...";
const QString ControlWithSpeech = "Control With Speech"; const QString ControlWithSpeech = "Control With Speech";
const QString DontCullMeshParts = "Don't Cull Mesh Parts"; const QString DontCullOutOfViewMeshParts = "Don't Cull Out Of View Mesh Parts";
const QString DontCullTooSmallMeshParts = "Don't Cull Too Small Mesh Parts";
const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DecreaseVoxelSize = "Decrease Voxel Size"; const QString DecreaseVoxelSize = "Decrease Voxel Size";
const QString DisableActivityLogger = "Disable Activity Logger"; const QString DisableActivityLogger = "Disable Activity Logger";

View file

@ -162,36 +162,6 @@ void renderElementProxy(EntityTreeElement* entityTreeElement) {
} }
} }
float EntityTreeRenderer::distanceToCamera(const glm::vec3& center, const ViewFrustum& viewFrustum) const {
glm::vec3 temp = viewFrustum.getPosition() - center;
float distanceToVoxelCenter = sqrtf(glm::dot(temp, temp));
return distanceToVoxelCenter;
}
// TODO: This could be optimized to be a table, or something that doesn't require recalculation on every
// render call for every entity
// TODO: This is essentially the same logic used to render voxels, but since models are more detailed then voxels
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
bool EntityTreeRenderer::shouldRenderEntity(float largestDimension, float distanceToCamera) const {
const float voxelToModelRatio = 4.0f; // must be this many times closer to a model than a voxel to see it.
float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
float scale = (float)TREE_SCALE;
float visibleDistanceAtScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, voxelSizeScale) / voxelToModelRatio;
while (scale > largestDimension) {
scale /= 2.0f;
visibleDistanceAtScale /= 2.0f;
}
if (scale < largestDimension) {
visibleDistanceAtScale *= 2.0f;
}
return (distanceToCamera <= visibleDistanceAtScale);
}
void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* args) { void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* args) {
bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE; bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE;
bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds); bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds);
@ -287,7 +257,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
// TODO: some entity types (like lights) might want to be rendered even // TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum... // when they are outside of the view frustum...
float distance = distanceToCamera(entityBox.calcCenter(), *args->_viewFrustum); float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter());
if (wantDebug) { if (wantDebug) {
qDebug() << "------- renderElement() ----------"; qDebug() << "------- renderElement() ----------";
@ -299,24 +269,28 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
qDebug() << " entityBox:" << entityItem->getAABox(); qDebug() << " entityBox:" << entityItem->getAABox();
qDebug() << " dimensions:" << entityItem->getDimensionsInMeters() << "in meters"; qDebug() << " dimensions:" << entityItem->getDimensionsInMeters() << "in meters";
qDebug() << " largestDimension:" << entityBox.getLargestDimension() << "in meters"; qDebug() << " largestDimension:" << entityBox.getLargestDimension() << "in meters";
qDebug() << " shouldRender:" << shouldRenderEntity(entityBox.getLargestDimension(), distance); qDebug() << " shouldRender:" << Menu::getInstance()->shouldRenderMesh(entityBox.getLargestDimension(), distance);
qDebug() << " in frustum:" << (args->_viewFrustum->boxInFrustum(entityBox) != ViewFrustum::OUTSIDE); qDebug() << " in frustum:" << (args->_viewFrustum->boxInFrustum(entityBox) != ViewFrustum::OUTSIDE);
} }
if (shouldRenderEntity(entityBox.getLargestDimension(), distance) &&
args->_viewFrustum->boxInFrustum(entityBox) != ViewFrustum::OUTSIDE) {
renderProxies(entityItem, args);
Glower* glower = NULL; bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE;
if (entityItem->getGlowLevel() > 0.0f) { if (!outOfView) {
glower = new Glower(entityItem->getGlowLevel()); bool bigEnoughToRender = Menu::getInstance()->shouldRenderMesh(entityBox.getLargestDimension(), distance);
}
entityItem->render(args); if (bigEnoughToRender) {
args->_itemsRendered++; renderProxies(entityItem, args);
if (glower) {
delete glower; Glower* glower = NULL;
if (entityItem->getGlowLevel() > 0.0f) {
glower = new Glower(entityItem->getGlowLevel());
}
entityItem->render(args);
args->_itemsRendered++;
if (glower) {
delete glower;
}
} else {
args->_itemsTooSmall++;
} }
} else { } else {
args->_itemsOutOfView++; args->_itemsOutOfView++;

View file

@ -76,11 +76,7 @@ public:
void deleteReleasedModels(); void deleteReleasedModels();
private: private:
QList<Model*> _releasedModels; QList<Model*> _releasedModels;
float distanceToCamera(const glm::vec3& center, const ViewFrustum& viewFrustum) const;
bool shouldRenderEntity(float largestDimension, float distanceToCamera) const;
void renderProxies(const EntityItem* entity, RenderArgs* args); void renderProxies(const EntityItem* entity, RenderArgs* args);
}; };
#endif // hifi_EntityTreeRenderer_h #endif // hifi_EntityTreeRenderer_h

View file

@ -47,7 +47,7 @@ Model::Model(QObject* parent) :
_blendNumber(0), _blendNumber(0),
_appliedBlendNumber(0), _appliedBlendNumber(0),
_calculatedMeshBoxesValid(false), _calculatedMeshBoxesValid(false),
_meshesGroupsKnown(false) { _meshGroupsKnown(false) {
// we may have been created in the network thread, but we live in the main thread // we may have been created in the network thread, but we live in the main thread
moveToThread(Application::getInstance()->thread()); moveToThread(Application::getInstance()->thread());
@ -273,7 +273,7 @@ void Model::reset() {
_jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation, 0.0f); _jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation, 0.0f);
} }
_meshesGroupsKnown = false; _meshGroupsKnown = false;
} }
bool Model::updateGeometry() { bool Model::updateGeometry() {
@ -323,7 +323,7 @@ bool Model::updateGeometry() {
deleteGeometry(); deleteGeometry();
_dilatedTextures.clear(); _dilatedTextures.clear();
_geometry = geometry; _geometry = geometry;
_meshesGroupsKnown = false; _meshGroupsKnown = false;
setJointStates(newJointStates); setJointStates(newJointStates);
needToRebuild = true; needToRebuild = true;
} else if (_jointStates.isEmpty()) { } else if (_jointStates.isEmpty()) {
@ -426,7 +426,7 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
} }
} }
if (!_meshesGroupsKnown) { if (!_meshGroupsKnown) {
segregateMeshGroups(); segregateMeshGroups();
} }
@ -1247,7 +1247,7 @@ void Model::applyNextGeometry() {
// we retain a reference to the base geometry so that its reference count doesn't fall to zero // we retain a reference to the base geometry so that its reference count doesn't fall to zero
_baseGeometry = _nextBaseGeometry; _baseGeometry = _nextBaseGeometry;
_geometry = _nextGeometry; _geometry = _nextGeometry;
_meshesGroupsKnown = false; _meshGroupsKnown = false;
_nextBaseGeometry.reset(); _nextBaseGeometry.reset();
_nextGeometry.reset(); _nextGeometry.reset();
} }
@ -1380,7 +1380,7 @@ void Model::segregateMeshGroups() {
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
} }
} }
_meshesGroupsKnown = true; _meshGroupsKnown = true;
} }
int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
@ -1390,10 +1390,8 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
const FBXGeometry& geometry = _geometry->getFBXGeometry(); const FBXGeometry& geometry = _geometry->getFBXGeometry();
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes(); const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
bool cullMeshParts = args && !Menu::getInstance()->isOptionChecked(MenuOption::DontCullMeshParts);
// depending on which parameters we were called with, pick the correct mesh group to render // depending on which parameters we were called with, pick the correct mesh group to render
QList<int>* whichList = NULL; QVector<int>* whichList = NULL;
if (translucent && !hasTangents && !hasSpecular && !isSkinned) { if (translucent && !hasTangents && !hasSpecular && !isSkinned) {
whichList = &_meshesTranslucent; whichList = &_meshesTranslucent;
} else if (translucent && hasTangents && !hasSpecular && !isSkinned) { } else if (translucent && hasTangents && !hasSpecular && !isSkinned) {
@ -1434,7 +1432,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
qDebug() << "unexpected!!! we don't know which list of meshes to render..."; qDebug() << "unexpected!!! we don't know which list of meshes to render...";
return 0; return 0;
} }
QList<int>& list = *whichList; QVector<int>& list = *whichList;
ProgramObject* program = &_program; ProgramObject* program = &_program;
Locations* locations = &_locations; Locations* locations = &_locations;
@ -1486,6 +1484,14 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
// i is the "index" from the original networkMeshes QVector... // i is the "index" from the original networkMeshes QVector...
foreach (int i, list) { foreach (int i, list) {
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
// to false to rebuild out mesh groups.
if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {
_meshGroupsKnown = false; // regenerate these lists next time around.
continue;
}
// exit early if the translucency doesn't match what we're drawing // exit early if the translucency doesn't match what we're drawing
const NetworkMesh& networkMesh = networkMeshes.at(i); const NetworkMesh& networkMesh = networkMeshes.at(i);
@ -1501,17 +1507,30 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
// if we got here, then check to see if this mesh is in view // if we got here, then check to see if this mesh is in view
if (args) { if (args) {
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts);
bool shouldRender = true; bool shouldRender = true;
args->_meshesConsidered++; args->_meshesConsidered++;
if (cullMeshParts && args->_viewFrustum) { if (args->_viewFrustum) {
shouldRender = args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; shouldRender = dontCullOutOfViewMeshParts ||
args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
if (shouldRender && cullTooSmallMeshParts) {
float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter());
shouldRender = Menu::getInstance()->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(),
distance);
if (!shouldRender) {
args->_meshesTooSmall++;
}
} else {
args->_meshesOutOfView++;
}
} }
if (shouldRender) { if (shouldRender) {
args->_meshesRendered++; args->_meshesRendered++;
} else { } else {
args->_meshesOutOfView++;
continue; // skip this mesh continue; // skip this mesh
} }
} }

View file

@ -31,6 +31,7 @@ class QScriptEngine;
class AnimationHandle; class AnimationHandle;
class Shape; class Shape;
class RenderArgs; class RenderArgs;
class ViewFrustum;
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer; typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer; typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
@ -335,27 +336,27 @@ private:
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
bool _meshesGroupsKnown; bool _meshGroupsKnown;
QList<int> _meshesTranslucent; QVector<int> _meshesTranslucent;
QList<int> _meshesTranslucentTangents; QVector<int> _meshesTranslucentTangents;
QList<int> _meshesTranslucentTangentsSpecular; QVector<int> _meshesTranslucentTangentsSpecular;
QList<int> _meshesTranslucentSpecular; QVector<int> _meshesTranslucentSpecular;
QList<int> _meshesTranslucentSkinned; QVector<int> _meshesTranslucentSkinned;
QList<int> _meshesTranslucentTangentsSkinned; QVector<int> _meshesTranslucentTangentsSkinned;
QList<int> _meshesTranslucentTangentsSpecularSkinned; QVector<int> _meshesTranslucentTangentsSpecularSkinned;
QList<int> _meshesTranslucentSpecularSkinned; QVector<int> _meshesTranslucentSpecularSkinned;
QList<int> _meshesOpaque; QVector<int> _meshesOpaque;
QList<int> _meshesOpaqueTangents; QVector<int> _meshesOpaqueTangents;
QList<int> _meshesOpaqueTangentsSpecular; QVector<int> _meshesOpaqueTangentsSpecular;
QList<int> _meshesOpaqueSpecular; QVector<int> _meshesOpaqueSpecular;
QList<int> _meshesOpaqueSkinned; QVector<int> _meshesOpaqueSkinned;
QList<int> _meshesOpaqueTangentsSkinned; QVector<int> _meshesOpaqueTangentsSkinned;
QList<int> _meshesOpaqueTangentsSpecularSkinned; QVector<int> _meshesOpaqueTangentsSpecularSkinned;
QList<int> _meshesOpaqueSpecularSkinned; QVector<int> _meshesOpaqueSpecularSkinned;
}; };

View file

@ -459,7 +459,7 @@ void Stats::display(
VoxelSystem* voxels = Application::getInstance()->getVoxels(); VoxelSystem* voxels = Application::getInstance()->getVoxels();
lines = _expanded ? 14 : 3; lines = _expanded ? 15 : 3;
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) { if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) {
lines += 10; // spatial audio processing adds 1 spacing line and 8 extra lines of info lines += 10; // spatial audio processing adds 1 spacing line and 8 extra lines of info
} }
@ -472,12 +472,16 @@ void Stats::display(
// Model/Entity render details // Model/Entity render details
EntityTreeRenderer* entities = Application::getInstance()->getEntities(); EntityTreeRenderer* entities = Application::getInstance()->getEntities();
voxelStats.str(""); voxelStats.str("");
voxelStats << "Entity Items rendered: " << entities->getItemsRendered() << " Out of view:" << entities->getItemsOutOfView(); voxelStats << "Entity Items rendered: " << entities->getItemsRendered()
<< " Out of view:" << entities->getItemsOutOfView()
<< " Too small:" << entities->getItemsTooSmall();
verticalOffset += STATS_PELS_PER_LINE; verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
voxelStats.str(""); voxelStats.str("");
voxelStats << "Meshes rendered: " << entities->getMeshesRendered() << " Out of view:" << entities->getMeshesOutOfView(); voxelStats << "Meshes rendered: " << entities->getMeshesRendered()
<< " Out of view:" << entities->getMeshesOutOfView()
<< " Too small:" << entities->getMeshesTooSmall();
verticalOffset += STATS_PELS_PER_LINE; verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);

View file

@ -162,7 +162,8 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) {
} }
void OctreeRenderer::render(RenderMode renderMode) { void OctreeRenderer::render(RenderMode renderMode) {
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, 0, 0, 0, 0, 0, 0, 0, 0 }; RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
if (_tree) { if (_tree) {
_tree->lockForRead(); _tree->lockForRead();
_tree->recurseTreeWithOperation(renderOperation, &args); _tree->recurseTreeWithOperation(renderOperation, &args);
@ -171,10 +172,12 @@ void OctreeRenderer::render(RenderMode renderMode) {
_meshesConsidered = args._meshesConsidered; _meshesConsidered = args._meshesConsidered;
_meshesRendered = args._meshesRendered; _meshesRendered = args._meshesRendered;
_meshesOutOfView = args._meshesOutOfView; _meshesOutOfView = args._meshesOutOfView;
_meshesTooSmall = args._meshesTooSmall;
_elementsTouched = args._elementsTouched; _elementsTouched = args._elementsTouched;
_itemsRendered = args._itemsRendered; _itemsRendered = args._itemsRendered;
_itemsOutOfView = args._itemsOutOfView; _itemsOutOfView = args._itemsOutOfView;
_itemsTooSmall = args._itemsTooSmall;
_trianglesRendered = args._trianglesRendered; _trianglesRendered = args._trianglesRendered;
_quadsRendered = args._quadsRendered; _quadsRendered = args._quadsRendered;

View file

@ -67,10 +67,12 @@ public:
int getElementsTouched() const { return _elementsTouched; } int getElementsTouched() const { return _elementsTouched; }
int getItemsRendered() const { return _itemsRendered; } int getItemsRendered() const { return _itemsRendered; }
int getItemsOutOfView() const { return _itemsOutOfView; } int getItemsOutOfView() const { return _itemsOutOfView; }
int getItemsTooSmall() const { return _itemsTooSmall; }
int getMeshesConsidered() const { return _meshesConsidered; } int getMeshesConsidered() const { return _meshesConsidered; }
int getMeshesRendered() const { return _meshesRendered; } int getMeshesRendered() const { return _meshesRendered; }
int getMeshesOutOfView() const { return _meshesOutOfView; } int getMeshesOutOfView() const { return _meshesOutOfView; }
int getMeshesTooSmall() const { return _meshesTooSmall; }
int getTrianglesRendered() const { return _trianglesRendered; } int getTrianglesRendered() const { return _trianglesRendered; }
int getQuadsRendered() const { return _quadsRendered; } int getQuadsRendered() const { return _quadsRendered; }
@ -86,10 +88,12 @@ protected:
int _elementsTouched; int _elementsTouched;
int _itemsRendered; int _itemsRendered;
int _itemsOutOfView; int _itemsOutOfView;
int _itemsTooSmall;
int _meshesConsidered; int _meshesConsidered;
int _meshesRendered; int _meshesRendered;
int _meshesOutOfView; int _meshesOutOfView;
int _meshesTooSmall;
int _trianglesRendered; int _trianglesRendered;
int _quadsRendered; int _quadsRendered;
@ -109,10 +113,12 @@ public:
int _elementsTouched; int _elementsTouched;
int _itemsRendered; int _itemsRendered;
int _itemsOutOfView; int _itemsOutOfView;
int _itemsTooSmall;
int _meshesConsidered; int _meshesConsidered;
int _meshesRendered; int _meshesRendered;
int _meshesOutOfView; int _meshesOutOfView;
int _meshesTooSmall;
int _trianglesRendered; int _trianglesRendered;
int _quadsRendered; int _quadsRendered;

View file

@ -876,3 +876,10 @@ void ViewFrustum::getFurthestPointFromCameraVoxelScale(const AACube& box, glm::v
} }
} }
float ViewFrustum::distanceToCamera(const glm::vec3& point) const {
glm::vec3 temp = getPosition() - point;
float distanceToPoint = sqrtf(glm::dot(temp, temp));
return distanceToPoint;
}

View file

@ -118,6 +118,8 @@ public:
// assumes box is in voxel scale, not TREE_SCALE, will scale view frustum's position accordingly // assumes box is in voxel scale, not TREE_SCALE, will scale view frustum's position accordingly
void getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const; void getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const;
float distanceToCamera(const glm::vec3& point) const;
private: private:
// Used for keyhole calculations // Used for keyhole calculations