Back to index

supertuxkart  0.5+dfsg1
replay_player.cpp
Go to the documentation of this file.
00001 //  $Id$
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2007 Maik Semder <ikework@gmx.de>
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #ifdef HAVE_GHOST_REPLAY
00021 
00022 #include "kart_properties_manager.hpp"
00023 #include "kart_properties.hpp"
00024 
00025 #include "replay_player.hpp"
00026 
00027 
00028 ReplayKart::ReplayKart()
00029 : m_kart_properties(NULL), m_model(NULL)
00030 {
00031 }
00032 
00033 ReplayKart::~ReplayKart()
00034 {
00035     destroy();
00036 }
00037 
00038 void ReplayKart::destroy()
00039 {
00040     m_kart_properties = NULL;
00041 }
00042 
00043 bool ReplayKart::init( const std::string &strKartIdent )
00044 {
00045     assert( !m_kart_properties );
00046 
00047     m_model = new ssgTransform();
00048     m_model->ref();
00049 
00050     m_kart_properties = kart_properties_manager->getKart( strKartIdent );
00051     if( NULL == m_kart_properties ) return false;
00052 
00053     ssgEntity *obj = m_kart_properties->getModel();
00054     assert( obj );
00055     // Optimize the model, this can't be done while loading the model
00056     // because it seems that it removes the name of the wheels or something
00057     // else needed to load the wheels as a separate object.
00058     ssgFlatten(obj);
00059 
00060     ssgRangeSelector *lod = new ssgRangeSelector;
00061 
00062     float r [ 2 ] = { -10.0f, 100.0f } ;
00063     lod -> addKid ( obj ) ;
00064     lod -> setRanges ( r, 2 ) ;
00065 
00066     m_model -> addKid ( lod ) ;
00067 
00068     return true;
00069 }
00070     
00071 #include "scene.hpp"
00072 
00073 ReplayPlayer::ReplayPlayer() 
00074 : ReplayBase(), m_current_frame_index(-1)
00075 {
00076 }
00077 
00078 ReplayPlayer::~ReplayPlayer() 
00079 { 
00080     destroy(); 
00081 }
00082 
00083 void ReplayPlayer::destroy() 
00084 { 
00085     m_current_frame_index = -1;
00086     m_Karts.clear();
00087     ReplayBase::destroy();
00088 }
00089 
00090 bool ReplayPlayer::loadReplayHumanReadable( FILE *fd ) 
00091 { 
00092     destroy();
00093 
00094     bool blnRet = false;
00095     int intTemp;
00096     char buff[1000];
00097     size_t number_karts;
00098     if( fscanf( fd, "Version: %s\n", buff ) != 1 ) return false;
00099     if( fscanf( fd, "numkarts: %u\n", &number_karts ) != 1 ) return false;
00100     if( fscanf( fd, "numplayers: %s\n", buff ) != 1 ) return false;
00101     if( fscanf( fd, "difficulty: %s\n", buff ) != 1 ) return false;
00102     if( fscanf( fd, "track: %s\n", buff ) != 1 ) return false;
00103     for( size_t k = 0; k < number_karts; ++k )
00104     {
00105         if( fscanf( fd, "model %d: %s\n", &intTemp, buff ) != 2 ) return false;
00106 
00107         m_Karts.resize( m_Karts.size() + 1 );
00108         ReplayKart &kart = m_Karts[ m_Karts.size() - 1 ];
00109         if( !kart.init( buff ) ) return false;
00110 
00111         scene->add ( kart.getModel() );
00112     }
00113 
00114     if( !m_ReplayBuffers.loadReplayHumanReadable( fd, number_karts ) ) return false;
00115 
00116     m_current_frame_index = 0;
00117 
00118     return true;
00119 }
00120 
00121 void ReplayPlayer::showReplayAt( float abs_time )
00122 {
00123     assert( m_ReplayBuffers.getNumberFrames() );
00124     assert( m_current_frame_index > -1 );
00125     assert( (size_t)m_current_frame_index < m_ReplayBuffers.getNumberFrames() );
00126 
00127     ReplayFrame const* frame;
00128 
00129     // find the current frame, we only scroll forward ..
00130     while(1)
00131     {
00132         // end reached?
00133         if( (m_current_frame_index + 1) == m_ReplayBuffers.getNumberFrames() ) break;
00134 
00135         // check time of next frame
00136         frame = m_ReplayBuffers.getFrameAt( m_current_frame_index+1 );
00137         if( frame->time > abs_time ) break;
00138 
00139         ++m_current_frame_index;
00140     }
00141 
00142     frame = m_ReplayBuffers.getFrameAt( m_current_frame_index );
00143 
00144     // interpolate, if we are not at the end
00145     if( (m_current_frame_index + 1) < (int)m_ReplayBuffers.getNumberFrames() )
00146     {
00147         ReplayFrame const* frame_next = m_ReplayBuffers.getFrameAt( m_current_frame_index+1 );
00148 
00149         // calc scale factor based on time between frames
00150         assert( frame_next->time > frame->time );
00151         assert( frame_next->time != frame->time );
00152         float scale = (abs_time - frame->time) / (frame_next->time - frame->time);
00153 
00154         sgVec3 tmp_v3;
00155         sgCoord pos;
00156 
00157         // calc interpolations for all objects
00158         for( size_t k = 0; k < m_Karts.size(); ++k )
00159         {
00160             // calc distance between next and current frame-position
00161             sgCopyVec3( pos.xyz, frame->p_kart_states[k].position.xyz ) ;
00162             sgCopyVec3( tmp_v3, frame_next->p_kart_states[k].position.xyz ) ;
00163             sgSubVec3( tmp_v3, pos.xyz );
00164 
00165             // scale it based on time between frames
00166             sgScaleVec3( tmp_v3, scale );
00167 
00168             // add interpolated vector
00169             sgAddVec3( pos.xyz, tmp_v3 );
00170 
00171             // no orientation-interpolation for starters
00172             sgCopyVec3( pos.hpr, frame->p_kart_states[k].position.hpr );
00173 
00174             m_Karts[ k ].setPosition( pos );
00175         }
00176     }
00177     else
00178     {
00179         // replay finished, leave them at last known position
00180         for( size_t k = 0; k < m_Karts.size(); ++k )
00181         {
00182             m_Karts[ k ].setPosition( frame->p_kart_states[ k ].position );
00183         }
00184     }
00185 
00186 }
00187 
00188 
00189 #endif // HAVE_GHOST_REPLAY