Different implementation of soft-landing.

This commit is contained in:
hiker 2014-09-30 23:13:48 +10:00
parent 26e92846de
commit 11916dd187
2 changed files with 32 additions and 36 deletions

View File

@ -77,6 +77,8 @@ struct btWheelInfo
bool m_bIsFrontWheel; bool m_bIsFrontWheel;
bool m_was_on_ground;
void* m_clientInfo;//can be used to store pointer to sync transforms... void* m_clientInfo;//can be used to store pointer to sync transforms...
btWheelInfo(btWheelInfoConstructionInfo& ci) btWheelInfo(btWheelInfoConstructionInfo& ci)
@ -102,7 +104,7 @@ struct btWheelInfo
m_rollInfluence = btScalar(0.1); m_rollInfluence = btScalar(0.1);
m_bIsFrontWheel = ci.m_bIsFrontWheel; m_bIsFrontWheel = ci.m_bIsFrontWheel;
m_maxSuspensionForce = ci.m_maxSuspensionForce; m_maxSuspensionForce = ci.m_maxSuspensionForce;
m_was_on_ground = true;
} }
void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo); void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo);

View File

@ -260,18 +260,15 @@ btScalar btKart::rayCast(unsigned int index)
depth = raylen * rayResults.m_distFraction; depth = raylen * rayResults.m_distFraction;
if (object && depth < max_susp_len) if (object && depth < max_susp_len)
{ {
param = rayResults.m_distFraction;
wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
wheel.m_raycastInfo.m_contactNormalWS.normalize(); wheel.m_raycastInfo.m_contactNormalWS.normalize();
wheel.m_raycastInfo.m_isInContact = true; wheel.m_raycastInfo.m_isInContact = true;
///@todo for driving on dynamic/movable objects!; ///@todo for driving on dynamic/movable objects!;
wheel.m_raycastInfo.m_groundObject = &getFixedBody(); wheel.m_raycastInfo.m_groundObject = &getFixedBody();
btScalar hitDistance = param*raylen; wheel.m_raycastInfo.m_suspensionLength = depth - wheel.m_wheelsRadius;
wheel.m_raycastInfo.m_suspensionLength =
hitDistance - wheel.m_wheelsRadius;
//clamp on max suspension travel
//clamp on max suspension travel
btScalar minSuspensionLength = wheel.getSuspensionRestLength() btScalar minSuspensionLength = wheel.getSuspensionRestLength()
- wheel.m_maxSuspensionTravelCm*btScalar(0.01); - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
btScalar maxSuspensionLength = wheel.getSuspensionRestLength() btScalar maxSuspensionLength = wheel.getSuspensionRestLength()
@ -314,35 +311,6 @@ btScalar btKart::rayCast(unsigned int index)
} else } else
{ {
// The raycast either hit nothing (object=NULL), or it hit something,
// but not in the maximum suspension range. If it hit something,
// check for the need of cushioning:
if(object)
{
// If the raycast hit something, see if the jump needs cushioning:
// i.e. a slowdown in fall speed in order to avoid that on landing
// the chassis hits the ground (causing a severe slowdown of the
// kart). The cushioning is done if the fall distance (v_down * dt)
// in this physics step is large enough that the kart would hit the
// ground, i.e. the maximum suspension length plus fall distance
// is larger than the distance to the object that was just detected.
// To allow for wall driving, properly project the velocity
// onto the normal
btVector3 v = m_chassisBody->getLinearVelocity();
btVector3 down(0, 1, 0);
btVector3 v_down = (v * down) * down;
if(depth < max_susp_len + v_down.length() *1./60.f)
{
// Apply an impulse that will roughly half the speed. Since
// there are 4 wheels, a single wheel should apply 1/4 of
// the necessary impulse:
btVector3 impulse = (-0.25f*0.5f/m_chassisBody->getInvMass())
* v_down;
m_chassisBody->applyCentralImpulse(impulse);
}
}
depth = btScalar(-1.0); depth = btScalar(-1.0);
//put wheel info as in rest position //put wheel info as in rest position
wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
@ -422,6 +390,32 @@ void btKart::updateVehicle( btScalar step )
m_num_wheels_on_ground++; m_num_wheels_on_ground++;
} }
bool needs_cushioning_test = false;
for(int i=0; i<m_wheelInfo.size(); i++)
{
btWheelInfo &wheel = m_wheelInfo[i];
if(!wheel.m_was_on_ground && wheel.m_raycastInfo.m_isInContact)
{
needs_cushioning_test = true;
break;
}
}
if(needs_cushioning_test)
{
const btVector3 &v = m_chassisBody->getLinearVelocity();
btVector3 down(0, 1, 0);
btVector3 v_down = (v * down) * down;
btScalar max_compensate_speed = m_wheelInfo[0].m_maxSuspensionForce * m_chassisBody->getInvMass() * step *4;
if(-v_down.getY() > max_compensate_speed)
{
btVector3 impulse = down * (-v_down.getY() - max_compensate_speed) / m_chassisBody->getInvMass();
Log::verbose("physics", "Cushioning %f", impulse.getY());
m_chassisBody->applyCentralImpulse(impulse);
}
}
for(int i=0; i<m_wheelInfo.size(); i++)
m_wheelInfo[i].m_was_on_ground = m_wheelInfo[i].m_raycastInfo.m_isInContact;
// If the kart is flying, try to keep it parallel to the ground. // If the kart is flying, try to keep it parallel to the ground.
if(m_num_wheels_on_ground==0) if(m_num_wheels_on_ground==0)
{ {