I recorded
this horde video at 1280*1024 @ 60 fps as a stream of TGA files.
The key for me was using a "delta time" value of 1/60s (0.0166...) for every frame of the simulation, ignoring how much time had actually past. This meant that the video is completely smooth, although to record 10 seconds of video took about 1 minute.
I use this function to get the pixel-data out of Horde:
Code:
void CPipeline::RenderTargetData( const std::string& name, int bufIndex, uint& width, uint& height,
uint& components, std::vector<float>& out )
{
int w=0,h=0,c=0;
Horde3D::getPipelineRenderTargetData( GetID(), name.c_str(), bufIndex, &w, &h, &c, NULL, 0 );
int s = w*h*c;
out.resize( s );
if( s )
Horde3D::getPipelineRenderTargetData( GetID(), name.c_str(), bufIndex, 0, 0, 0, &out[0], s*sizeof(float) );
width = w;
height = h;
components = c;
}
And my main loop looks like this:
Code:
const float averageFrameRate = 1/60.0f;
float flDelta = averageFrameRate;
double flLastTime = GetTime();
while( !m_exitApp )
{
if( m_Record )
{
flDelta = averageFrameRate;
flLastTime += averageFrameRate;
}
UpdateScene( renderer, flLastTime, flDelta );
RenderScene( renderer );
if( m_Record )
{
std::stringstream filename;
filename << "record" << std::setw(4) << std::setfill('0') << m_RecordedFrames++ << ".tga";
uint w, h, c;
std::vector<float> data;
ScreenShot( w, h, c, data );
FILE* fp;
if( w && h && c && (fp = fopen( filename.str().c_str(), "wb" )) )
{
uint8 bpp = c*8;
std::auto_ptr<uint8> apOutput( new uint8[w*h*c] );
uint8* imageOut = apOutput.get();
ASSERT( data.size() == w*h*c );
for( uint i=0; i<w*h*c; i+=c )
{
if( c == 4 )
{
imageOut[i+0] = (uint8)(data[i+2]*255.0f);
imageOut[i+1] = (uint8)(data[i+1]*255.0f);
imageOut[i+2] = (uint8)(data[i+0]*255.0f);
imageOut[i+3] = (uint8)(data[i+3]*255.0f);
}
else if( c == 3 )
{
imageOut[i+0] = (uint8)(data[i+2]*255.0f);
imageOut[i+1] = (uint8)(data[i+1]*255.0f);
imageOut[i+2] = (uint8)(data[i+0]*255.0f);
}
else
{
for( uint j=0; j<c; ++j )
imageOut[i+j] = (uint8)(data[i+j]*255.0f);
}
}
// Build TGA header
uint8 b;
uint16 s;
fwrite( &(b = 0), sizeof(uint8 ), 1, fp );// Number of ID bytes after header
fwrite( &(b = 0), sizeof(uint8 ), 1, fp );// Color map type: none
fwrite( &(b = 2), sizeof(uint8 ), 1, fp );// Image type: Uncompressed true color
fwrite( &(s = 0), sizeof(uint16), 1, fp );// First color map index
fwrite( &(s = 0), sizeof(uint16), 1, fp );// Color map length
fwrite( &(b = 16), sizeof(uint8 ), 1, fp );// Color map bits per entry
fwrite( &(s = 0), sizeof(uint16), 1, fp );// X origin
fwrite( &(s = 0), sizeof(uint16), 1, fp );// Y origin
fwrite( &(s = w), sizeof(uint16), 1, fp );// Width
fwrite( &(s = h), sizeof(uint16), 1, fp );// Height
fwrite( &(b =bpp), sizeof(uint8 ), 1, fp );// Bits per pixel
fwrite( &(b = 0), sizeof(uint8 ), 1, fp );// Image descriptor
fwrite( imageOut, sizeof(uint8 ), w*h*c, fp );
fclose( fp );
}
}
// Calculate FPS
double flNewTime = GetTime();
flDelta = (float)(flNewTime-flLastTime);
if( !m_Record )
flLastTime = flNewTime;
m_curFPS = 1/flDelta;
}