mirror of https://github.com/GTAmodding/re3.git
Fix many boat performance issues at high FPS, but cornering/handling still not perfect.
This commit is contained in:
parent
e0dfa8b971
commit
6f8ba21552
|
@ -343,6 +343,7 @@ CBoat::ProcessControl(void)
|
|||
bIsDrowning = false;
|
||||
}
|
||||
|
||||
// Apply buoyancy impulse the first time (why twice?)
|
||||
m_fVolumeUnderWater = mod_Buoyancy.m_volumeUnderWater;
|
||||
m_vecBuoyancePoint = buoyancePoint;
|
||||
if(GetModelIndex() == MI_SKIMMER && GetUp().z < -0.5f && Abs(m_vecMoveSpeed.x) < 0.2f && Abs(m_vecMoveSpeed.y) < 0.2f)
|
||||
|
@ -352,13 +353,17 @@ CBoat::ProcessControl(void)
|
|||
if(bSeparateTurnForce)
|
||||
ApplyTurnForce(0.4f*buoyanceImpulse, buoyancePoint);
|
||||
|
||||
// TODO: what is this?
|
||||
if(GetModelIndex() == MI_SKIMMER)
|
||||
if(m_skimmerThingTimer != 0.0f ||
|
||||
GetForward().z < -0.5f && GetUp().z > -0.5f && m_vecMoveSpeed.z < -0.15f &&
|
||||
buoyanceImpulse.z > 0.01f*m_fMass * GRAVITY*CTimer::GetTimeStep() &&
|
||||
buoyanceImpulse.z < 0.4f*m_fMass * GRAVITY*CTimer::GetTimeStep()){
|
||||
#ifdef FIX_BUGS
|
||||
// buoyanceImpulse already has a factor of timestep in it
|
||||
float turnImpulse = -0.00017f*GetForward().z*buoyanceImpulse.z * m_fMass*CTimer::GetDefaultTimeStep();
|
||||
#else
|
||||
float turnImpulse = -0.00017f*GetForward().z*buoyanceImpulse.z * m_fMass*CTimer::GetTimeStep();
|
||||
#endif
|
||||
ApplyTurnForce(turnImpulse*GetForward(), GetUp());
|
||||
bBoatInWater = false;
|
||||
//BUG? aren't we forgetting the timestep here?
|
||||
|
@ -370,15 +375,21 @@ CBoat::ProcessControl(void)
|
|||
m_skimmerThingTimer = 0.0f;
|
||||
}
|
||||
|
||||
// Apply buoyancy impulse the second time (why twice?)
|
||||
if(!onLand && bBoatInWater && GetUp().z > 0.0f){
|
||||
#ifdef FIX_BUGS
|
||||
// buoyanceImpulse already has a factor of timestep in it
|
||||
float impulse = m_vecMoveSpeed.MagnitudeSqr()*pBoatHandling->fAqPlaneForce*buoyanceImpulse.z*CTimer::GetDefaultTimeStep()*0.5f;
|
||||
#else
|
||||
float impulse = m_vecMoveSpeed.MagnitudeSqr()*pBoatHandling->fAqPlaneForce*buoyanceImpulse.z*CTimer::GetTimeStep()*0.5f;
|
||||
#endif
|
||||
if(GetModelIndex() == MI_SKIMMER)
|
||||
impulse *= 1.0f + m_fGasPedal;
|
||||
else if(m_fGasPedal > 0.05f)
|
||||
impulse *= m_fGasPedal;
|
||||
else
|
||||
impulse = 0.0f;
|
||||
impulse = Min(impulse, GRAVITY*pBoatHandling->fAqPlaneLimit*m_fMass*CTimer::GetTimeStep());
|
||||
impulse = Min(impulse, GRAVITY*pBoatHandling->fAqPlaneLimit*m_fMass*CTimer::GetTimeStep()); // Both sides have a factor of TimeStep, therefore this Min() is not a problem at high FPS
|
||||
ApplyMoveForce(impulse*GetUp());
|
||||
ApplyTurnForce(impulse*GetUp(), buoyancePoint - pBoatHandling->fAqPlaneOffset*GetForward());
|
||||
}
|
||||
|
@ -491,7 +502,11 @@ CBoat::ProcessControl(void)
|
|||
CVector propellerForce = propellerDepth * Multiply3x3(GetMatrix(), force*CVector(-steerSin, 0.0f, 0.0f));
|
||||
ApplyMoveForce(propellerForce * CTimer::GetTimeStep());
|
||||
ApplyTurnForce(propellerForce * CTimer::GetTimeStep(), propeller);
|
||||
#ifdef FIX_BUGS
|
||||
float rightForce = -steerSin * force * 0.75f/steerFactor * CTimer::GetTimeStep();
|
||||
#else
|
||||
float rightForce = -steerSin * force * 0.75f/steerFactor * Max(CTimer::GetTimeStep(), 0.01f);
|
||||
#endif
|
||||
ApplyTurnForce(GetRight() * rightForce, GetUp());
|
||||
}
|
||||
}else
|
||||
|
@ -501,7 +516,12 @@ CBoat::ProcessControl(void)
|
|||
CVector right = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f));
|
||||
float rightSpeed = DotProduct(m_vecMoveSpeed, right);
|
||||
float impulse = 0.1f*pHandling->fSuspensionBias * m_fMass * m_fVolumeUnderWater * rightSpeed * CTimer::GetTimeStep();
|
||||
ApplyMoveForce(right - impulse * 0.3f * CVector(-right.y, right.x, 0.0f));
|
||||
#ifdef FIX_BUGS
|
||||
// Fix boat perf at high FPS: ensure both terms have a (correct) factor of timestep before doing subtraction
|
||||
ApplyMoveForce(right * CTimer::GetTimeStepFix() - impulse * 0.3f * CVector(-right.y, right.x, 0.0f));
|
||||
#else
|
||||
ApplyMoveForce(right - impulse * 0.3f * CVector(-right.y, right.x, 0.0f));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(GetStatus() == STATUS_PLAYER && CPad::GetPad(0)->GetHandBrake()){
|
||||
|
@ -519,25 +539,45 @@ CBoat::ProcessControl(void)
|
|||
m_vecMoveSpeed.y = Min(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MAX_Y-100.0f))*0.01f); // north
|
||||
m_vecMoveSpeed.y = Max(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MIN_Y+100.0f))*0.01f); // south
|
||||
|
||||
// Apply water resistance to linear movement
|
||||
if(!onLand && bBoatInWater && !bSeparateTurnForce)
|
||||
ApplyWaterResistance();
|
||||
|
||||
// Apply water resistance to rotation
|
||||
if((GetModelIndex() != MI_SKIMMER || m_skimmerThingTimer == 0.0f) && !bSeparateTurnForce){
|
||||
// No idea what exactly is going on here besides drag in YZ
|
||||
#ifdef FIX_BUGS
|
||||
// Rockstar's attempts to make this framerate independent are totally wrong.
|
||||
// Rules of thumb:
|
||||
// - use Pow(x,time) if you multiply the result into the velocity
|
||||
// - use x*time if you add the result into the velocity
|
||||
// We have to disable one of these Pow() methods and then add our own correction at the end.
|
||||
float fxfake = Pow(pBoatHandling->vecTurnRes.x, CTimer::GetDefaultTimeStep());
|
||||
float fy = Pow(pBoatHandling->vecTurnRes.y, CTimer::GetTimeStep());
|
||||
float fz = Pow(pBoatHandling->vecTurnRes.z, CTimer::GetTimeStep());
|
||||
m_vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); // invert - to local space
|
||||
float drag = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fxfake;
|
||||
m_vecTurnSpeed.y *= fy;
|
||||
m_vecTurnSpeed.z *= fz;
|
||||
float forceUp = -(1.0f - drag) * m_vecTurnSpeed.x * m_fTurnMass;
|
||||
m_vecTurnSpeed = Multiply3x3(GetMatrix(), m_vecTurnSpeed); // back to world
|
||||
CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass);
|
||||
ApplyTurnForce(forceUp*GetUp() * CTimer::GetTimeStepFix(), com + GetForward());
|
||||
#else
|
||||
float fx = Pow(pBoatHandling->vecTurnRes.x, CTimer::GetTimeStep());
|
||||
float fy = Pow(pBoatHandling->vecTurnRes.y, CTimer::GetTimeStep());
|
||||
float fz = Pow(pBoatHandling->vecTurnRes.z, CTimer::GetTimeStep());
|
||||
m_vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); // invert - to local space
|
||||
// TODO: figure this out
|
||||
float magic = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fx;
|
||||
float drag = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fx;
|
||||
m_vecTurnSpeed.y *= fy;
|
||||
m_vecTurnSpeed.z *= fz;
|
||||
float forceUp = (magic - 1.0f) * m_vecTurnSpeed.x * m_fTurnMass;
|
||||
float forceUp = (drag - 1.0f) * m_vecTurnSpeed.x * m_fTurnMass;
|
||||
m_vecTurnSpeed = Multiply3x3(GetMatrix(), m_vecTurnSpeed); // back to world
|
||||
CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass);
|
||||
ApplyTurnForce(forceUp*GetUp(), com + GetForward());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
m_nDeltaVolumeUnderWater = (m_fVolumeUnderWater-m_fPrevVolumeUnderWater)*10000;
|
||||
|
||||
// Falling into water
|
||||
|
@ -555,6 +595,9 @@ CBoat::ProcessControl(void)
|
|||
speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fBrakeBias;
|
||||
CVector speed = speedFwd*GetForward() + CVector(0.0f, 0.0f, speedUp);
|
||||
CVector splashImpulse = speed * m_fMass;
|
||||
#ifdef FIX_BUGS
|
||||
splashImpulse *= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
ApplyMoveForce(splashImpulse);
|
||||
ApplyTurnForce(splashImpulse, buoyancePoint);
|
||||
}
|
||||
|
@ -893,26 +936,29 @@ CBoat::ApplyWaterResistance(void)
|
|||
//
|
||||
// We don't actually have to limit ourselves to a fixed time unit (like 1ms chunks),
|
||||
// instead we can raise the resistance to some power of time using Pow().
|
||||
float rrx = Pow(rx, 0.5f*CTimer::GetTimeStep()); // Why 0.5f? Taste?
|
||||
float rry = Pow(ry, 0.5f*CTimer::GetTimeStep());
|
||||
float rrz = Pow(rz, 0.5f*CTimer::GetTimeStep());
|
||||
float rrx = Pow(rx, 0.5f*CTimer::GetTimeStep()); // Why 0.5f? Taste?
|
||||
float rry = Pow(ry, 0.5f*CTimer::GetTimeStep());
|
||||
float rrz = Pow(rz, 0.5f*CTimer::GetTimeStep());
|
||||
float rryfake = Pow(ry, 0.5f*CTimer::GetDefaultTimeStep()); // Fudge factor needed for other equations to make sense at high FPS
|
||||
|
||||
m_vecMoveSpeed = Multiply3x3(m_vecMoveSpeed, GetMatrix()); // convert velocities to boat-local space (y = boat forwards, x = sideways, z = up/down)
|
||||
m_vecMoveSpeed.x *= rrx;
|
||||
m_vecMoveSpeed.y *= rry;
|
||||
m_vecMoveSpeed.z *= rrz;
|
||||
float force = (rry - 1.0f) * m_vecMoveSpeed.y * m_fMass;
|
||||
float force = (rryfake - 1.0f) * m_vecMoveSpeed.y * m_fMass;
|
||||
m_vecMoveSpeed = Multiply3x3(GetMatrix(), m_vecMoveSpeed); // back to world space
|
||||
|
||||
// Is this for "flipping the boat over"? Seems to have almost zero effect normally?
|
||||
ApplyTurnForce(force*GetForward(), -GetUp());
|
||||
// WTH is this for?
|
||||
ApplyTurnForce(force*GetForward()*CTimer::GetTimeStepFix(), -GetUp());
|
||||
|
||||
// What the hell? Why arbitrarily compound in one more factor of rrz?
|
||||
// This is framerate dependent! Bah!
|
||||
// This is framerate dependent! Bah! I suspect it has very little effect.
|
||||
/*
|
||||
if(m_vecMoveSpeed.z > 0.0f)
|
||||
m_vecMoveSpeed.z *= rrz;
|
||||
else
|
||||
m_vecMoveSpeed.z *= (1.0f - rrz)*0.5f + rrz;
|
||||
*/
|
||||
#else
|
||||
// TODO: figure out how this works
|
||||
float resistance = 0.001f * pHandling->fSuspensionForceLevel * SQR(m_fVolumeUnderWater) * m_fMass;
|
||||
|
|
|
@ -109,6 +109,17 @@ cBuoyancy::ProcessBuoyancyBoat(CVehicle *veh, float buoyancy, CVector *point, CV
|
|||
float volume = SimpleSumBuoyancyData(waterLevel, waterPosition);
|
||||
float upImpulse = volume * volDiv * buoyancy * CTimer::GetTimeStep();
|
||||
CVector speed = veh->GetSpeed(Multiply3x3(veh->GetMatrix(), CVector(x, y, 0.0f)));
|
||||
#ifdef FIX_BUGS
|
||||
// "GetSpeed" seems to depend on framerate (bad).
|
||||
// This ruins boat performance at high FPS. Approximate sequence of events:
|
||||
// - "speed" goes tiny at high FPS
|
||||
// - "damp" goes high as a result
|
||||
// - high dampening reduces the buoyancy forces that keep the boat above the water
|
||||
// - boats sit _slightly_ lower in water (you have to disable ALL waves to see this, it's a very small change)
|
||||
// - all of boat handling performance changes because a different amount of the boat is underwater
|
||||
// Finding this was a PITA!
|
||||
speed /= CTimer::GetTimeStepFix();
|
||||
#endif
|
||||
float damp = 1.0f - DotProduct(speed, waterNormal)*veh->pHandling->fSuspensionDampingLevel;
|
||||
float finalImpulse = upImpulse*Max(damp, 0.0f);
|
||||
impulse->z += finalImpulse;
|
||||
|
|
Loading…
Reference in New Issue