mirror of https://github.com/GTAmodding/re3.git
Fix all(?) vehicle handling problems at high FPS. Refactor FIX_BUGS in ProcessWheel() to be much simpler.
This commit is contained in:
parent
879280bcf7
commit
ba832f93e8
|
@ -590,7 +590,12 @@ CPhysical::ApplyAirResistance(void)
|
|||
}else if(GetStatus() != STATUS_GHOST){
|
||||
float f = Pow(1.0f/Abs(1.0f + m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr()), CTimer::GetTimeStep());
|
||||
m_vecMoveSpeed *= f;
|
||||
#ifdef FIX_BUGS
|
||||
// Fix too much friction at high FPS (evil cause of bad vehicle handling, rear tires unable to lose traction, etc!)
|
||||
m_vecTurnSpeed *= Pow(0.99f, CTimer::GetTimeStepFix());
|
||||
#else
|
||||
m_vecTurnSpeed *= 0.99f;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1071,6 +1076,10 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
|
|||
if(fOtherSpeedA > speedSum){
|
||||
impulseA = (speedSum - fOtherSpeedA) * A->m_fMass;
|
||||
impulseB = (speedSum - fOtherSpeedB) * B->m_fMass;
|
||||
#ifdef FIX_BUGS
|
||||
impulseA *= CTimer::GetTimeStepFix();
|
||||
impulseB *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
impulseLimit = adhesiveLimit*CTimer::GetTimeStep();
|
||||
if(impulseA < -impulseLimit) impulseA = -impulseLimit;
|
||||
#ifdef FIX_BUGS
|
||||
|
@ -1107,6 +1116,10 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
|
|||
if(fOtherSpeedA > speedSum){
|
||||
impulseA = (speedSum - fOtherSpeedA) * A->m_fMass;
|
||||
impulseB = (speedSum - fOtherSpeedB) * massB;
|
||||
#ifdef FIX_BUGS
|
||||
impulseA *= CTimer::GetTimeStepFix();
|
||||
impulseB *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
impulseLimit = adhesiveLimit*CTimer::GetTimeStep();
|
||||
if(impulseA < -impulseLimit) impulseA = -impulseLimit;
|
||||
if(impulseB > impulseLimit) impulseB = impulseLimit;
|
||||
|
@ -1140,6 +1153,10 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
|
|||
if(fOtherSpeedA > speedSum){
|
||||
impulseA = (speedSum - fOtherSpeedA) * massA;
|
||||
impulseB = (speedSum - fOtherSpeedB) * B->m_fMass;
|
||||
#ifdef FIX_BUGS
|
||||
impulseA *= CTimer::GetTimeStepFix();
|
||||
impulseB *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
impulseLimit = adhesiveLimit*CTimer::GetTimeStep();
|
||||
if(impulseA < -impulseLimit) impulseA = -impulseLimit;
|
||||
if(impulseB > impulseLimit) impulseB = impulseLimit;
|
||||
|
@ -1174,6 +1191,10 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
|
|||
if(fOtherSpeedA > speedSum){
|
||||
impulseA = (speedSum - fOtherSpeedA) * massA;
|
||||
impulseB = (speedSum - fOtherSpeedB) * massB;
|
||||
#ifdef FIX_BUGS
|
||||
impulseA *= CTimer::GetTimeStepFix();
|
||||
impulseB *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
impulseLimit = adhesiveLimit*CTimer::GetTimeStep();
|
||||
if(impulseA < -impulseLimit) impulseA = -impulseLimit;
|
||||
if(impulseB > impulseLimit) impulseB = impulseLimit;
|
||||
|
@ -1214,6 +1235,9 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
|
|||
// not really impulse but speed
|
||||
// maybe use ApplyFrictionMoveForce instead?
|
||||
fImpulse = -fOtherSpeed;
|
||||
#ifdef FIX_BUGS
|
||||
fImpulse *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
impulseLimit = adhesiveLimit*CTimer::GetTimeStep() / m_fMass;
|
||||
if(fImpulse < -impulseLimit) fImpulse = -impulseLimit;
|
||||
CVector vImpulse = frictionDir*fImpulse;
|
||||
|
@ -1235,6 +1259,9 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
|
|||
frictionDir = vOtherSpeed * (1.0f/fOtherSpeed);
|
||||
#endif
|
||||
fImpulse = -fOtherSpeed * m_fMass;
|
||||
#ifdef FIX_BUGS
|
||||
fImpulse *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
impulseLimit = adhesiveLimit*CTimer::GetTimeStep() * 1.5;
|
||||
if(fImpulse < -impulseLimit) fImpulse = -impulseLimit;
|
||||
ApplyFrictionMoveForce(frictionDir*fImpulse);
|
||||
|
|
|
@ -857,8 +857,12 @@ CAutomobile::ProcessControl(void)
|
|||
(m_aSuspensionSpringRatio[1] < 1.0f || m_aSuspensionSpringRatio[3] < 1.0f))
|
||||
ApplyTurnForce(-GRAVITY*Min(m_fTurnMass, 2500.0f)*GetUp(), -1.0f*GetForward());
|
||||
}
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
// Keep brake non-timestepped (so the later ProcessWheel() takes only non-timestepped inputs)
|
||||
brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetDefaultTimeStep();
|
||||
#else
|
||||
brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();
|
||||
#endif
|
||||
bool neutralHandling = GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && (pHandling->Flags & HANDLING_NEUTRALHANDLING);
|
||||
float brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias;
|
||||
float brakeBiasRear = neutralHandling ? 1.0f : 2.0f-pHandling->fBrakeBias; // looks like a bug, but it was correct in III...
|
||||
|
@ -1058,12 +1062,7 @@ CAutomobile::ProcessControl(void)
|
|||
float rearBrake = brake;
|
||||
float rearTraction = traction;
|
||||
if(bIsHandbrakeOn){
|
||||
#ifdef FIX_BUGS
|
||||
// Not sure if this is needed, but brake usually has timestep as a factor
|
||||
rearBrake = 20000.0f * CTimer::GetTimeStepFix();
|
||||
#else
|
||||
rearBrake = 20000.0f;
|
||||
#endif
|
||||
if(fwdSpeed > 0.1f && pHandling->Flags & HANDLING_HANDBRAKE_TYRE){
|
||||
m_fTireTemperature += 0.005*CTimer::GetTimeStep();
|
||||
if(m_fTireTemperature > 2.0f)
|
||||
|
@ -1072,8 +1071,11 @@ CAutomobile::ProcessControl(void)
|
|||
}else if(m_doingBurnout && mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)){
|
||||
rearBrake = 0.0f;
|
||||
rearTraction = 0.0f;
|
||||
// BUG: missing timestep
|
||||
#ifdef FIX_BUGS
|
||||
ApplyTurnForce(contactPoints[CARWHEEL_REAR_LEFT], -0.001f*m_fTurnMass*m_fSteerAngle*GetRight()*CTimer::GetTimeStepFix());
|
||||
#else
|
||||
ApplyTurnForce(contactPoints[CARWHEEL_REAR_LEFT], -0.001f*m_fTurnMass*m_fSteerAngle*GetRight());
|
||||
#endif
|
||||
}else if(m_fTireTemperature > 1.0f){
|
||||
rearTraction *= m_fTireTemperature;
|
||||
}
|
||||
|
|
|
@ -125,7 +125,12 @@ cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, fl
|
|||
float targetVelocity = Gears[gear].fMaxVelocity*speedMul*fCheat;
|
||||
float accel = (targetVelocity - fVelocity) * (fEngineAcceleration*accelMul) / Abs(targetVelocity);
|
||||
if(Abs(fVelocity) < Abs(Gears[gear].fMaxVelocity*fCheat))
|
||||
#ifdef FIX_BUGS
|
||||
// The acceleration provided by a transmission+engine should not depend on framelength.
|
||||
fAcceleration = gasPedal * accel;
|
||||
#else
|
||||
fAcceleration = gasPedal * accel * CTimer::GetTimeStep();
|
||||
#endif
|
||||
else
|
||||
fAcceleration = 0.0f;
|
||||
return fAcceleration;
|
||||
|
|
|
@ -788,7 +788,14 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
|
|||
bAlreadySkidding = false;
|
||||
#endif
|
||||
|
||||
// how much force we want to apply in these axes
|
||||
// Velocity impulses fwd and right. Units are like meters per second.
|
||||
// This function was written assuming a fixed FPS, so a correction is made
|
||||
// right at the end before actually applying these impulses.
|
||||
//
|
||||
// Note that many functions in this engine deal with "force impulses" rather
|
||||
// than "velocity impulses". They are directly related: F=ma. It is
|
||||
// possible that the original devs actually used force impulses here but
|
||||
// an optimising compiler re-arranged their maths.
|
||||
float fwd = 0.0f;
|
||||
float right = 0.0f;
|
||||
|
||||
|
@ -804,7 +811,12 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
|
|||
bAlreadySkidding = true;
|
||||
*wheelState = WHEEL_STATE_NORMAL;
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
// Everything else here is timestep independent, let's stay with this theme to keep the rest of the FPS bugfixes simpler.
|
||||
adhesion *= CTimer::GetDefaultTimeStep();
|
||||
#else
|
||||
adhesion *= CTimer::GetTimeStep();
|
||||
#endif
|
||||
if(bAlreadySkidding)
|
||||
adhesion *= pHandling->fTractionLoss;
|
||||
|
||||
|
@ -812,28 +824,17 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
|
|||
if(contactSpeedRight != 0.0f){
|
||||
// exert opposing force
|
||||
right = -contactSpeedRight/wheelsOnGround;
|
||||
// BUG?
|
||||
// contactSpeedRight is independent of framerate but right has timestep as a factor
|
||||
// so we probably have to fix this
|
||||
// fixing this causes jittery cars at 15fps, and causes the car to move backwards slowly at 18fps
|
||||
// at 19fps, the effects are gone ...
|
||||
//right *= CTimer::GetTimeStepFix();
|
||||
|
||||
if(wheelStatus == WHEEL_STATUS_BURST){
|
||||
float fwdspeed = Min(contactSpeedFwd, fBurstSpeedMax);
|
||||
#ifdef FIX_BUGS
|
||||
// Keep the effect running at the same frequency even when the game is at high FPS
|
||||
right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstTyreMod, fBurstTyreMod) * CTimer::GetLogicalFramesPassed();
|
||||
#else
|
||||
right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstTyreMod, fBurstTyreMod);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(bDriving){
|
||||
fwd = thrust;
|
||||
|
||||
// limit sideways force (why?)
|
||||
// Limit sideways forces applied by the tires to the max the tires can possibly do.
|
||||
if(right > 0.0f){
|
||||
if(right > adhesion)
|
||||
right = adhesion;
|
||||
|
@ -843,11 +844,6 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
|
|||
}
|
||||
}else if(contactSpeedFwd != 0.0f){
|
||||
fwd = -contactSpeedFwd/wheelsOnGround;
|
||||
#ifdef FIX_BUGS
|
||||
// contactSpeedFwd is independent of framerate but fwd has timestep as a factor
|
||||
// so we probably have to fix this
|
||||
fwd *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
|
||||
if(!bBraking){
|
||||
if(m_fGasPedal < 0.01f){
|
||||
|
@ -859,9 +855,6 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
|
|||
brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;
|
||||
else
|
||||
brake = mod_HandlingManager.fWheelFriction / pHandling->fMass;
|
||||
#ifdef FIX_BUGS
|
||||
brake *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -888,10 +881,10 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
|
|||
*wheelState = WHEEL_STATE_SKIDDING;
|
||||
}
|
||||
|
||||
float l = Sqrt(speedSq);
|
||||
float speed = Sqrt(speedSq);
|
||||
float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss;
|
||||
right *= adhesion * tractionLoss / l;
|
||||
fwd *= adhesion * tractionLoss / l;
|
||||
right *= adhesion * tractionLoss / speed;
|
||||
fwd *= adhesion * tractionLoss / speed;
|
||||
}
|
||||
|
||||
if(fwd != 0.0f || right != 0.0f){
|
||||
|
@ -923,9 +916,19 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
|
|||
else
|
||||
turnDirection = direction;
|
||||
|
||||
|
||||
// Curious: there is a perfectly good ApplyMoveSpeed() function that
|
||||
// takes "velocity impulses", but instead we use the ApplyMoveForce()
|
||||
// function which takes a "force impulse" instead and then fix up the
|
||||
// difference by multiplying in the vehicle mass (F=ma). Possibly
|
||||
// evidence that an optimising compiler re-arranged the arithmetic?
|
||||
float impulse = speed*m_fMass;
|
||||
float turnImpulse = turnSpeed*GetMass(wheelContactPoint, turnDirection);
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
impulse = impulse * CTimer::GetTimeStepFix();
|
||||
turnImpulse = turnImpulse * CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
ApplyMoveForce(impulse * direction);
|
||||
ApplyTurnForce(turnImpulse * turnDirection, wheelContactPoint);
|
||||
}
|
||||
|
@ -949,7 +952,14 @@ CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &whee
|
|||
bAlreadySkidding = false;
|
||||
#endif
|
||||
|
||||
// how much force we want to apply in these axes
|
||||
// Velocity impulses fwd and right. Units are like meters per second.
|
||||
// This function was written assuming a fixed FPS, so a correction is made
|
||||
// right at the end before actually applying these impulses.
|
||||
//
|
||||
// Note that many functions in this engine deal with "force impulses" rather
|
||||
// than "velocity impulses". They are directly related: F=ma. It is
|
||||
// possible that the original devs actually used force impulses here but
|
||||
// an optimising compiler re-arranged their maths.
|
||||
float fwd = 0.0f;
|
||||
float right = 0.0f;
|
||||
|
||||
|
@ -966,7 +976,12 @@ CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &whee
|
|||
bAlreadySkidding = true;
|
||||
*wheelState = WHEEL_STATE_NORMAL;
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
// Everything else here is timestep independent, let's stay with this theme to keep the rest of the FPS bugfixes simpler.
|
||||
adhesion *= CTimer::GetDefaultTimeStep();
|
||||
#else
|
||||
adhesion *= CTimer::GetTimeStep();
|
||||
#endif
|
||||
if(bAlreadySkidding)
|
||||
adhesion *= pHandling->fTractionLoss;
|
||||
|
||||
|
@ -979,20 +994,10 @@ CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &whee
|
|||
if(contactSpeedRight != 0.0f){
|
||||
// exert opposing force
|
||||
right = -contactSpeedRight/wheelsOnGround;
|
||||
#ifdef FIX_BUGS
|
||||
// contactSpeedRight is independent of framerate but right has timestep as a factor
|
||||
// so we probably have to fix this
|
||||
right *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
|
||||
if(wheelStatus == WHEEL_STATUS_BURST){
|
||||
float fwdspeed = Min(contactSpeedFwd, fBurstBikeSpeedMax);
|
||||
#ifdef FIX_BUGS
|
||||
// Keep the effect running at the same frequency even when the game is at high FPS
|
||||
right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstBikeTyreMod, fBurstBikeTyreMod) * CTimer::GetLogicalFramesPassed();
|
||||
#else
|
||||
right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstBikeTyreMod, fBurstBikeTyreMod);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1009,12 +1014,6 @@ CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &whee
|
|||
}
|
||||
}else if(contactSpeedFwd != 0.0f){
|
||||
fwd = -contactSpeedFwd/wheelsOnGround;
|
||||
#ifdef FIX_BUGS
|
||||
// contactSpeedFwd is independent of framerate but fwd has timestep as a factor
|
||||
// so we probably have to fix this
|
||||
fwd *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
|
||||
if(!bBraking){
|
||||
if(m_fGasPedal < 0.01f){
|
||||
if(IsBike())
|
||||
|
@ -1025,9 +1024,6 @@ CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &whee
|
|||
brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;
|
||||
else
|
||||
brake = mod_HandlingManager.fWheelFriction / m_fMass;
|
||||
#ifdef FIX_BUGS
|
||||
brake *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1078,6 +1074,10 @@ CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &whee
|
|||
|
||||
float impulse = speed*m_fMass;
|
||||
float turnImpulse = speed*GetMass(wheelContactPoint, direction);
|
||||
#ifdef FIX_BUGS
|
||||
impulse = impulse * CTimer::GetTimeStepFix();
|
||||
turnImpulse = turnImpulse * CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
CVector vTurnImpulse = turnImpulse * direction;
|
||||
ApplyMoveForce(impulse * direction);
|
||||
|
||||
|
|
Loading…
Reference in New Issue