* set max. sample-frequency to 30 frames per second
* put sample-freq-statistic in the end of replay-file as comments
* did some replay-cleaning

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1265 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
ikework 2007-09-27 09:47:48 +00:00
parent c1ed88df9c
commit 0b7cadfbea
8 changed files with 93 additions and 46 deletions

View File

@ -68,6 +68,7 @@ public:
int isOnGround () {return m_on_ground; }
sgCoord* getVelocity () {return & m_velocity; }
sgCoord* getCoord () {return &m_curr_pos; }
const sgCoord* getCoord () const {return &m_curr_pos; }
const sgVec4* getNormalHOT () const {return m_normal_hot; }
void setCoord (sgCoord* pos) {sgCopyCoord ( &m_curr_pos,pos); }
virtual void placeModel () {m_model->setTransform(&m_curr_pos); }

View File

@ -40,7 +40,7 @@ struct ReplayFrame
// absolute time of frame
float time;
// for each kart in frame, points to continious block
// in Buffers::m_pp_blocks_kart_states with m_number_cars items
// in Buffers::m_pp_blocks_kart_states with m_number_karts items
ReplayKartState *p_kart_states;
};

View File

@ -6,9 +6,10 @@
#include "replay_base.hpp"
#include "replay_buffers.hpp"
#define REPLAY_SAVE_STATISTIC
ReplayBuffers::ReplayBuffers()
: m_number_cars(0),
: m_number_karts(0),
m_BufferFrame(),
m_BufferKartState()
{
@ -23,16 +24,16 @@ void ReplayBuffers::destroy()
{
m_BufferFrame.destroy();
m_BufferKartState.destroy();
m_number_cars = 0;
m_number_karts = 0;
}
bool ReplayBuffers::init( unsigned int number_cars,
bool ReplayBuffers::init( unsigned int number_karts,
size_t number_preallocated_frames )
{
m_number_cars = number_cars;
m_number_karts = number_karts;
if( !m_BufferFrame.init( number_preallocated_frames ) ) return false;
if( !m_BufferKartState.init( number_preallocated_frames, number_cars ) ) return false;
if( !m_BufferKartState.init( number_preallocated_frames, number_karts ) ) return false;
return true;
}
@ -63,6 +64,10 @@ bool ReplayBuffers::saveReplayHumanReadable( FILE *fd ) const
if( fprintf( fd, "frames: %u\n", getNumberFrames() ) < 1 ) return false;
#ifdef REPLAY_SAVE_STATISTIC
float time_step_min = 9999999.0f, time_step_max = 0.0f, time_last;
#endif
unsigned int frame_idx, kart_idx;
ReplayFrame const *frame;
ReplayKartState const *kart;
@ -71,7 +76,7 @@ bool ReplayBuffers::saveReplayHumanReadable( FILE *fd ) const
frame = getFrameAt( frame_idx );
if( fprintf( fd, "frame %u time %f\n", frame_idx, frame->time ) < 1 ) return false;
for( kart_idx = 0; kart_idx < m_number_cars; ++kart_idx )
for( kart_idx = 0; kart_idx < m_number_karts; ++kart_idx )
{
kart = frame->p_kart_states + kart_idx;
@ -79,18 +84,42 @@ bool ReplayBuffers::saveReplayHumanReadable( FILE *fd ) const
kart->position.xyz[0], kart->position.xyz[1], kart->position.xyz[2],
kart->position.hpr[0], kart->position.hpr[1], kart->position.hpr[2] ) < 1 ) return false;
}
#ifdef REPLAY_SAVE_STATISTIC
if( frame_idx )
{
float diff = frame->time - time_last;
if( diff < time_step_min ) time_step_min = diff;
if( diff > time_step_max ) time_step_max = diff;
}
time_last = frame->time;
#endif
}
#ifdef REPLAY_SAVE_STATISTIC
float time_step_avg;
if( getNumberFrames() > 1 )
{
time_step_avg = time_last / ( getNumberFrames() - 1 );
}
else
{
time_step_avg = -1.0f;
}
fprintf( fd, "\n# statistic time-steps:\n# \tmin: %f\n# \tmax: %f\n# \tavg: %f\n", time_step_min, time_step_max, time_step_avg );
#endif
return true;
}
bool ReplayBuffers::loadReplayHumanReadable( FILE *fd, size_t number_cars )
bool ReplayBuffers::loadReplayHumanReadable( FILE *fd, unsigned int number_karts )
{
size_t frames;
if( fscanf( fd, "frames: %u\n", &frames ) != 1 ) return false;
if( !init( number_cars, frames ) ) return false;
if( !init( number_karts, frames ) ) return false;
assert( m_number_karts );
unsigned int frame_idx, kart_idx, tmp;
ReplayFrame *frame;
ReplayKartState *kart;
@ -102,7 +131,7 @@ bool ReplayBuffers::loadReplayHumanReadable( FILE *fd, size_t number_cars )
if( fscanf( fd, "frame %u time %f\n", &tmp, &frame->time ) != 2 ) return false;
for( kart_idx = 0; kart_idx < number_cars; ++kart_idx )
for( kart_idx = 0; kart_idx < m_number_karts; ++kart_idx )
{
kart = frame->p_kart_states + kart_idx;

View File

@ -40,7 +40,7 @@ public:
ReplayBuffers();
~ReplayBuffers();
bool init( unsigned int number_cars,
bool init( unsigned int number_karts,
size_t number_preallocated_frames );
void destroy();
@ -54,9 +54,10 @@ public:
ReplayFrame const* getFrameAt( size_t frame_index ) const { return m_BufferFrame.getObjectAt( frame_index ); }
size_t getNumberFrames() const { return m_BufferFrame.getNumberObjectsUsed(); }
unsigned int getNumberKarts() const { return m_number_karts; }
bool saveReplayHumanReadable( FILE *fd ) const;
bool loadReplayHumanReadable( FILE *fd, size_t number_cars );
bool loadReplayHumanReadable( FILE *fd, unsigned int number_karts );
private:
bool isHealthy() const { return m_BufferFrame.isHealthy() && m_BufferKartState.isHealthy(); }
@ -65,7 +66,7 @@ private:
typedef Buffer<ReplayFrame> BufferFrame;
typedef BufferArray<ReplayKartState> BufferKartState;
unsigned int m_number_cars;
unsigned int m_number_karts;
BufferFrame m_BufferFrame;
BufferKartState m_BufferKartState;
};

View File

@ -1,9 +1,11 @@
#ifdef HAVE_GHOST_REPLAY
#include "replay_recorder.hpp"
#include <cassert>
#include "replay_recorder.hpp"
#include "world.hpp"
const float ReplayRecorder::REPLAY_TIME_STEP_MIN = 1.0f / (float)ReplayRecorder::REPLAY_FREQUENCY_MAX;
ReplayRecorder::ReplayRecorder()
: ReplayBase()
@ -20,16 +22,45 @@ void ReplayRecorder::destroy()
ReplayBase::destroy();
}
bool ReplayRecorder::initRecorder( unsigned int number_cars, size_t number_preallocated_frames )
bool ReplayRecorder::initRecorder( unsigned int number_karts, size_t number_preallocated_frames )
{
assert( number_cars );
assert( number_karts );
destroy();
if( !m_ReplayBuffers.init( number_cars, number_preallocated_frames ) ) return false;
if( !m_ReplayBuffers.init( number_karts, number_preallocated_frames ) ) return false;
return true;
}
bool ReplayRecorder::pushFrame()
{
// we dont record the startphase ..
assert( world->getPhase() != World::START_PHASE );
assert( world->getNumKarts() == m_ReplayBuffers.getNumberKarts() );
// make sure we're not under time-step-min
if( m_ReplayBuffers.getNumberFrames() )
{
ReplayFrame const *last_Frame = m_ReplayBuffers.getFrameAt( m_ReplayBuffers.getNumberFrames() - 1 );
if( (world->getClock() - last_Frame->time) < REPLAY_TIME_STEP_MIN ) return true;
}
ReplayFrame *pFrame = getNewFrame();
if( !pFrame ) return false;
pFrame->time = world->getClock();
Kart const *kart;
int number_karts = world->getNumKarts();
for( int kart_index = 0; kart_index < number_karts; ++kart_index )
{
kart = world->getKart( kart_index );
sgCopyCoord( &( pFrame->p_kart_states[ kart_index ].position ),
kart->getCoord() );
}
return true;
}
#endif // HAVE_GHOST_REPLAY

View File

@ -33,19 +33,26 @@ class ReplayRecorder : public ReplayBase
private:
// assuming 10 minutes with 50 frames per second
enum { BUFFER_PREALLOCATE_FRAMES = 10 * 50 * 60, };
enum { REPLAY_FREQUENCY_MAX = 30 };
// calculated from REPLAY_FREQUENCY_MAX
static const float REPLAY_TIME_STEP_MIN;
public:
ReplayRecorder();
virtual ~ReplayRecorder();
void destroy();
bool initRecorder( unsigned int number_cars,
bool initRecorder( unsigned int number_karts,
size_t number_preallocated_frames = BUFFER_PREALLOCATE_FRAMES );
// something might go wrong, since a new buffer may be allocated, so false means
// no memory available
bool pushFrame();
private:
// returns a new *free* frame to be used to store the current frame-data into it
// used to *record* the replay
ReplayFrame* getNewFrame() { return m_ReplayBuffers.getNewFrame(); }
};

View File

@ -395,35 +395,12 @@ void World::update(float delta)
// normally, but after switching to RACE_PHASE m_clock is set back to 0.0
if( m_phase != START_PHASE )
{
pushReplayFrameData();
m_replay_recorder.pushFrame();
if( m_p_replay_player ) m_p_replay_player->showReplayAt( m_clock );
}
#endif
}
#ifdef HAVE_GHOST_REPLAY
//-----------------------------------------------------------------------------
void World::pushReplayFrameData()
{
// we dont record the startphase ..
assert( m_phase != START_PHASE );
ReplayFrame *pFrame = m_replay_recorder.getNewFrame();
if( !pFrame ) return;
pFrame->time = m_clock;
Karts::const_iterator itKarts;
int kart_index = 0;
for( itKarts = m_kart.begin(); itKarts != m_kart.end(); ++itKarts, ++kart_index )
{
sgCopyCoord( &( pFrame->p_kart_states[ kart_index ].position ),
(*itKarts)->getCoord() );
}
} // pushFrameData
#endif // HAVE_GHOST_REPLAY
#ifdef HAVE_GHOST_REPLAY
//-----------------------------------------------------------------------------
bool World::saveReplayHumanReadable( std::string const &filename ) const
@ -528,7 +505,7 @@ void World::checkRaceStatus()
sound_manager->playSfx(SOUND_START);
#ifdef HAVE_GHOST_REPLAY
// push positions at time 0.0 to replay-data
pushReplayFrameData();
m_replay_recorder.pushFrame();
#endif
}
else if (m_clock > 1.0 && m_ready_set_go == 2)

View File

@ -127,8 +127,9 @@ private:
sgCoord init_pos);
#ifdef HAVE_GHOST_REPLAY
public:
float getClock() const { return m_clock; }
private:
void pushReplayFrameData();
bool saveReplayHumanReadable( std::string const &filename ) const;
bool loadReplayHumanReadable( std::string const &filename );