mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 03:40:20 +02:00
properly handle LOD in rendering by not rendering small entities
This commit is contained in:
parent
ed670ff48e
commit
d1a046e6ed
4 changed files with 110 additions and 66 deletions
|
@ -110,6 +110,101 @@ const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityI
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void renderElementProxy(EntityTreeElement* entityTreeElement) {
|
||||||
|
glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter() * (float)TREE_SCALE;
|
||||||
|
float elementSize = entityTreeElement->getScale() * (float)TREE_SCALE;
|
||||||
|
glColor3f(1.0f, 0.0f, 0.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x, elementCenter.y, elementCenter.z);
|
||||||
|
glutWireCube(elementSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
bool displayElementChildProxies = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementChildProxies);
|
||||||
|
|
||||||
|
if (displayElementChildProxies) {
|
||||||
|
// draw the children
|
||||||
|
float halfSize = elementSize / 2.0f;
|
||||||
|
float quarterSize = elementSize / 4.0f;
|
||||||
|
glColor3f(1.0f, 1.0f, 0.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glColor3f(1.0f, 0.0f, 1.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glColor3f(0.0f, 1.0f, 0.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glColor3f(0.0f, 0.0f, 1.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glColor3f(1.0f, 1.0f, 1.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glColor3f(0.0f, 0.5f, 0.5f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glColor3f(0.5f, 0.0f, 0.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glColor3f(0.0f, 0.5f, 0.0f);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize);
|
||||||
|
glutWireCube(halfSize);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::renderElement(OctreeElement* element, RenderArgs* args) {
|
void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) {
|
||||||
bool wantDebug = false;
|
bool wantDebug = false;
|
||||||
|
|
||||||
|
@ -132,73 +227,13 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
||||||
|
|
||||||
bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE;
|
bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE;
|
||||||
bool displayElementProxy = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementProxy);
|
bool displayElementProxy = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementProxy);
|
||||||
bool displayElementChildProxies = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementChildProxies);
|
|
||||||
|
|
||||||
|
|
||||||
if (!isShadowMode && displayElementProxy && numberOfEntities > 0) {
|
if (!isShadowMode && displayElementProxy && numberOfEntities > 0) {
|
||||||
glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter() * (float)TREE_SCALE;
|
renderElementProxy(entityTreeElement);
|
||||||
float elementSize = entityTreeElement->getScale() * (float)TREE_SCALE;
|
|
||||||
glColor3f(1.0f, 0.0f, 0.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x, elementCenter.y, elementCenter.z);
|
|
||||||
glutWireCube(elementSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
if (displayElementChildProxies) {
|
|
||||||
// draw the children
|
|
||||||
float halfSize = elementSize / 2.0f;
|
|
||||||
float quarterSize = elementSize / 4.0f;
|
|
||||||
glColor3f(1.0f, 1.0f, 0.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glColor3f(1.0f, 0.0f, 1.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glColor3f(0.0f, 1.0f, 0.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glColor3f(0.0f, 0.0f, 1.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glColor3f(1.0f, 1.0f, 1.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glColor3f(0.0f, 0.5f, 0.5f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glColor3f(0.5f, 0.0f, 0.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glColor3f(0.0f, 0.5f, 0.0f);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize);
|
|
||||||
glutWireCube(halfSize);
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
EntityItem* entityItem = entityItems[i];
|
EntityItem* entityItem = entityItems[i];
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
|
@ -210,13 +245,16 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
||||||
<< "isBestFit=" << isBestFit;
|
<< "isBestFit=" << isBestFit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// render entityItem aspoints
|
// render entityItem
|
||||||
AACube entityCube = entityItem->getAACube();
|
AACube entityCube = entityItem->getAACube();
|
||||||
entityCube.scale(TREE_SCALE);
|
entityCube.scale(TREE_SCALE);
|
||||||
|
|
||||||
// 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...
|
||||||
if (args->_viewFrustum->cubeInFrustum(entityCube) != ViewFrustum::OUTSIDE) {
|
float distance = distanceToCamera(entityCube.calcCenter(), *args->_viewFrustum);
|
||||||
|
if (shouldRenderEntity(entityCube.getLargestDimension(), distance) &&
|
||||||
|
args->_viewFrustum->cubeInFrustum(entityCube) != ViewFrustum::OUTSIDE) {
|
||||||
|
|
||||||
Glower* glower = NULL;
|
Glower* glower = NULL;
|
||||||
if (entityItem->getGlowLevel() > 0.0f) {
|
if (entityItem->getGlowLevel() > 0.0f) {
|
||||||
glower = new Glower(entityItem->getGlowLevel());
|
glower = new Glower(entityItem->getGlowLevel());
|
||||||
|
@ -231,7 +269,6 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
||||||
if (glower) {
|
if (glower) {
|
||||||
delete glower;
|
delete glower;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
args->_itemsOutOfView++;
|
args->_itemsOutOfView++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,10 @@ 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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityTreeRenderer_h
|
#endif // hifi_EntityTreeRenderer_h
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
doesn't include the extra exists bits will break something.
|
doesn't include the extra exists bits will break something.
|
||||||
|
|
||||||
3) Make sure LOD logic honors the LOD settings for entities in "spanners/parent" cells.
|
3) Make sure LOD logic honors the LOD settings for entities in "spanners/parent" cells.
|
||||||
|
-- network - don't SEND small entities even if their spanner cell is visible
|
||||||
|
|
||||||
7) some jutter with moving entities
|
7) some jutter with moving entities
|
||||||
-- I think this might only happen with lots of models in an element or in view
|
-- I think this might only happen with lots of models in an element or in view
|
||||||
|
@ -229,6 +230,7 @@
|
||||||
// FIXED -- animations don't appear on all viewers
|
// FIXED -- animations don't appear on all viewers
|
||||||
// FIXED -- animations are on different frames -- the data suggest they are the same frame number from a simulation perspective
|
// FIXED -- animations are on different frames -- the data suggest they are the same frame number from a simulation perspective
|
||||||
// SOLVED -- 50) Verify pruning logic...
|
// SOLVED -- 50) Verify pruning logic...
|
||||||
|
// SOLVED -- 51) LOD for rendering - don't render small entities even if their spanner cell is visible
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
const glm::vec3& getCorner() const { return _corner; }
|
const glm::vec3& getCorner() const { return _corner; }
|
||||||
float getScale() const { return _scale; }
|
float getScale() const { return _scale; }
|
||||||
glm::vec3 getDimensions() const { return glm::vec3(_scale,_scale,_scale); }
|
glm::vec3 getDimensions() const { return glm::vec3(_scale,_scale,_scale); }
|
||||||
|
float getLargestDimension() const { return _scale; }
|
||||||
|
|
||||||
glm::vec3 calcCenter() const;
|
glm::vec3 calcCenter() const;
|
||||||
glm::vec3 calcTopFarLeft() const;
|
glm::vec3 calcTopFarLeft() const;
|
||||||
|
|
Loading…
Reference in a new issue