1 #pragma once
2 #include "../vdrift/mathvector.h"
3 #include "../vdrift/quaternion.h"
4 #include <OgreVector3.h>
5 #include "half.hpp"
6 #include <OgrePrerequisites.h>  //
7 using Ogre::uchar;
8 using Ogre::ushort;
9 class CAR;
10 using half_float::half;
11 
12 //  replay load log and check
13 #define LOG_RPL
14 
15 
16 //  NEW replays since 2.6
17 //  variable header and frame sizes
18 //----------------------------------------------------------------------------------------
19 
20 /// size of ReplayFrame2
21 //= 202 Bytes per frame (minimal,approx)
22 //  202 * 80 fps = 16.1 kB/s
23 //  1 min = 970 kB, 10 min = 9.7 MB
24 
25 struct ReplayHeader2
26 {
27 	char head[5];  // "SR/^ "
28 	short ver;
29 	float time;  // total time
30 
31 	std::string track;   // track name
32 	char track_user;  // user/original
33 
34 	char numPlayers;
35 	std::vector<std::string> cars;  // car names eg. ES
36 	std::vector<uchar> numWh;  //wheels count for all cars
37 
38 	float trees;      // trees multipler
39 	char num_laps;
40 	char networked;   // if 1, was networked, so use nicks when playing
41 	std::string sim_mode;  // easy, normal, etc
42 
43 	std::vector<std::string> nicks;  // multiplayer nicks
44 	//std::vector<float> hue,sat,val,gloss,refl;  // cars colors?
45 
46 	ReplayHeader2();
47 	void Default(), SetHead();
48 	void FromOld(const struct ReplayHeader& hdr);
49 };
50 
51 //  car data, for each simulation frame
52 //--------------------------------------------
53 enum eFlags {  b_braking=0, b_scrap, b_hit, b_fluid, b_hov };  // max 8
54 
55 //  wheel
56 struct RWheel
57 {
58 	MATHVECTOR<float,3> pos;
59 	QUATERNION<half> rot;
60 
61 	//  trails, particles, snd
62 	char surfType, whTerMtr;  //TRACKSURFACE::TYPE
63 	char whRoadMtr, whP;  //particle type
64 
65 	//  tire
66 	half squeal, slide, whVel;
67 	half suspVel, suspDisp;
68 
69 	//  fluids
70 	uchar whH;  // /var - submerge
71 	half whAngVel;
72 	half whSteerAng;  // 38B
73 };
74 
75 struct RScrap
76 {
77 	half fScrap, fScreech;  // 4B
78 };
79 
80 struct RHit
81 {
82 	half fHitForce, fParIntens, fParVel;
83 	Ogre::Vector3 vHitPos, vHitNorm;  // world hit data
84 };  // 30B
85 
86 struct ReplayFrame2
87 {
88 	//dont use int, not portable
89 
90 	//  time  since game start
91 	float time;
92 
93 	//  car
94 	MATHVECTOR<float,3> pos;
95 	QUATERNION<float> rot;
96 	// 32B  (size in Bytes so far)
97 
98 	// cant use bit fields, not portable
99 	uchar fl;  // flags, bool 1bit
setReplayFrame2100 	void set(eFlags e, bool b) {  if (b)  fl |= 1 << e;  else  fl &= ~(1 << e); }
getReplayFrame2101 	bool get(eFlags e) const   {  return ((fl >> e) & 1u) > 0;  }
102 	// 35B
103 
104 	//  hud
105 	char gear;
106 	half rpm,vel;
107 	uchar damage, clutch;
108 	uchar percent;  // track % val
109 	// 41B
110 
111 	//  sound, input
112 	uchar throttle, fboost;  char steer;
113 	half speed, dynVel;
114 	// 48B
115 
116 	//  ext
117 	half whMudSpin;  //-2 /var - may not be saved, check flags
118 	half hov_roll;  //-2 /var - V1 roll_ang or sph_yaw for O
119 
120 
121 	//  wheel
122 	std::vector<RWheel> wheels;  // 38B  vec-24B
123 
124 	//  hit continuous
125 	std::vector<RScrap> scrap;  // 4B
126 
127 	//  hit impact, sparks
128 	half fHitTime;
129 	std::vector<RHit> hit;  // 30B  saved on hit only
130 	// 50B
131 
132 
133 	ReplayFrame2();
134 	void FromCar(const CAR* pCar, half prevHitTime);
135 	void FromOld(const struct ReplayFrame& fr, uchar numWh, half prevHitTime);
136 
137 	//total: 50B + 4*38B = 202B min
138 };
139 
140 //  Replay
141 //--------------------------------------------
142 class Replay2
143 {
144 public:
145 	Replay2();
146 
147 	bool LoadFile(std::string file, bool onlyHdr=false);
148 	bool SaveFile(std::string file);
149 
150 	void AddFrame(const ReplayFrame2& frame, int carNum);    // record
151 	bool GetFrame(float time, ReplayFrame2* fr, int carNum);  // play
GetFrame0(int id)152 	const ReplayFrame2& GetFrame0(int id){  return frames[0][id];  }
153 
154 	const float GetTimeLength() const;  // total time in seconds
GetNumFrames()155 	const int GetNumFrames() const {  return frames.empty() ? 0 : frames[0].size();  }
156 
157 	bool GetLastFrame(ReplayFrame2* pFr, int carNum);
158 	half GetLastHitTime(int carNum);
159 
160 	//  inits only basic header data, fill the rest after
161 	void InitHeader(const char* track, bool trk_user, bool bClear);
162 	void Clear(bool time=true);  // call this after header.numPlayers change
163 	void ClearCars();
164 
165 	void CopyFrom(const Replay2& rpl);
166 	void DeleteFrames(int carNum, float fromTime);
167 
168 	static bool fixOldTrkName(std::string& trk);  // old
169 
170 	ReplayHeader2 header;
171 private:
172 	typedef std::vector<ReplayFrame2> Frames;  // 1 player
173 	std::vector<Frames> frames;  // all plrs
174 	int idLast;  // last index from GetFrame
175 };
176 
177 
178 //  OLD replays, const size
179 //-----------------------------------------------------------------------------------------------------------
180 
181 const static int ciRplHdrSize = 1024;
182 const static int cDefSize = 8*1024;
183 
184 
185 // note: add new vars always at end of
186 // ReplayHeader or ReplayFrame structs (backward compatibility)
187 
188 /// size of ReplayFrame Old
189 //= 400 Bytes per frame
190 //  400 * 160 fps = 64 kB/s
191 //  1 min = 3.84 MB, 10 min = 38.4 MB
192 
193 
194 //  Replay  whole replay/ghost data - max 4 players, max 4 wheels
195 //--------------------------------------------
196 struct ReplayHeader
197 {
198 	char head[5];  // "SR\_ "
199 	typedef char ChName[32];
200 
201 	char track[63];   // track name  (hmap crc? diff-)
202 	char track_user;  // user/original
203 	ChName car;       // car name  (eg. ES, .car file crc?, settings diff-)
204 
205 	int ver, frameSize;  // bin data format - sizeof(ReplayFrame)
206 	float whR[4][4];  // cars wheels radius (not used now)
207 
208 	int numPlayers;
209 	float hue[4],sat[4],val[4];  // cars colors
210 	ChName cars[3];   // car names (when numPlayers > 1)
211 
212 	ChName nicks[4];  // multiplayer nicks
213 	char descr[128];  // description - user text (wasnt used)
214 	float trees;      // trees multipler
215 	char num_laps;
216 	char networked;   // if 1, was networked, so use nicks when playing
217 	char sim_mode[32];// easy, normal, etc
218 
219 	ReplayHeader();
220 	void Default(), SafeEnd0();
221 };
222 
223 //  Replay  car data, for each simulation frame
224 //--------------------------------------------
225 struct ReplayFrame
226 {
227 	//  time  since game start
228 	double time;
229 	//  car & wheels
230 	MATHVECTOR<float,3> pos, whPos[4];
231 	QUATERNION<float> rot, whRot[4];
232 
233 	//  hud
234 	float rpm,vel, clutch;  int gear;  //char
235 
236 	//  sound, input
237 	float throttle, steer;
238 	MATHVECTOR<float,3> posEngn;  //snd engine pos --
239 	float speed, dynVel;
240 
241 	//  wheel trails, particles, snd
242 	char surfType[4], whTerMtr[4];  //TRACKSURFACE::TYPE
243 	float squeal[4], slide[4], whVel[4];
244 	float suspVel[4], suspDisp[4];
245 
246 	float fboost;  // input, particles
247 	char whRoadMtr[4];
248 
249 	//  fluids
250 	float whH[4], whAngVel[4];  // submerge height
251 	char whP[4];  //particle type
252 	float whSteerAng[2];
253 
254 	float percent;  // track % val
255 	char braking;  // for rear car lights (bool)
256 
257 	//  hit sparks
258 	float fHitTime, fParIntens,fParVel;
259 	Ogre::Vector3 vHitPos,vHitNorm;  // world hit data
260 	float whMudSpin, fHitForce, fCarScrap, fCarScreech;
261 	float hov_roll;  //=sph_yaw for O
262 
263 	//uchar damage;  //todo..
264 
265 	ReplayFrame();
266 	void FromCar(const CAR* pCar);
267 };
268 
269 //  Replay
270 //--------------------------------------------
271 class Replay
272 {
273 public:
274 	Replay();
275 
276 	bool LoadFile(std::string file, bool onlyHdr=false);
277 	bool SaveFile(std::string file);
278 
279 	void AddFrame(const ReplayFrame& frame, int carNum);    // record
280 	bool GetFrame(double time, ReplayFrame* fr, int carNum);  // play
GetFrame0(int id)281 	const ReplayFrame& GetFrame0(int id){  return frames[0][id];  }
282 
283 	const double GetTimeLength(int carNum=0) const;  // total time in seconds
GetNumFrames()284 	const int GetNumFrames() const {  return frames[0].size();  }
285 
286 	//  inits only basic header data, fill the rest after
287 	void InitHeader(const char* track, bool trk_user, const char* car, bool bClear);
288 	void Clear();  // call this after header.numPlayers change
289 	void CopyFrom(const Replay& rpl);
290 	void DeleteFrames(int carNum, double fromTime);
291 
292 	static bool fixOldTrkName(std::string& trk);  // old
293 
294 	ReplayHeader header;
295 	//ReplayHeader2 header;
296 private:
297 	friend class Replay2;
298 	typedef std::vector<ReplayFrame> Frames;  // 1 player
299 	std::vector<Frames> frames;  // all plrs
300 	int idLast;  // last index from GetFrame
301 };
302 
303 
304 
305 //  Rewind  only data for car sim, to rewind back
306 //-----------------------------------------------------------------------------------------------------------
307 struct RewindFrame
308 {
309 	//  time  since game start
310 	double time;
311 	//  car
312 	MATHVECTOR<float,3> pos, vel, angvel;
313 	QUATERNION<float> rot;
314 	float fDamage, hov_roll;
315 	//engine rpm?..
316 };
317 
318 
319 ///  Rewind
320 //  to move car back in time, not saved in file, can have less frames than replay
321 //--------------------------------------------
322 class Rewind
323 {
324 public:
325 	Rewind();
326 
327 	void AddFrame(const RewindFrame& frame, int carNum);
328 	bool GetFrame(double time, RewindFrame* fr, int carNum);
329 
330 	const double GetTimeLength(int carNum=0) const;  // total time in seconds
331 
332 	void Clear();
333 private:
334 	std::vector<RewindFrame> frames[4];  // 4 players max (split screen)
335 	int idLast[4];  // last index from GetFrame (optimisation)
336 };
337