src/replay.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *            replay.cc
00003  *
00004  *  Fri Jun 10 18:58:04 2005
00005  *  Copyright  2005  Joe Venzon
00006  *  joe@venzon.net
00007  ****************************************************************************/
00008 
00009 /*
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023  */
00024  
00025 #include "replay.h"
00026 
00027 REPLAY::REPLAY()
00028 {
00029         num_packets = 0;
00030         replay = false;
00031         timeindex = 0.0;
00032         funcmem = NULL;
00033         playing = false;
00034         cur_packet = 0;
00035         //loadstate = -1;
00036         state_to_load = 0;
00037         num_states = 0;
00038         cur_state = 0;
00039         
00040         ghostcar = false;
00041         
00042         int i;
00043         for (i = 0; i < MAX_STATES; i++)
00044         {
00045                 if (state_mem[i].funcmem != NULL)
00046                 {
00047                         state_mem[i].funcmem = NULL;
00048                 }
00049         }
00050         
00051         if (curstate.funcmem != NULL)
00052                 curstate.funcmem = NULL;
00053 }
00054 
00055 REPLAY::~REPLAY()
00056 {
00057         if (funcmem != NULL)
00058                 delete [] funcmem;
00059 }
00060 
00061 void REPLAY::Clear()
00062 {
00063         int i;
00064         for (i = 0; i < num_states; i++)
00065         {
00066                 if (state_mem[i].funcmem != NULL)
00067                 {
00068                         delete [] state_mem[i].funcmem;
00069                         state_mem[i].funcmem = NULL;
00070                 }
00071         }
00072         
00073         num_packets = 0;
00074         timeindex = 0;
00075         num_states = 0;
00076 }
00077 
00078 void REPLAY::AddRecord(string newdofunction, float newval, int newstate)
00079 {
00080         if (replay && num_packets < MAX_PACKETS)
00081         {
00082                 //packet
00083                 
00084                 //if (newval != 0.0)
00085                         //cout << newdofunction << "," << newval << endl;
00086                 
00087                 int funcidx = 0;
00088                 int i;
00089                 for (i = 0; i < fnum; i++)
00090                 {
00091                         if (funcmem[i].func_name == newdofunction)
00092                                 funcidx = i;
00093                 }
00094                 
00095                 //if (newdofunction == "gas")
00096                         //cout << timeindex << ": " << newstate << " - " << newdofunction << ", " << newval << endl;
00097                 
00098                 /*if ((newstate == 1 && !funcmem[funcidx].active) || newstate != 1 || (newstate == 1 && funcmem[funcidx].active && funcmem[funcidx].oldval != newval))
00099                 {
00100                         packet[num_packets].time = timeindex;
00101                         packet[num_packets].val = newval;
00102                         strcpy(packet[num_packets].dofunction, newdofunction.c_str());
00103                         packet[num_packets].state = newstate;
00104                         
00105                         num_packets++;
00106                         
00107                         //if (newdofunction == "gas")
00108                                 cout << "added " << newdofunction << " packet, " << timeindex << ": " << newstate << " - " << newdofunction << ", " << newval << "/" << funcmem[funcidx].oldval << endl;
00109                 }*/
00110                 
00111                 //put the values into their functional slot.  this allows higher priority
00112                 // commands to be considered over lower priority ones (as with the vamosworld
00113                 // control processing code (effectively)
00114                 if (newstate != 2)
00115                 {
00116                         funcmem[funcidx].lastupdateat = timeindex;
00117                         funcmem[funcidx].newval = newval;
00118                         if (newstate == 1)
00119                                 funcmem[funcidx].held = true;
00120                         else
00121                                 funcmem[funcidx].held = false;
00122                         funcmem[funcidx].active = true;
00123                         //if (newdofunction == "gas")
00124                                 //cout << newdofunction << ", lastupdate set at " << timeindex << endl;
00125                 }
00126         }
00127 }
00128 
00129 extern float FrameTime();
00130 
00131 void REPLAY::IncrementFrame()
00132 {
00133         //cout << frame[num_frames].num_records << endl;
00134         
00135         if (funcmem == NULL)
00136                 return;
00137         
00138         if (playing)
00139                 PlayIncrement();
00140         
00141         if (!replay)
00142                 return;
00143         
00144         if (num_packets >= MAX_PACKETS)
00145         {
00146                 //write out a block of data to the file
00147                 //fwrite(
00148                 //cout << "Replay buffer full" << endl;
00149                 Stop();
00150                 Clear();
00151                 return;
00152         }
00153         
00154         //cout << "frame increment" << endl;
00155         
00156         int i;
00157         for (i = 0; i < fnum; i++)
00158         {
00159                 //if (funcmem[i].func_name == "gas")
00160                         //cout << "gas " << funcmem[i].lastupdateat << ":" << timeindex << " - " << funcmem[i].held << " " << funcmem[i].active << endl;
00161 
00162                 //only add a packet if it's non-held or if it's held but the value is different from the stored one
00163                 if (funcmem[i].active && (!funcmem[i].held || (funcmem[i].held && funcmem[i].oldval != funcmem[i].newval)))
00164                 {
00165                         packet[num_packets].time = timeindex;
00166                         packet[num_packets].val = funcmem[i].newval;
00167                         packet[num_packets].chardata[CHAR_FUNCNUM] = i;
00168                         //strcpy(packet[num_packets].dofunction, funcmem[i].func_name.c_str());
00169                         int newstate = 0;
00170                         if (funcmem[i].held)
00171                                 newstate = 1;
00172                         packet[num_packets].chardata[CHAR_STATE] = newstate;
00173                         
00174                         num_packets++;
00175                         
00176                         //cout << "added " << funcmem[i].func_name << " packet, " << timeindex << ": " << newstate << " - " << funcmem[i].newval << "/" << funcmem[i].oldval << endl;
00177                 }
00178                 
00179                 //add a "stop" packet to indicate the (held) function is no longer being
00180                 // called each frame.  only do this if there wasn't an update this frame
00181                 if (funcmem[i].lastupdateat != timeindex && funcmem[i].held && funcmem[i].active)
00182                 {
00183                         funcmem[i].active = false;
00184                         //cout << funcmem[i].lastupdateat << ":" << timeindex << endl;
00185                         //AddRecord(funcmem[i].func_name, funcmem[i].oldval, 2);
00186                         
00187                         packet[num_packets].time = timeindex;
00188                         packet[num_packets].val = funcmem[i].newval;
00189                         packet[num_packets].chardata[CHAR_FUNCNUM] = i;
00190                         //strcpy(packet[num_packets].dofunction, funcmem[i].func_name.c_str());
00191                         packet[num_packets].chardata[CHAR_STATE] = 2;
00192                         
00193                         num_packets++;
00194                 }
00195                 
00196                 //for non-held keys, set the active to false after one frame.
00197                 if (funcmem[i].active && !funcmem[i].held)
00198                         funcmem[i].active = false;
00199                 
00200                 //propagate the value in memory
00201                 funcmem[i].oldval = funcmem[i].newval;
00202                 
00203                 //if (funcmem[i].func_name == "gas")
00204                         //cout << "gas " << funcmem[i].lastupdateat << ":" << timeindex << " - " << funcmem[i].held << " " << funcmem[i].active << endl;
00205         }
00206         
00207         //record a state if necessary
00208         float remain;
00209         int mult;
00210         mult = (int) (timeindex / STATE_FREQUENCY);
00211         remain = timeindex - mult * STATE_FREQUENCY;
00212         if (remain < FrameTime())
00213         {
00214                 curstate.fnum = fnum;
00215                 if (curstate.funcmem != NULL)
00216                 {
00217                         delete [] curstate.funcmem;
00218                         curstate.funcmem = NULL;
00219                 }
00220                 curstate.funcmem = new FUNCTION_MEMORY_SYNC [fnum];
00221                 int i;
00222                 for (i = 0; i < fnum; i++)
00223                 {
00224                         curstate.funcmem[i].oldval = funcmem[i].oldval;
00225                         curstate.funcmem[i].newval = funcmem[i].newval;
00226                         curstate.funcmem[i].held = funcmem[i].held;
00227                         curstate.funcmem[i].active = funcmem[i].active;
00228                         curstate.funcmem[i].lastupdateat = funcmem[i].lastupdateat;
00229                 }
00230                 RememberCarState();
00231                 if (DBG_REPLAY)
00232                         cout << "Recording state at " << timeindex << endl;
00233         }
00234         
00235         timeindex += FrameTime();
00236         
00237         //cout << "frame finished" << endl;
00238         
00239         //cout << num_frames << endl;
00240 }
00241 
00242 extern void ResetWorld(bool fullreset);
00243 
00244 void REPLAY::Start()
00245 {
00246         if (state.GetGameState() != STATE_PLAYING && state.GetGameState() != STATE_STAGING)
00247                 return;
00248         
00249         if (state.GetGameMode() == MODE_TIMETRIAL)
00250                 state.SetGameState(STATE_STAGING);
00251         
00252         if (replay)
00253                 Stop();
00254         if (playing)
00255                 PlayStop();
00256         
00257         timer.Reset();
00258         
00259         //rebuild function memory
00260         BuildFuncMem(funcmem, fnum);
00261         
00262         Clear();
00263         replay = true;
00264         num_packets = 0;
00265         
00266         ResetWorld(true);
00267         //RememberCarState();
00268         
00269         //rf = fopen("replays/temp.vdr", "wb");
00270 }
00271 
00272 void REPLAY::Stop()
00273 {
00274         if (!replay)
00275                 return;
00276         
00277         replay = false;
00278         
00279         //cout << timeindex << endl;
00280         
00281         string filename = settings.GetSettingsDir() + "/replays/1.vdr";
00282         rf = fopen(filename.c_str(), "wb");
00283         
00284         WriteHeader(rf, funcmem, fnum, 0);
00285         
00286         //fwrite(packet, sizeof(REPLAY_PACKET), num_packets, rf);
00287         WritePackets(rf, packet, num_packets, state_mem, num_states);
00288         
00289         fclose(rf);
00290         
00291         if (funcmem != NULL)
00292                 delete [] funcmem;
00293         funcmem = NULL;
00294         
00295         //fclose(rf);
00296 }
00297 
00298 void REPLAY::WriteHeader(FILE * rf, FUNCTION_MEMORY * fmem, int fnm, int carnumber)
00299 {
00300         //write the file format version
00301         string ver = REPLAY_VERSION;
00302         fwrite(ver.c_str(), 1, ver.length(), rf);
00303         
00304         //write the current car
00305         int ln = state.GetCarName(carnumber).length();
00306         fwrite(&ln, 1, sizeof(int), rf);
00307         string cn = state.GetCarName(carnumber);
00308         fwrite(cn.c_str(), 1, cn.length(), rf);
00309         
00310         //write the current car paint
00311         int cp = state.GetCarPaint(carnumber);
00312         fwrite(&cp, sizeof(int), 1, rf);
00313         
00314         //write the current track
00315         ln = state.GetTrackName().length();
00316         fwrite(&ln, 1, sizeof(int), rf);
00317         fwrite(state.GetTrackName().c_str(), 1, state.GetTrackName().length(), rf);
00318         
00319         fwrite(&fnm, 1, sizeof(int), rf);
00320         
00321         int i;
00322         for (i = 0; i < fnm; i++)
00323         {
00324                 char fout[FUNCTION_CHARS];
00325                 strcpy(fout, fmem[i].func_name.c_str());
00326                 fwrite(fout,1,FUNCTION_CHARS, rf);
00327         }
00328 }
00329 
00330 void REPLAY::WritePackets(FILE * rf, REPLAY_PACKET * pak, int pnum, CARSTATE * smem, int snum)
00331 {
00332         int si = 0;
00333         int i;
00334         for (i = 0; i < pnum; i++)
00335         {
00336                 while (si < snum && smem[si].time <= pak[i].time)
00337                 {
00338                         unsigned char funccode = FUNCTION_STATEINFO;
00339                         fwrite(&funccode, 1, sizeof(unsigned char), rf);
00340                         smem[si].WriteToFile(rf);
00341                         
00342                         si++;
00343                 }
00344                 
00345                 fwrite(&pak[i], sizeof(REPLAY_PACKET), 1, rf);
00346         }
00347 }
00348 
00349 void REPLAY::BuildFuncMem(FUNCTION_MEMORY * &fmem, int & fnm)
00350 {
00351         if (fmem != NULL)
00352                 delete [] fmem;
00353         
00354         ifstream cl;
00355         cl.open(settings.GetFullDataPath("lists/control_list").c_str());
00356         int counter = 0;
00357         string junk = utility.sGetLine(cl);
00358         while (!cl.eof())
00359         {
00360                 counter++;
00361                 junk = utility.sGetLine(cl);
00362         }
00363         fnm = counter / 2;
00364         cl.close();
00365         cl.clear();
00366         cl.open(settings.GetFullDataPath("lists/control_list").c_str());
00367         fmem = new FUNCTION_MEMORY [fnm];
00368         int i;
00369         for (i = 0; i < fnm; i++)
00370         {
00371                 junk = utility.sGetLine(cl);
00372                 fmem[i].func_name = utility.sGetLine(cl);
00373                 fmem[i].oldval = -1337.0;
00374                 fmem[i].held = false;
00375                 fmem[i].active = false;
00376         }
00377         //cout << controlinfo.num_tokens << endl;
00378         cl.close();
00379 }
00380 
00381 float REPLAY::Recording()
00382 {
00383         if (!replay)
00384                 return -1;
00385         
00386         return (float) num_packets / (float) MAX_PACKETS;
00387 }
00388 
00389 //extern void SelectCar(string cfile, bool trim);
00390 extern void LoadWorld();
00391 
00392 bool REPLAY::PlayStart(string replayname)
00393 {
00394         return PlayStart(replayname, false);
00395 }
00396 
00397 bool REPLAY::PlayStart(string replayname, bool ngc)
00398 {       
00399         if (state.GetGameState() != STATE_PLAYING && state.GetGameState() != STATE_INITIALMENU && state.GetGameState() != STATE_STAGING)
00400                 return false;
00401         
00402         string replayfn;
00403         
00404         replayfn = settings.GetSettingsDir() + "/replays/" + replayname + ".vdr";
00405         
00406         if (!utility.FileExists(replayfn))
00407                 return false;
00408         
00409         ghostcar = ngc;
00410         
00411         if (state.GetGameState() == STATE_INITIALMENU)
00412                 state.SetGameState(STATE_PLAYING);
00413         
00414         if (state.GetGameMode() == MODE_TIMETRIAL)
00415                 state.SetGameState(STATE_STAGING);
00416         
00417         if (replay)
00418                 Stop();
00419         
00420         //cout << sizeof(REPLAY_PACKET) << endl;
00421         
00422         rf = fopen((replayfn).c_str(), "rb");
00423         
00424         if (rf == NULL)
00425                 return false;
00426         
00427         //BuildFuncMem();
00428         
00429         cur_packet = 0;
00430         cur_state = 0;
00431         
00432         REPLAY_PACKET tpacket;
00433         
00434         //check the file format version
00435         string ver = REPLAY_VERSION;
00436         char vs[ver.length()+1];
00437         fread(&vs, 1, ver.length(), rf);
00438         vs[ver.length()] = '\0';
00439         if (strcmp(vs, ver.c_str()) != 0)
00440         {
00441                 cout << "incompatible replay version: " << vs << endl;
00442                 fclose(rf);
00443                 return false;
00444         }
00445 
00446         //read the embedded car
00447         int ln;
00448         fread(&ln, 1, sizeof(ln), rf);
00449         char carname[256];
00450         fread(carname, sizeof(char), ln, rf);
00451         carname[ln] = '\0';
00452         replaycar = carname;
00453         
00454         //read the embedded car paint
00455         int paint = 0;
00456         fread(&paint, sizeof(int), 1, rf);
00457         replaypaint = paint;
00458         
00459         //read the embedded track
00460         fread(&ln, 1, sizeof(ln), rf);
00461         char trackname[256];
00462         fread(trackname, sizeof(char), ln, rf);
00463         trackname[ln] = '\0';
00464         state.SetTrackName(trackname);
00465         //car_paint = paint;
00466         state.SetCarPaint(0, paint);
00467         //change cars
00468         state.SetCarName(0, carname);
00469         
00470         //reload the world
00471         LoadWorld();
00472         
00473         timer.Reset();
00474         
00475         //build a function cache
00476         if (funcmem != NULL)
00477                 delete [] funcmem;
00478         
00479         fread(&fnum, 1, sizeof(int), rf);
00480         funcmem = new FUNCTION_MEMORY [fnum];
00481         int i;
00482         for (i = 0; i < fnum; i++)
00483         {
00484                 char fin[FUNCTION_CHARS];
00485                 fread(fin, 1, FUNCTION_CHARS, rf);
00486                 funcmem[i].func_name = fin;
00487                 funcmem[i].oldval = 0.0;
00488                 funcmem[i].held = false;
00489                 funcmem[i].active = false;
00490         }
00491         
00492         playing = true;
00493         
00494         //load up packets
00495         num_packets = 0;
00496         num_states = 0;
00497         while (!feof(rf))
00498         {
00499                 unsigned char nextfunc;
00500                 fread(&nextfunc, sizeof(unsigned char), 1, rf);
00501                 if (!feof(rf))
00502                 {
00503                         if (nextfunc == FUNCTION_STATEINFO)
00504                         {
00505                                 //fseek(rf, -1, SEEK_CUR);
00506                                 state_mem[num_states].ReadFromFile(rf);
00507                                 num_states++;
00508                         }
00509                         else
00510                         {
00511                                 fseek(rf, -1, SEEK_CUR);
00512                                 fread(&tpacket, sizeof(REPLAY_PACKET), 1, rf);
00513                                 packet[num_packets] = tpacket;
00514                                 playend = packet[num_packets].time;
00515                                 num_packets++;
00516                         }
00517                 }
00518         }
00519         
00520         if (DBG_REPLAY)
00521                 cout << num_packets << " packets, " << num_states << " states." << endl;
00522         
00523         ResetWorld(true);
00524         
00525         timeindex = 0;
00526         PlayProcessFrame();
00527         
00528         return true;
00529 }
00530 
00531 void REPLAY::PlayStop()
00532 {
00533         if (Playing() == -1)
00534                 return;
00535         
00536         state_to_load = false;
00537         
00538         if (funcmem != NULL)
00539         {
00540                 delete [] funcmem;
00541                 funcmem = NULL;
00542         }
00543         
00544         playing = false;
00545         
00546         fclose(rf);
00547 }
00548 
00549 float REPLAY::Playing()
00550 {
00551         if (!playing)
00552                 return -1;
00553         
00554         return (float) timeindex / (float) playend;
00555 }
00556 
00557 int REPLAY::GetNumFuncs()
00558 {
00559         return fnum;
00560 }
00561 
00562 void REPLAY::PlayIncrement()
00563 {
00564         if (cur_packet >= num_packets)
00565         {
00566                 //cout << "replay complete" << endl;
00567                 PlayStop();
00568                 return;
00569         }
00570         
00571         timeindex += FrameTime();
00572         
00573         PlayProcessFrame();
00574 }
00575 
00576 void REPLAY::PlayProcessFrame()
00577 {       
00578         if (DBG_REPLAY && timeindex - FrameTime()/2.0 < packet[cur_packet].time && timeindex + FrameTime()/2.0 > packet[cur_packet].time)
00579                 //cout << packet[cur_packet].time << "," << timeindex << endl;
00580                 printf("%f,%f\n", packet[cur_packet].time, timeindex);
00581         
00582         int i;
00583         for (i = 0; i < fnum; i++)
00584         {
00585                 if (!funcmem[i].held && funcmem[i].active)
00586                         funcmem[i].active = false;
00587         }
00588         
00589         state_to_load = false;
00590         
00591         //while (cur_state < num_states && timeindex - FrameTime()/2.0 < state_mem[cur_state].time && timeindex + FrameTime()/2.0 > state_mem[cur_state].time)
00592         /*while (cur_state < num_states && timeindex + FrameTime()/2.0 > state_mem[cur_state].time)
00593         {
00594                 //loadstate = cur_state;
00595                 state_to_load = true;
00596                 loadstate.CopyFrom(state_mem[cur_state]);
00597                 
00598                 for (i = 0; i < fnum; i++)
00599                 {
00600                         funcmem[i].oldval = loadstate.funcmem[i].oldval;
00601                         funcmem[i].newval = loadstate.funcmem[i].newval;
00602                         funcmem[i].held = loadstate.funcmem[i].held;
00603                         funcmem[i].active = loadstate.funcmem[i].active;
00604                         funcmem[i].lastupdateat = loadstate.funcmem[i].lastupdateat;
00605                 }
00606                 
00607                 //cout << loadstate << "/" << num_states << endl;
00608                 //cout << state_mem[cur_state].time << endl;
00609                 cur_state++;
00610         }*/
00611         
00612         CARSTATE * nextstate = GetNextState(timeindex + FrameTime()/2.0);
00613         while (nextstate != NULL)
00614         {
00615                 state_to_load = true;
00616                 loadstate.CopyFrom(*nextstate);
00617                 
00618                 for (i = 0; i < fnum; i++)
00619                 {
00620                         funcmem[i].oldval = loadstate.funcmem[i].oldval;
00621                         funcmem[i].newval = loadstate.funcmem[i].newval;
00622                         funcmem[i].held = loadstate.funcmem[i].held;
00623                         funcmem[i].active = loadstate.funcmem[i].active;
00624                         funcmem[i].lastupdateat = loadstate.funcmem[i].lastupdateat;
00625                 }
00626                 
00627                 nextstate = GetNextState(timeindex + FrameTime()/2.0);
00628         }
00629         
00630         //while (cur_packet < num_packets && timeindex - FrameTime()/2.0 < packet[cur_packet].time && timeindex + FrameTime()/2.0 > packet[cur_packet].time)
00631         /*while (cur_packet < num_packets && timeindex + FrameTime()/2.0 > packet[cur_packet].time)
00632         {
00633                 //cout << timeindex << endl;
00634                 
00635                 //string curfunc = packet[cur_packet].dofunction;
00636                 //if (CHAR_FUNCNUM < 200)
00637                 {
00638                         string curfunc = funcmem[packet[cur_packet].chardata[CHAR_FUNCNUM]].func_name;
00639                 
00640                         int funcidx = 0;
00641                         for (i = 0; i < fnum; i++)
00642                         {
00643                                 if (funcmem[i].func_name == curfunc)
00644                                         funcidx = i;
00645                         }
00646                         
00647                         funcmem[funcidx].newval = packet[cur_packet].val;
00648                         if (packet[cur_packet].chardata[CHAR_STATE] == 0)
00649                                 funcmem[funcidx].held = false;
00650                         if (packet[cur_packet].chardata[CHAR_STATE] == 1)
00651                                 funcmem[funcidx].held = true;
00652                         
00653                         if (packet[cur_packet].chardata[CHAR_STATE] == 2)
00654                                 funcmem[funcidx].active = false;
00655                         else
00656                                 funcmem[funcidx].active = true;
00657                 }
00658                 
00659                 cur_packet++;
00660         }*/
00661         
00662         REPLAY_PACKET * nextpacket = GetNextPacket(timeindex + FrameTime()/2.0);
00663         while (nextpacket != NULL)
00664         {
00665                 string curfunc = funcmem[nextpacket->chardata[CHAR_FUNCNUM]].func_name;
00666         
00667                 int funcidx = 0;
00668                 for (i = 0; i < fnum; i++)
00669                 {
00670                         if (funcmem[i].func_name == curfunc)
00671                                 funcidx = i;
00672                 }
00673                 
00674                 funcmem[funcidx].newval = nextpacket->val;
00675                 if (nextpacket->chardata[CHAR_STATE] == 0)
00676                         funcmem[funcidx].held = false;
00677                 if (nextpacket->chardata[CHAR_STATE] == 1)
00678                         funcmem[funcidx].held = true;
00679                 
00680                 if (nextpacket->chardata[CHAR_STATE] == 2)
00681                         funcmem[funcidx].active = false;
00682                 else
00683                         funcmem[funcidx].active = true;
00684                 
00685                 nextpacket = GetNextPacket(timeindex + FrameTime()/2.0);
00686         }
00687 }
00688 
00689 FUNCTION_MEMORY REPLAY::GetFunc(int idx)
00690 {
00691         return funcmem[idx];
00692 }
00693 
00694 int REPLAY::GetFuncIdx(string funcname)
00695 {
00696         int i;
00697         int idx = -1;
00698         for (i = 0; i < fnum; i++)
00699         {
00700                 if (funcmem[i].func_name == funcname)
00701                         idx = i;
00702         }
00703         
00704         if (idx < 0)
00705         {
00706                 cout << "Error in GetFuncIdx: " << funcname << endl;
00707                 return 0;
00708         }
00709         else
00710                 return idx;
00711 }
00712 
00713 double REPLAY::GetTime()
00714 {
00715         if (replay || playing)
00716                 return timeindex;
00717         else
00718                 return 0.0;
00719 }
00720 
00721 void CARSTATE::CopyFrom(CARSTATE other)
00722 {
00723         time = other.time;
00724         chassispos = other.chassispos;
00725         chassisorientation = other.chassisorientation;
00726         chassisvel = other.chassisvel;
00727         chassisangvel = other.chassisangvel;
00728         int i;
00729         for (i = 0; i < 4; i++)
00730         {
00731                 suspdisp[i] = other.suspdisp[i];
00732                 suspcompvel[i] = other.suspcompvel[i];
00733                 tirespeed[i] = other.tirespeed[i];
00734         }
00735         gear = other.gear;
00736         enginespeed = other.enginespeed;
00737         clutchspeed = other.clutchspeed;
00738         enginedrag = other.enginedrag;
00739         
00740         segment = other.segment;
00741         
00742         if (funcmem != NULL)
00743         {
00744                 delete [] funcmem;
00745                 funcmem = NULL;
00746         }
00747         
00748         fnum = other.fnum;
00749         funcmem = new FUNCTION_MEMORY_SYNC [fnum];
00750         for (i = 0; i < fnum; i++)
00751         {
00752                 funcmem[i].oldval = other.funcmem[i].oldval;
00753                 funcmem[i].newval = other.funcmem[i].newval;
00754                 funcmem[i].held = other.funcmem[i].held;
00755                 funcmem[i].active = other.funcmem[i].active;
00756                 funcmem[i].lastupdateat = other.funcmem[i].lastupdateat;
00757         }
00758 }
00759 
00760 void REPLAY::RememberCarState()
00761 {
00762         state_mem[num_states].CopyFrom(curstate);
00763         /*state_mem[num_states].fnum = fnum;
00764         if (state_mem[num_states].funcmem != NULL)
00765         {
00766                 delete [] state_mem[num_states].funcmem;
00767                 state_mem[num_states].funcmem = NULL;
00768         }
00769         state_mem[num_states].funcmem = new FUNCTION_MEMORY_SYNC [fnum];
00770         int i;
00771         for (i = 0; i < fnum; i++)
00772         {
00773                 state_mem[num_states].funcmem->oldval = funcmem->oldval;
00774                 state_mem[num_states].funcmem->newval = funcmem->newval;
00775                 state_mem[num_states].funcmem->held = funcmem->held;
00776                 state_mem[num_states].funcmem->active = funcmem->active;
00777                 state_mem[num_states].funcmem->lastupdateat = funcmem->lastupdateat;
00778         }*/
00779         
00780         num_states++;
00781         
00782         if (num_states >= MAX_STATES)
00783         {
00784                 cout << "Maximum number of replay states exceeded, replay is too long" << endl;
00785                 num_states = MAX_STATES-1;
00786         }
00787 }
00788 
00789 void CARSTATE::WriteToFile(FILE * fout)
00790 {
00791         fwrite(&time, sizeof(double), 1, fout);
00792         WriteVector(chassispos, fout);
00793         WriteMatrix(chassisorientation, fout);
00794         WriteVector(chassisvel, fout);
00795         WriteVector(chassisangvel, fout);
00796         
00797         int i;
00798         for (i = 0; i < 4; i++)
00799         {
00800                 fwrite(&suspdisp[i], sizeof(double), 1, fout);
00801                 fwrite(&suspcompvel[i], sizeof(double), 1, fout);
00802                 WriteVector(whlangvel[i], fout);
00803                 fwrite(&tirespeed[i], sizeof(double), 1, fout);
00804         }
00805         
00806         fwrite(&gear, sizeof(int), 1, fout);
00807         fwrite(&enginespeed, sizeof(double), 1, fout);
00808         fwrite(&clutchspeed, sizeof(double), 1, fout);
00809         fwrite(&enginedrag, sizeof(double), 1, fout);
00810         
00811         fwrite(&segment, sizeof(int), 1, fout);
00812         
00813         //write a function state block
00814         fwrite(&fnum, sizeof(int), 1, fout);
00815         
00816         for (i = 0; i < fnum; i++)
00817         {
00818                 fwrite(&(funcmem[i]), sizeof(struct FUNCTION_MEMORY_SYNC), 1, fout);
00819         }
00820 }
00821 
00822 void CARSTATE::WriteVector(Vamos_Geometry::Three_Vector wv, FILE * fout)
00823 {
00824         fwrite(&wv[0], sizeof(double), 1, fout);
00825         fwrite(&wv[1], sizeof(double), 1, fout);
00826         fwrite(&wv[2], sizeof(double), 1, fout);
00827 }
00828 
00829 void CARSTATE::WriteMatrix(Vamos_Geometry::Three_Matrix wv, FILE * fout)
00830 {
00831         fwrite(&wv[0][0], sizeof(double), 1, fout);
00832         fwrite(&wv[0][1], sizeof(double), 1, fout);
00833         fwrite(&wv[0][2], sizeof(double), 1, fout);
00834         
00835         fwrite(&wv[1][0], sizeof(double), 1, fout);
00836         fwrite(&wv[1][1], sizeof(double), 1, fout);
00837         fwrite(&wv[1][2], sizeof(double), 1, fout);
00838         
00839         fwrite(&wv[2][0], sizeof(double), 1, fout);
00840         fwrite(&wv[2][1], sizeof(double), 1, fout);
00841         fwrite(&wv[2][2], sizeof(double), 1, fout);
00842 }
00843 
00844 void CARSTATE::ReadFromFile(FILE * fin)
00845 {
00846         fread(&time, sizeof(double), 1, fin);
00847         ReadVector(chassispos, fin);
00848         ReadMatrix(chassisorientation, fin);
00849         ReadVector(chassisvel, fin);
00850         ReadVector(chassisangvel, fin);
00851         
00852         int i;
00853         for (i = 0; i < 4; i++)
00854         {
00855                 fread(&suspdisp[i], sizeof(double), 1, fin);
00856                 fread(&suspcompvel[i], sizeof(double), 1, fin);
00857                 ReadVector(whlangvel[i], fin);
00858                 fread(&tirespeed[i], sizeof(double), 1, fin);
00859         }
00860         
00861         fread(&gear, sizeof(int), 1, fin);
00862         fread(&enginespeed, sizeof(double), 1, fin);
00863         fread(&clutchspeed, sizeof(double), 1, fin);
00864         fread(&enginedrag, sizeof(double), 1, fin);
00865         
00866         fread(&segment, sizeof(int), 1, fin);
00867         
00868         //read in a function state block
00869         fread(&fnum, sizeof(int), 1, fin);
00870         
00871         if (funcmem != NULL)
00872         {
00873                 delete [] funcmem;
00874                 funcmem = NULL;
00875         }
00876         
00877         funcmem = new FUNCTION_MEMORY_SYNC [fnum];
00878         
00879         for (i = 0; i < fnum; i++)
00880         {
00881                 fread(&(funcmem[i]), sizeof(struct FUNCTION_MEMORY_SYNC), 1, fin);
00882         }
00883 }
00884 
00885 void CARSTATE::ReadVector(Vamos_Geometry::Three_Vector &wv, FILE * fin)
00886 {
00887         fread(&wv[0], sizeof(double), 1, fin);
00888         fread(&wv[1], sizeof(double), 1, fin);
00889         fread(&wv[2], sizeof(double), 1, fin);
00890 }
00891 
00892 void CARSTATE::ReadMatrix(Vamos_Geometry::Three_Matrix &wv, FILE * fin)
00893 {
00894         fread(&wv.m_mat[0][0], sizeof(double), 1, fin);
00895         fread(&wv.m_mat[0][1], sizeof(double), 1, fin);
00896         fread(&wv.m_mat[0][2], sizeof(double), 1, fin);
00897         
00898         fread(&wv.m_mat[1][0], sizeof(double), 1, fin);
00899         fread(&wv.m_mat[1][1], sizeof(double), 1, fin);
00900         fread(&wv.m_mat[1][2], sizeof(double), 1, fin);
00901         
00902         fread(&wv.m_mat[2][0], sizeof(double), 1, fin);
00903         fread(&wv.m_mat[2][1], sizeof(double), 1, fin);
00904         fread(&wv.m_mat[2][2], sizeof(double), 1, fin);
00905 }
00906 
00907 /*int REPLAY::LoadState()
00908 {
00909         if (loadstate >= num_states)
00910                 return -1;
00911         else
00912                 return loadstate;
00913 }*/
00914 
00915 CARSTATE * REPLAY::LoadState()
00916 {
00917         if (state_to_load)
00918                 return &loadstate;
00919         else
00920                 return NULL;
00921 }
00922 
00923 void REPLAY::Jump(double newtime)
00924 {       
00925         if (Playing() != -1)
00926         {
00927                 int mult = (int)(newtime / STATE_FREQUENCY);
00928                 newtime = (double) mult * STATE_FREQUENCY;
00929                 
00930                 //cout << "jump: " << newtime << "," << timeindex << endl;
00931                 
00932                 if (newtime > timeindex)
00933                 {
00934                         int prev = cur_state;
00935                         
00936                         //ff through states
00937                         while (cur_state < num_states && state_mem[cur_state].time < newtime - FrameTime()/2.0)
00938                                 cur_state++;
00939                         
00940                         //cout << cur_state - prev << " states" << endl;
00941                         //cout << "now on " << cur_state << endl;
00942                         
00943                         prev = cur_packet;
00944                         
00945                         //ff through packets
00946                         while (cur_packet < num_packets && packet[cur_packet].time < newtime - FrameTime()/2.0)
00947                                 cur_packet++;
00948                         
00949                         //cout << cur_packet - prev << " packets" << endl;
00950                         //cout << "now on " << cur_packet << endl;
00951                 }
00952                 
00953                 if (newtime < timeindex)
00954                 {
00955                         //rw through states
00956                         while (cur_state > 0 && state_mem[cur_state].time > newtime + FrameTime()/2.0)
00957                                 cur_state--;
00958                         
00959                         //rw through packets
00960                         while (cur_packet > 0 && packet[cur_packet].time > newtime + FrameTime()/2.0)
00961                                 cur_packet--;
00962                 }
00963                 
00964                 timeindex = newtime;
00965         }
00966 }
00967 
00968 CARSTATE * REPLAY::GetNextState(double until)
00969 {
00970         if (cur_state < num_states && state_mem[cur_state].time < until)
00971         {
00972                 if (DBG_REPLAY)
00973                         cout << "Reading state at " << timeindex << endl;
00974                 cur_state++;
00975                 return &(state_mem[cur_state-1]);
00976         }
00977         
00978         return NULL;
00979 }
00980 
00981 REPLAY_PACKET * REPLAY::GetNextPacket(double until)
00982 {
00983         if (cur_packet < num_packets && packet[cur_packet].time < until)
00984         {
00985                 cur_packet++;
00986                 return &(packet[cur_packet-1]);
00987         }
00988         
00989         return NULL;
00990 }

Generated on Thu Oct 19 04:05:54 2006 by  doxygen 1.4.6