00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00083
00084
00085
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
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
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
00124
00125 }
00126 }
00127 }
00128
00129 extern float FrameTime();
00130
00131 void REPLAY::IncrementFrame()
00132 {
00133
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
00147
00148
00149 Stop();
00150 Clear();
00151 return;
00152 }
00153
00154
00155
00156 int i;
00157 for (i = 0; i < fnum; i++)
00158 {
00159
00160
00161
00162
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
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
00177 }
00178
00179
00180
00181 if (funcmem[i].lastupdateat != timeindex && funcmem[i].held && funcmem[i].active)
00182 {
00183 funcmem[i].active = false;
00184
00185
00186
00187 packet[num_packets].time = timeindex;
00188 packet[num_packets].val = funcmem[i].newval;
00189 packet[num_packets].chardata[CHAR_FUNCNUM] = i;
00190
00191 packet[num_packets].chardata[CHAR_STATE] = 2;
00192
00193 num_packets++;
00194 }
00195
00196
00197 if (funcmem[i].active && !funcmem[i].held)
00198 funcmem[i].active = false;
00199
00200
00201 funcmem[i].oldval = funcmem[i].newval;
00202
00203
00204
00205 }
00206
00207
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
00238
00239
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
00260 BuildFuncMem(funcmem, fnum);
00261
00262 Clear();
00263 replay = true;
00264 num_packets = 0;
00265
00266 ResetWorld(true);
00267
00268
00269
00270 }
00271
00272 void REPLAY::Stop()
00273 {
00274 if (!replay)
00275 return;
00276
00277 replay = false;
00278
00279
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
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
00296 }
00297
00298 void REPLAY::WriteHeader(FILE * rf, FUNCTION_MEMORY * fmem, int fnm, int carnumber)
00299 {
00300
00301 string ver = REPLAY_VERSION;
00302 fwrite(ver.c_str(), 1, ver.length(), rf);
00303
00304
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
00311 int cp = state.GetCarPaint(carnumber);
00312 fwrite(&cp, sizeof(int), 1, rf);
00313
00314
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
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
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
00421
00422 rf = fopen((replayfn).c_str(), "rb");
00423
00424 if (rf == NULL)
00425 return false;
00426
00427
00428
00429 cur_packet = 0;
00430 cur_state = 0;
00431
00432 REPLAY_PACKET tpacket;
00433
00434
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
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
00455 int paint = 0;
00456 fread(&paint, sizeof(int), 1, rf);
00457 replaypaint = paint;
00458
00459
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
00466 state.SetCarPaint(0, paint);
00467
00468 state.SetCarName(0, carname);
00469
00470
00471 LoadWorld();
00472
00473 timer.Reset();
00474
00475
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
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
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
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
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
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
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
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
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
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
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
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
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
00908
00909
00910
00911
00912
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
00931
00932 if (newtime > timeindex)
00933 {
00934 int prev = cur_state;
00935
00936
00937 while (cur_state < num_states && state_mem[cur_state].time < newtime - FrameTime()/2.0)
00938 cur_state++;
00939
00940
00941
00942
00943 prev = cur_packet;
00944
00945
00946 while (cur_packet < num_packets && packet[cur_packet].time < newtime - FrameTime()/2.0)
00947 cur_packet++;
00948
00949
00950
00951 }
00952
00953 if (newtime < timeindex)
00954 {
00955
00956 while (cur_state > 0 && state_mem[cur_state].time > newtime + FrameTime()/2.0)
00957 cur_state--;
00958
00959
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 }