1 
2 // vehicle.h [psim]
3 
4 // Copyright 2004-2006 Jasmine Langridge, jas@jareiko.net
5 // License: GPL version 2 (see included gpl.txt)
6 
7 //
8 // This file contains definitions and classes related to Vehicles
9 //
10 
11 #include "engine.h"
12 
13 // vehicle core types
14 enum class v_core_type{
15 	car,
16 	tank,
17 	helicopter,
18 	plane,
19 	hovercraft
20 };
21 
22 
23 // vehicle clip point types
24 enum class v_clip_type{
25 	body,
26 	drive_left,
27 	drive_right,
28 	hover
29 };
30 
31 // MPS = metres per second
32 // KPH = kilometres per hour
33 // MPH = miles per hour
34 
35 #define MPS_TO_MPH(x) ((x) * 2.23693629f) // thanks Google!
36 #define MPS_TO_KPH(x) ((x) * 3.6f)
37 
38 // Starting position in degrees, measured counter-clockwise from the x-axis.
39 #define MPH_ZERO_DEG 210
40 #define KPH_ZERO_DEG 220
41 
42 // Degrees to rotate the speedo needle for each unit of speed
43 #define DEG_PER_MPH 1.5f
44 #define DEG_PER_KPH 1.0f
45 
46 // Multiplier for mps to speed in some unit
47 const float MPS_MPH_SPEED_MULT = 2.23693629f;
48 const float MPS_KPH_SPEED_MULT = 3.6f;
49 
50 // Multiplier for mps to degs on the speedo dial
51 const float MPS_MPH_DEG_MULT = MPS_MPH_SPEED_MULT * DEG_PER_MPH;
52 const float MPS_KPH_DEG_MULT = MPS_KPH_SPEED_MULT * DEG_PER_KPH;
53 
54 ///
55 /// @brief class which contains the control status of a vehicle
56 ///
57 struct v_control_s {
58   // shared
59   float throttle;
60   float brake1,brake2;
61   vec3f turn;
62   vec2f aim;
63 
64   // helicopter
65   float collective;
66 
67   // -- utility --
68 
setZerov_control_s69   void setZero() {
70     throttle = 0.0f;
71     brake1 = 0.0f;
72     brake2 = 0.0f;
73     turn = vec3f::zero();
74     aim = vec2f::zero();
75     collective = 0.0f;
76   }
77 
setDefaultRatesv_control_s78   void setDefaultRates() {
79     throttle = 10.0f;
80     brake1 = 10.0f;
81     brake2 = 10.0f;
82     turn = vec3f(10.0f,10.0f,10.0f);
83     aim = vec2f(10.0f,10.0f);
84     collective = 10.0f;
85   }
86 
87   ///
88   /// @brief ensure all the values are within range
89   ///
clampv_control_s90   void clamp() {
91     CLAMP(throttle, -1.0f, 1.0f);
92     CLAMP(brake1, 0.0f, 1.0f);
93     CLAMP(brake2, 0.0f, 1.0f);
94     CLAMP(turn.x, -1.0f, 1.0f);
95     CLAMP(turn.y, -1.0f, 1.0f);
96     CLAMP(turn.z, -1.0f, 1.0f);
97     CLAMP(aim.x, -1.0f, 1.0f);
98     CLAMP(aim.y, -1.0f, 1.0f);
99     CLAMP(collective, -1.0f, 1.0f);
100   }
101 };
102 
103 // @todo Why call the same class in two ways?
104 typedef v_control_s v_state_s;
105 
106 
107 struct vehicle_clip_s {
108   vec3f pt;
109   v_clip_type type;
110   float force, dampening;
111 };
112 
113 ///
114 /// @brief stores a type of wheel and its stats
115 ///
116 struct PVehicleTypeWheel {
117   // its position
118   vec3f pt;
119   float radius;
120   // performance
121   float drive, steer, brake1, brake2;
122   // suspension proper resistance force
123   float force;
124   float dampening;
125 
126   // frictions value of the wheel with the ground (around 0.03)
127   float friction;
128 };
129 
130 ///
131 /// @brief stores a type of part
132 ///
133 struct PVehicleTypePart {
134   std::string name, parentname;
135   int parent;
136 
137   PReferenceFrame ref_local;
138 
139   std::vector<vehicle_clip_s> clip;
140 
141   std::vector<PVehicleTypeWheel> wheel;
142 
143   std::vector<PReferenceFrame> flame;
144 
145   float scale;
146   PModel *model;
147 };
148 
149 ///
150 /// @brief class which store a model (type) of vehicle: e.g. name, specifications
151 ///
152 class PVehicleType : public PResource {
153 public:
154 
155   // Statistics and stuff displayed to the user, not actually used in the simulation
156   std::string proper_name;
157   std::string proper_class;  // class name (i.e. "WRC")
158 
159   // how many wheels drive
160   std::string pstat_wheeldrive;
161 
162   // contains 100 times the average wheel roadholding in human readable form
163   std::string pstat_roadholding;
164 
165   // contains the engine max power in human readable form
166   std::string pstat_enginepower;
167 
168   // type of vehicle (usually car)
169   v_core_type coretype;
170 
171   // mass
172   float mass;
173 
174   // dimensions (aproximated as a cuboid)
175   vec3f dims;
176 
177   // parts which compose the vehicle
178   std::vector<PVehicleTypePart> part;
179 
180   // wheel scale
181   float wheelscale;
182 
183   // wheel model
184   PModel *wheelmodel;
185 
186   // Car statistics (powercurve, gears...)
187   PEngine engine;
188 
189   float inverse_drive_total;
190 
191   float wheel_speed_multiplier;
192 
193   // Vehicle dinamic specification
194   struct {
195     // shared
196     float speed;
197     vec3f turnspeed;
198     float turnspeed_a, turnspeed_b; // turnspeed = a + b * speed
199     vec3f drag;
200     float angdrag; // angular drag
201     vec2f lift; // x = fin lift (hz), y = wing lift (vt)
202     vec2f fineffect; // x = rudder/fin (hz), y = tail (vt)
203   } param;
204 
205   // vehicle specific control specifications
206   v_control_s ctrlrate;
207 
208 public:
PVehicleType()209   PVehicleType() { }
~PVehicleType()210   ~PVehicleType() { unload(); }
211 
212 public:
213   bool load(const std::string &filename, PSSModel &ssModel);
214   void unload();
215 };
216 
217 
218 ///
219 /// @brief Class representing a wheel of a vehicle
220 ///
221 struct PVehicleWheel {
222 
223 	// suspension position
224 	float ride_pos;
225 	// suspension position changing velocity
226 	float ride_vel;
227 	// driving axis rotation
228 	float spin_pos, spin_vel;
229 	// steering axis rotation
230 	float turn_pos;
231 
232 	// his reference position in the world
233 	PReferenceFrame ref_world;
234 
235 	// the reference position in the world of the lowest point of the wheel (the one touching the ground)
236 	PReferenceFrame ref_world_lowest_point;
237 
238 	float skidding, dirtthrow;
239 	// where the dust trail starts and its velocity
240 	vec3f dirtthrowpos, dirtthrowvec;
241 
242     // bump travel is the current velocity from bumplast to bumpnext
243 	float bumplast, bumpnext, bumptravel;
244 
245 	PVehicleWheel();
246 
247 	// reset wheel to default
248 	void reset();
249 
250 	// get the lowest point of the wheel (the one that will touch the ground)
251 	vec3f getLowestPoint();
252 };
253 
254 ///
255 /// @brief a vehicle point part, can have wheels attached
256 ///
257 struct PVehiclePart {
258 
259   // ref_local is initted from vehicle type, but may change per-vehicle
260 
261   // reference points in the local and world system
262   PReferenceFrame ref_local, ref_world;
263 
264   std::vector<PVehicleWheel> wheel;
265 };
266 
267 ///
268 /// @brief store a vehicle instance
269 ///
270 class PVehicle {
271 
272 public:
273   // physic simulation information
274   PSim &sim;
275 
276   // the type of Vehicle and of his part
277   PVehicleType *type;
278 
279   // the reference rigid body of the vehicle
280   // contains datas such as position, orientation, velocity, mass ...
281   PRigidBody *body;
282 
283   // the part which compose the vehicle
284   std::vector<PVehiclePart> part;
285 
286   // current control state (eg. brakes, turn)
287   v_state_s state;
288 
289   // engine instance
290   PEngineInstance iengine;
291 
292   // helicopter-specific
293   float blade_ang1;
294 
295   // next checkpoint
296   int nextcp;
297   // next codriver checkpoint
298   int nextcdcp;
299   // current lap, counted from 1
300   int currentlap;
301 
302   // for vehicle resetting, after being flipped
303   float reset_trigger_time;
304   vec3f reset_pos;
305   quatf reset_ori;
306   float reset_time;
307 
308   // for body crash/impact noises
309   float crunch_level, crunch_level_prev;
310 
311   // current controls situation (eg. brakes, turn)
312   v_control_s ctrl;
313 
314   float forwardspeed;
315   float wheel_angvel;
316   float wheel_speed;
317 
318   // how much noise for the drifting of the wheels. 0 means none
319   float skid_level;
320 
321   // when a vehicle starts going offroad this time is set (to know how much time has spent offroad)
322   float offroadtime_begin;
323   // when a vehicle stops going offroad this time is set (to know how much time has spent offroad)
324   float offroadtime_end;
325   // total time offroad
326   float offroadtime_total;
327 
328   PVehicle(PSim &sim_parent, PVehicleType *_type);
329   //~PVehicle() { unload(); } // body unloaded by sim
330 
331 public:
getBody()332   PRigidBody &getBody() { return *body; }
333 
334   /*
335   // NetObject stuff
336   void performScopeQuery(GhostConnection *connection);
337   U32 packUpdate(GhostConnection *connection, U32 updateMask, BitStream *stream);
338   void unpackUpdate(GhostConnection *connection, BitStream *stream);
339   */
340 
341   // simulate for 'delta' seconds
342   void tick(const float& delta);
343 
344   // check if a wheel touches the ground so that can have a dust trail
345   bool canHaveDustTrail();
346 
347   // update world reference of parts and wheels
348   void updateParts();
349 
350   // reset the car in place
351   void doReset();
352   // reset the car to a custom position and orientation
353   void doReset(const vec3f &pos, const quatf &ori);
354 
getEngineRPM()355   float getEngineRPM() { return iengine.getEngineRPM(); }
getCurrentGear()356   int getCurrentGear() { return iengine.getCurrentGear(); }
getFlagGearChange()357   bool getFlagGearChange() { return iengine.getFlagGearChange(); }
getCrashNoiseLevel()358   float getCrashNoiseLevel() {
359     if (crunch_level > crunch_level_prev) {
360       float tmp = crunch_level - crunch_level_prev;
361       crunch_level_prev = crunch_level;
362       return tmp;
363     } else {
364       return 0.0f;
365     }
366   }
getWheelSpeed()367   float getWheelSpeed() { return wheel_speed; }
getSkidLevel()368   float getSkidLevel() { return skid_level; }
369 
370 private:
371 	// subroutines that reset and stops status of the car
372 	// it's more low level that the doReset() one
373 	void reset();
374 };
375