Enable friction to be changed per wheel: previously sliding was only

enabled once the whole kart chassis was tilted enough, but karts could
still end up driving on a wall (one wheel on a wall would not tilt the
chassis enough to trigger sliding, but give the kart an up velocity
which allowed it to drive on the wall). Friction is now determined
by the normal of the triangle hit by the raycast.
This commit is contained in:
hiker 2017-03-29 08:32:50 +11:00
parent 9fdd39b075
commit 3da2c07d62

View File

@ -2463,31 +2463,44 @@ void Kart::updateEnginePowerAndBrakes(float dt)
// ----------------------------------------------------------------------------
/** Handles sliding, i.e. the kart sliding off terrain that is too steep.
* Dynamically determine friction so that the kart looses its traction
* when trying to drive on too steep surfaces. Below angles of 0.25 rad,
* you have full traction; above 0.5 rad angles you have absolutely none;
* inbetween there is a linear change in friction. This is done for each
* wheel individually (since otherwise karts were still able with enough
* speed to drive on walls - one wheel 'on a wall' would not tilt the
* kart chassis enough to trigger sliding, but since that wheel had still
* full friction, give the kart an upwards velocity).
*/
void Kart::updateSliding()
{
// dynamically determine friction so that the kart looses its traction
// when trying to drive on too steep surfaces. Below angles of 0.25 rad,
// you have full traction; above 0.5 rad angles you have absolutely none;
// inbetween there is a linear change in friction
float friction = 1.0f;
bool enable_sliding = false;
// This way the current handling of sliding can be disabled
// for certain material (e.g. the curve in skyline on which otherwise
// karts could not drive).
// We also had a crash reported here, which was caused by not
// having a material here - no idea how this could have happened,
// but this problem is now avoided by testing if there is a material
if (isOnGround() &&
(!getMaterial() || !getMaterial()->highTireAdhesion()))
// Allow the sliding to be disabled per material (for so called
// high adhesion material), which is useful for e.g. banked curves.
// We don't have per-wheel material, so the test for special material
// with high adhesion is done per kart (not per wheel).
const Material * material = getMaterial();
if (material && material->highTireAdhesion())
{
const btMatrix3x3 &m = m_vehicle->getChassisWorldTransform().getBasis();
// To get the angle between up=(0,1,0), we have to do:
// m*(0,1,0) to get the up vector of the kart, then the
// scalar product between this and (0,1,0) - which is m[1][1]:
float distanceFromUp = m[1][1];
for (int i = 0; i < m_vehicle->getNumWheels(); i++)
{
btWheelInfo &wheel = m_vehicle->getWheelInfo(i);
wheel.m_frictionSlip = m_kart_properties->getFrictionSlip();
}
m_vehicle->setSliding(false);
return;
}
// Now test for each wheel if it should be sliding
// -----------------------------------------------
bool enable_sliding = false;
for (int i = 0; i < m_vehicle->getNumWheels(); i++)
{
const btWheelInfo &wheel = m_vehicle->getWheelInfo(i);
if (!wheel.m_raycastInfo.m_isInContact) continue;
const btVector3 &norm = m_vehicle->getWheelInfo(i).m_raycastInfo.m_contactNormalWS;
float distanceFromUp = norm.dot(getNormal());
float friction;
if (distanceFromUp < 0.85f)
{
friction = 0.0f;
@ -2502,13 +2515,8 @@ void Kart::updateSliding()
friction = (distanceFromUp - 0.85f) / 0.5f;
enable_sliding = true;
}
}
for (unsigned int i=0; i<4; i++)
{
btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
wheel.m_frictionSlip = friction*m_kart_properties->getFrictionSlip();
}
m_vehicle->getWheelInfo(i).m_frictionSlip = friction * m_kart_properties->getFrictionSlip();
} // for i < numWheels
m_vehicle->setSliding(enable_sliding);
} // updateSliding