Screen Ratio LOD Strategy

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

// 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

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

#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

#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(external link) 


摘自:http://www.ogre3d.org/tikiwiki/ScreenRatioLodStrategy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值