diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 76df0fd87..8207488ac 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -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