From 3da2c07d62731e891ea70d0705cd985185a3b04d Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 29 Mar 2017 08:32:50 +1100 Subject: [PATCH] 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. --- src/karts/kart.cpp | 62 ++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 27 deletions(-) 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