void CARDYNAMICS::UpdateWheelTransform() { for(int i = 0; i < WHEEL_POSITION_SIZE; ++i) { wheel_position[i] = GetWheelPositionAtDisplacement(WHEEL_POSITION(i), suspension[i].GetDisplacementPercent()); wheel_orientation[i] = Orientation() * GetWheelSteeringAndSuspensionOrientation(WHEEL_POSITION(i)); } }
const BEZIER * GetCurrentPatch(const CAR *c) { const BEZIER *curr_patch = c->GetCurPatch(WHEEL_POSITION(0)); if (!curr_patch) { curr_patch = c->GetCurPatch(WHEEL_POSITION(1)); //let's try the other wheel if (!curr_patch) return NULL; } return curr_patch; }
void AI::calcMu(AI_Car *c) { int i; float long_friction = 0.0; float lat_friction = 0.0; for (i=0; i<4; i++) { long_friction += c->car->GetTireMaxFx(WHEEL_POSITION(i)); lat_friction += c->car->GetTireMaxFy(WHEEL_POSITION(i)); } float long_mu = FRICTION_FACTOR_LONG * long_friction * c->car->GetInvMass() / GRAVITY; float lat_mu = FRICTION_FACTOR_LAT * lat_friction * c->car->GetInvMass() / GRAVITY; if (!isnan(long_mu)) c->longitude_mu = long_mu; if (!isnan(lat_mu)) c->lateral_mu = lat_mu; }
float CAR::GetTireSquealAmount(WHEEL_POSITION i) const { const TRACKSURFACE & surface = dynamics.GetWheelContact(WHEEL_POSITION(i)).GetSurface(); if (surface.type == TRACKSURFACE::NONE) return 0; btQuaternion wheelspace = dynamics.GetUprightOrientation(WHEEL_POSITION(i)); btVector3 groundvel = quatRotate(wheelspace.inverse(), dynamics.GetWheelVelocity(WHEEL_POSITION(i))); float wheelspeed = dynamics.GetWheel(WHEEL_POSITION(i)).GetAngularVelocity() * dynamics.GetTire(WHEEL_POSITION(i)).GetRadius(); groundvel[0] -= wheelspeed; groundvel[1] *= 2.0; groundvel[2] = 0; float squeal = (groundvel.length() - 3.0) * 0.2; double slide = dynamics.GetTire(i).GetSlide() / dynamics.GetTire(i).GetIdealSlide(); double slip = dynamics.GetTire(i).GetSlip() / dynamics.GetTire(i).GetIdealSlip(); double maxratio = std::max(std::abs(slide), std::abs(slip)); float squealfactor = std::max(0.0, maxratio - 1.0); squeal *= squealfactor; if (squeal < 0) squeal = 0; if (squeal > 1) squeal = 1; return squeal; }
void CAR::UpdateSounds(float dt) { if (!psound) return; MATHVECTOR <float, 3> pos_car = GetPosition(); MATHVECTOR <float, 3> pos_eng = ToMathVector<float>(dynamics.GetEnginePosition()); psound->SetSourcePosition(roadnoise, pos_car[0], pos_car[1], pos_car[2]); psound->SetSourcePosition(crashsound, pos_car[0], pos_car[1], pos_car[2]); psound->SetSourcePosition(gearsound, pos_car[0], pos_car[1], pos_car[2]); psound->SetSourcePosition(brakesound, pos_car[0], pos_car[1], pos_car[2]); psound->SetSourcePosition(handbrakesound, pos_car[0], pos_car[1], pos_car[2]); // update engine sounds float rpm = GetEngineRPM(); float throttle = dynamics.GetEngine().GetThrottle(); float total_gain = 0.0; std::vector<std::pair<size_t, float> > gainlist; gainlist.reserve(enginesounds.size()); for (std::vector<ENGINESOUNDINFO>::iterator i = enginesounds.begin(); i != enginesounds.end(); ++i) { ENGINESOUNDINFO & info = *i; float gain = 1.0; if (rpm < info.minrpm) { gain = 0; } else if (rpm < info.fullgainrpmstart && info.fullgainrpmstart > info.minrpm) { gain *= (rpm - info.minrpm) / (info.fullgainrpmstart - info.minrpm); } if (rpm > info.maxrpm) { gain = 0; } else if (rpm > info.fullgainrpmend && info.fullgainrpmend < info.maxrpm) { gain *= 1.0 - (rpm - info.fullgainrpmend) / (info.maxrpm - info.fullgainrpmend); } if (info.power == ENGINESOUNDINFO::BOTH) { gain *= throttle * 0.5 + 0.5; } else if (info.power == ENGINESOUNDINFO::POWERON) { gain *= throttle; } else if (info.power == ENGINESOUNDINFO::POWEROFF) { gain *= (1.0-throttle); } total_gain += gain; gainlist.push_back(std::make_pair(info.sound_source, gain)); float pitch = rpm / info.naturalrpm; psound->SetSourcePosition(info.sound_source, pos_eng[0], pos_eng[1], pos_eng[2]); psound->SetSourcePitch(info.sound_source, pitch); } // normalize gains assert(total_gain >= 0.0); for (std::vector<std::pair<size_t, float> >::iterator i = gainlist.begin(); i != gainlist.end(); ++i) { float gain; if (total_gain == 0.0) { gain = 0.0; } else if (enginesounds.size() == 1 && enginesounds.back().power == ENGINESOUNDINFO::BOTH) { gain = i->second; } else { gain = i->second / total_gain; } psound->SetSourceGain(i->first, gain); } // update tire squeal sounds for (int i = 0; i < 4; i++) { // make sure we don't get overlap psound->SetSourceGain(gravelsound[i], 0.0); psound->SetSourceGain(grasssound[i], 0.0); psound->SetSourceGain(tiresqueal[i], 0.0); float squeal = GetTireSquealAmount(WHEEL_POSITION(i)); float maxgain = 0.3; float pitchvariation = 0.4; size_t * sound_active; const TRACKSURFACE & surface = dynamics.GetWheelContact(WHEEL_POSITION(i)).GetSurface(); if (surface.type == TRACKSURFACE::ASPHALT) { sound_active = tiresqueal; } else if (surface.type == TRACKSURFACE::GRASS) { sound_active = grasssound; maxgain = 0.4; // up the grass sound volume a little } else if (surface.type == TRACKSURFACE::GRAVEL) { sound_active = gravelsound; maxgain = 0.4; } else if (surface.type == TRACKSURFACE::CONCRETE) { sound_active = tiresqueal; maxgain = 0.3; pitchvariation = 0.25; } else if (surface.type == TRACKSURFACE::SAND) { sound_active = grasssound; maxgain = 0.25; // quieter for sand pitchvariation = 0.25; } else { sound_active = tiresqueal; maxgain = 0.0; } btVector3 pos_wheel = dynamics.GetWheelPosition(WHEEL_POSITION(i)); btVector3 vel_wheel = dynamics.GetWheelVelocity(WHEEL_POSITION(i)); float pitch = (vel_wheel.length() - 5.0) * 0.1; if (pitch < 0) pitch = 0; if (pitch > 1) pitch = 1; pitch = 1.0 - pitch; pitch *= pitchvariation; pitch = pitch + (1.0 - pitchvariation); if (pitch < 0.1) pitch = 0.1; if (pitch > 4.0) pitch = 4.0; psound->SetSourcePosition(sound_active[i], pos_wheel[0], pos_wheel[1], pos_wheel[2]); psound->SetSourcePitch(sound_active[i], pitch); psound->SetSourceGain(sound_active[i], squeal * maxgain); } //update road noise sound { float gain = dynamics.GetVelocity().length(); if (gain < 0) gain = -gain; gain *= 0.02; gain *= gain; if (gain > 1.0) gain = 1.0; psound->SetSourceGain(roadnoise, gain); } /* //update bump noise sound { for (int i = 0; i < 4; i++) { suspensionbumpdetection[i].Update( dynamics.GetSuspension(WHEEL_POSITION(i)).GetVelocity(), dynamics.GetSuspension(WHEEL_POSITION(i)).GetDisplacementFraction(), dt); if (suspensionbumpdetection[i].JustSettled()) { float bumpsize = suspensionbumpdetection[i].GetTotalBumpSize(); const float breakevenms = 5.0; float gain = bumpsize * GetSpeed() / breakevenms; if (gain > 1) gain = 1; if (gain < 0) gain = 0; if (gain > 0 && !tirebump[i].Audible()) { tirebump[i].SetGain(gain); tirebump[i].Stop(); tirebump[i].Play(); } } } } //update crash sound { crashdetection.Update(GetSpeed(), dt); float crashdecel = crashdetection.GetMaxDecel(); if (crashdecel > 0) { const float mingainat = 500; const float maxgainat = 3000; const float mingain = 0.1; float gain = (crashdecel-mingainat)/(maxgainat-mingainat); if (gain > 1) gain = 1; if (gain < mingain) gain = mingain; if (!crashsound.Audible()) { crashsound.SetGain(gain); crashsound.Stop(); crashsound.Play(); } } } */ // update gear sound if (driver_view && gearsound_check != GetGear()) { float gain = 0.0; if (GetEngineRPM() != 0.0) gain = GetEngineRPMLimit() / GetEngineRPM(); if (gain > 0.5) gain = 0.5; if (gain < 0.25) gain = 0.25; if (!psound->GetSourcePlaying(gearsound)) { psound->ResetSource(gearsound); psound->SetSourceGain(gearsound, gain); } gearsound_check = GetGear(); } }
void PERFORMANCE_TESTING::TestStoppingDistance(bool abs, std::ostream & info_output, std::ostream & error_output) { info_output << "Testing stopping distance" << std::endl; ResetCar(); car.dynamics.SetABS(abs); double maxtime = 300.0; double t = 0.; double dt = .004; int i = 0; std::vector <float> inputs(CARINPUT::INVALID, 0.0); inputs[CARINPUT::THROTTLE] = 1.0; float stopthreshold = 0.1; //if the speed (in m/s) is less than this value, discontinue the testing btVector3 stopstart; //where the stopping starts float brakestartspeed = 26.82; //speed at which to start braking, in m/s (26.82 m/s is 60 mph) bool accelerating = true; //switches to false once 60 mph is reached while (t < maxtime) { if (accelerating) { inputs[CARINPUT::THROTTLE] = 1.0; inputs[CARINPUT::BRAKE] = 0.0; } else { inputs[CARINPUT::THROTTLE] = 0.0; inputs[CARINPUT::BRAKE] = 1.0; inputs[CARINPUT::NEUTRAL] = 1.0; } car.HandleInputs(inputs); world.update(dt); if (car.dynamics.GetSpeed() >= brakestartspeed && accelerating) //stop accelerating and hit the brakes { accelerating = false; stopstart = car.dynamics.GetWheelPosition(WHEEL_POSITION(0)); //std::cout << "hitting the brakes at " << t << ", " << car.dynamics.GetSpeed() << std::endl; } if (!accelerating && car.dynamics.GetSpeed() < stopthreshold) { break; } if (car.GetEngineRPM() < 1) { error_output << "Car stalled during launch, t=" << t << std::endl; break; } if (i % (int)(1.0/dt) == 0) //every second { //std::cout << t << ", " << car.dynamics.GetSpeed() << ", " << car.GetGear() << ", " << car.GetEngineRPM() << std::endl; } t += dt; i++; } btVector3 stopend = car.dynamics.GetWheelPosition(WHEEL_POSITION(0)); info_output << "60-0 stopping distance "; if (abs) info_output << "(ABS)"; else info_output << "(no ABS)"; info_output << ": " << ConvertToFeet((stopend-stopstart).length()) << " ft" << std::endl; }