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 ∼ 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