Skip to main content
ScreenRatioLodStrategy        

Screen Ratio LOD Strategy

ScreenRatioLodStrategy works by analyzing how much portion of screen a model occupies on screen on any given instance of time, and selects a LOD mesh/material accordingly. ScreenRatioLodStrategy is inspired by PixelCountLodStrategy.

Status

  • ScreenRatioLodStrategy is slight modification of PixelCountLodStrategy.
  • Currently it is not included in Ogre SDK

Inspiration

I feel ScreenRatioLodStrategy does a little more justice to varying screen resolutions these days.

Say, I specify a PixelCountLodStrategy mesh with 50% complexity reduction below 500*500 pixel area. Now this might work very well on my 1080p monitor, but when I view the same model on a 1024*800 netbook screen or projector, model will switch to level 1 a little too soon.

ScreenRatioLodStrategy on the other hand specifies the Ratio below which lod will be reduced. We spacify lod values as 0.2(=20%), 0.1(=10%) and so on. So when a model takes below 20% of total screen area, it will switch to level 1. This is total independent of whether I am running a 800*600 projector or a 1080p monitor.

ScreenRatioLodStrategy VS PixelCountLodStrategy

  1. ScreenRatioLodStrategy is inspired by PixelCountLodStrategy, but provide simpler and better control over LOD meshes.
  2. Where PixelCountLodStrategy specifies LOD meshes when they occupy certain number pixels on screen (eg 500*500pixels, 200*200), ScreenRatioLodStrategy specifies LOD meshes when they occupy certain percent of total screen area (50% of screen, 20% of screen)
  3. Easier to specify lod values while defining LOD meshes

ScreenRatioLodStrategy Values

NOTE: values need testing

LOD values are specified as ratio, that is, area occupied by a model of total screen area. However please note that the values are approximations and generally higher than actual area. For example

  • LOD Value > 1.0 = majority of screen space (~50%)
  • LOD Value > 0.5 = significant amount of screen space (~25%)
  • LOD Value > 0.2 = small amount of screen space (~5%)
  • and so on

How To Programatically Prepare A Mesh For ScreenRatioLodStrategy ?

NOTE: code needs testing

For ScreenRatioLodStrategy , mesh lod values are stored in decreasing orger, starting with MAX_FLOAT value. Here is what you have to do

Copy to clipboard
// define base mesh MeshPtr mesh = MeshManager::getSingleton().load("something-100p.mesh"); // level 0, 100 percent // add LOD strategy mesh->setLodStrategy(new Ogre::ScreenRatioLodStrategy()); // might need to reapply after load // add level 1 mesh mesh->createManualLodLevel(0.5, "something-50p.mesh"); // level 1, 50 percent // add level 2 mesh, for pixel area below 200*200 mesh->createManualLodLevel(0.2, "something-25p.mesh"); // level 2, 25 percent // export LODed mesh MeshSerializer ser; ser.exportMesh(mesh1.get(), "something-with-lod.mesh");


How to use LODed mesh

NOTE: code needs testing

Copy to clipboard
Entity* enty = sceneManager->createEntity("MyLodMesh", "something-with-lod.mesh"); enty->setLodStrategy(new Ogre::ScreenRatioLodStrategy()); // optional


Help Needed

  • Currently it does not implement Singleton interface, if someone can do it
  • I could not decide if I need to do something in transformBias function

CODE

.H

Copy to clipboard
#ifndef __Screen_Ratio_Lod_Strategy_H__ #define __Screen_Ratio_Lod_Strategy_H__ #include "Ogre.h" #include "OgreLodStrategy.h" using namespace Ogre; // TODO add singleton interface class SUBMERGE_API ScreenRatioLodStrategy : public LodStrategy { protected: virtual Real getValueImpl(const MovableObject *movableObject, const Camera *camera) const; public: ScreenRatioLodStrategy(); virtual Real getBaseValue() const; virtual Real transformBias(Real factor) const; virtual ushort getIndex(Real value, const Mesh::MeshLodUsageList& meshLodUsageList) const; virtual ushort getIndex(Real value, const Material::LodValueList& materialLodValueList) const; virtual void sort(Mesh::MeshLodUsageList& meshLodUsageList) const; virtual bool isSorted(const Mesh::LodValueList& values) const; }; #endif

.CPP

Copy to clipboard
#include "ScreenRatioLodStrategy.h" ScreenRatioLodStrategy::ScreenRatioLodStrategy() : LodStrategy("ScreenRatio") { } Real ScreenRatioLodStrategy::getValueImpl(const MovableObject *movableObject, const Ogre::Camera *camera) const { // Get area of unprojected circle with object bounding radius Real boundingArea = Math::PI * Math::Sqr(movableObject->getBoundingRadius()); // Base computation on projection type switch (camera->getProjectionType()) { case PT_PERSPECTIVE: { // Get camera distance Real distanceSquared = movableObject->getParentNode()->getSquaredViewDepth(camera); // Check for 0 distance if (distanceSquared <= std::numeric_limits<Real>::epsilon()) return getBaseValue(); // Get projection matrix (this is done to avoid computation of tan(fov / 2)) const Matrix4& projectionMatrix = camera->getProjectionMatrix(); // Estimate pixel ratio return (boundingArea * projectionMatrix[0][0] * projectionMatrix[1][1]) / distanceSquared; } case PT_ORTHOGRAPHIC: { // Compute orthographic area Real orthoArea = camera->getOrthoWindowHeight() * camera->getOrthoWindowWidth(); // Check for 0 orthographic area if (orthoArea <= std::numeric_limits<Real>::epsilon()) return getBaseValue(); // Estimate pixel ratio return boundingArea / orthoArea; } default: { // This case is not covered for obvious reasons throw; } } } //--------------------------------------------------------------------- Real ScreenRatioLodStrategy::getBaseValue() const { // Use the maximum possible value as base return std::numeric_limits<Real>::max(); } //--------------------------------------------------------------------- Real ScreenRatioLodStrategy::transformBias(Real factor) const { // No transformation required for pixel ratio strategy return factor; } //--------------------------------------------------------------------- ushort ScreenRatioLodStrategy::getIndex(Real value, const Mesh::MeshLodUsageList& meshLodUsageList) const { // Values are descending return getIndexDescending(value, meshLodUsageList); } //--------------------------------------------------------------------- ushort ScreenRatioLodStrategy::getIndex(Real value, const Material::LodValueList& materialLodValueList) const { // Values are descending return getIndexDescending(value, materialLodValueList); } //--------------------------------------------------------------------- void ScreenRatioLodStrategy::sort(Mesh::MeshLodUsageList& meshLodUsageList) const { // Sort descending sortDescending(meshLodUsageList); } //--------------------------------------------------------------------- bool ScreenRatioLodStrategy::isSorted(const Mesh::LodValueList& values) const { // Check if values are sorted descending return isSortedDescending(values); }

References

http://www.ogre3d.org/tikiwiki/PixelCountLodStrategy