lunes, 26 de mayo de 2008

Controlando la tasa de frames por segundo

En esta entrada explicaremos cómo controlar la cantidad de frames por segundo que tendrá nuestra aplicación Irrlicht.


Se que más de uno se preguntará ¿por qué limitar los FPS? Cuantos mas mejor ¿no? La respuesta es sí y no. Veréis, a partir de los 30fps ya no notamos diferencia de fluidez, luego, no es necesario que la cpu y gpu curren al 100%. Si limitamos la tasa de frames a 30, evitaremos el recalentamiento de los chips y eso, en portatiles se agradece mucho: menos consumo de bateria (si fuera el caso), menos calor, menos movimiento de ventilador y por tanto, menos acumulación de polvo, etc.

Asi pues, nuestra clase aplicacion tendrá un objeto que sea el encargado de introducir pausas limitar los fps. En caso de que el equipo no llegue al limite, no se introducirían pausas.

Para hacerlo bonito, lo haremos al estilo IS1. Implementaremos una interfaz que tendrá los métodos minimos y necesarios para que cualquier clase que implemente dicha interfaz, pueda controlar sin problemas los fps.

He aquí la clase interfaz IFPSManager. Vemos que tiene dos metodos a implementar por las clases que hereden de ésta, mUpdateFPS() y mDrawFPS().

class IFPSManager
{
public:
IFPSManager();
IFPSManager(IrrlichtDevice *device);
virtual ~IFPSManager();

virtual void mUpdateFPS() = 0;
virtual void mDrawFPS() = 0;
};



Y ahora la declaración de la clase FPSManager que implementa la interfaz.
#include "IFPSManager.h"

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

class FPSManager : public IFPSManager
{
public:
FPSManager();
FPSManager(IrrlichtDevice *device);
virtual ~FPSManager();

virtual void mUpdateFPS();
virtual void mDrawFPS();

protected:
IrrlichtDevice *f_device;
IVideoDriver *f_driver;

s32 fFPSMax;
f32 fFPSMaxMiliSeconds;
f32 fPauseInDraw;
};



No nos olvidemos de la implementación. La forma de calcular la pausa entre frames aún no es definitiva, pero gracias a la interfaz, podemos escribir otro gestor de fps sin tener que desechar este FPSManager.
#include "FPSManager.h"

FPSManager::FPSManager()
{
f_device = NULL;
f_driver = NULL;
fFPSMax = 0;
fFPSMaxMiliSeconds = 0.0;
fPauseInDraw = 0.0;
}

FPSManager::FPSManager(IrrlichtDevice *device)
{
f_device = device;
f_driver = f_device->getVideoDriver();
fFPSMax = 25;
fFPSMaxMiliSeconds = 1/(f32)fFPSMax;
fPauseInDraw = 0.0;
}

FPSManager::~FPSManager()
{
f_device = NULL;
fFPSMax = 0;
fFPSMaxMiliSeconds = 0.0;
fPauseInDraw = 0.0;
}

void
FPSManager::mUpdateFPS()
{
if (f_driver->getFPS() > fFPSMax)
fPauseInDraw = (fFPSMaxMiliSeconds - 1.0/(f32)f_driver->getFPS()) * 1000.0;
f_device->sleep((u32)fPauseInDraw);
}

void
FPSManager::mDrawFPS()
{
core::stringw str(core::stringw(f_driver->getFPS()));
str.append(L"fps");
f_device->setWindowCaption(str.c_str());
}



Hasta aquí el gestor de frames por segundo. En la proxima entrega hablaremos de la Interfaz de ventana IApplication.



No hay comentarios: