Improved collision handling to better detect left/right side
collisions. Made collisions more bouncy than before (but I am still tuning). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10827 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
9ba9aa5794
commit
90e6a02193
@ -312,7 +312,7 @@
|
||||
bevelling, and uses a simple box shape.
|
||||
As an example, a value of 1 for x and z will result in a
|
||||
sharp 'arrow' like shape. -->
|
||||
<collision impulse="150" impulse-time="0.1" side-impulse="600"
|
||||
<collision impulse="12000" impulse-time="0.1" side-impulse="600"
|
||||
restitution="1.0" bevel-factor="0.5 0.0 0.5" />
|
||||
|
||||
<!-- Kart-specific plunger and rubber band handling: max-length is
|
||||
|
@ -265,6 +265,7 @@ void DefaultAIController::update(float dt)
|
||||
/*And obviously general kart stuff*/
|
||||
AIBaseController::update(dt);
|
||||
m_collided = false;
|
||||
m_controls->m_fire = false;
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -438,8 +438,11 @@ void btKart::updateVehicle( btScalar step )
|
||||
|
||||
if(m_time_additional_impulse>0)
|
||||
{
|
||||
m_time_additional_impulse -= step;
|
||||
m_chassisBody->applyCentralImpulse(m_additional_impulse);
|
||||
float dt = step > m_time_additional_impulse
|
||||
? m_time_additional_impulse
|
||||
: step;
|
||||
m_chassisBody->applyCentralImpulse(m_additional_impulse*dt);
|
||||
m_time_additional_impulse -= dt;
|
||||
}
|
||||
|
||||
if(m_time_additional_rotation>0)
|
||||
@ -461,7 +464,7 @@ void btKart::updateVehicle( btScalar step )
|
||||
// kart, or a strongly 'visual jolt' of the kart
|
||||
btTransform &iwt=m_chassisBody->getInterpolationWorldTransform();
|
||||
iwt.setRotation(iwt.getRotation()*add_rot);
|
||||
m_time_additional_rotation -= step;
|
||||
m_time_additional_rotation -= dt;
|
||||
}
|
||||
} // updateVehicle
|
||||
|
||||
@ -724,30 +727,33 @@ void btKart::updateFriction(btScalar timeStep)
|
||||
rollingFriction=0;
|
||||
}
|
||||
|
||||
//switch between active rolling (throttle), braking and non-active
|
||||
// rolling friction (no throttle/break)
|
||||
|
||||
m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
|
||||
|
||||
btScalar maximp = wheelInfo.m_wheelsSuspensionForce
|
||||
* timeStep * wheelInfo.m_frictionSlip;
|
||||
btScalar maximpSide = maximp;
|
||||
btScalar maximpSquared = maximp * maximpSide;
|
||||
m_forwardImpulse[wheel] = rollingFriction;
|
||||
|
||||
btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
|
||||
btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
|
||||
|
||||
btScalar impulseSquared = (x*x + y*y);
|
||||
|
||||
if (impulseSquared > maximpSquared)
|
||||
if(m_time_additional_impulse>0)
|
||||
{
|
||||
sliding = true;
|
||||
btScalar factor = maximp / btSqrt(impulseSquared);
|
||||
m_wheelInfo[wheel].m_skidInfo *= factor;
|
||||
} // if impulseSquared > maximpSquared
|
||||
m_wheelInfo[wheel].m_skidInfo = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
btScalar maximp = wheelInfo.m_wheelsSuspensionForce
|
||||
* timeStep * wheelInfo.m_frictionSlip;
|
||||
btScalar maximpSide = maximp;
|
||||
btScalar maximpSquared = maximp * maximpSide;
|
||||
|
||||
btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
|
||||
btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
|
||||
|
||||
btScalar impulseSquared = (x*x + y*y);
|
||||
|
||||
if (impulseSquared > maximpSquared)
|
||||
{
|
||||
sliding = true;
|
||||
btScalar factor = maximp / btSqrt(impulseSquared);
|
||||
m_wheelInfo[wheel].m_skidInfo *= factor;
|
||||
} // if impulseSquared > maximpSquared
|
||||
} // else (!m_timed_impulse
|
||||
} // for (int wheel=0; wheel<getNumWheels(); wheel++)
|
||||
|
||||
} // for (int wheel=0; wheel<getNumWheels(); wheel++)
|
||||
|
||||
m_zipper_active = false;
|
||||
m_zipper_velocity = 0;
|
||||
@ -779,7 +785,7 @@ void btKart::updateFriction(btScalar timeStep)
|
||||
av.setY(m_skid_angular_velocity);
|
||||
m_chassisBody->setAngularVelocity(av);
|
||||
}
|
||||
else if (sliding && m_allow_sliding)
|
||||
else if (sliding && (m_allow_sliding || m_time_additional_impulse>0) )
|
||||
{
|
||||
for (int wheel = 0; wheel < getNumWheels(); wheel++)
|
||||
{
|
||||
|
@ -230,7 +230,7 @@ public:
|
||||
} // setTimedImpulse
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the time an additional impulse is activated. */
|
||||
float getImpulseTime() const { return m_time_additional_impulse; }
|
||||
float getCentralImpulseTime() const { return m_time_additional_impulse; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets a rotation that is applied over a certain amount of time (to avoid
|
||||
* a too rapid changes in the kart).
|
||||
|
@ -221,6 +221,11 @@ bool Physics::projectKartDownwards(const Kart *k)
|
||||
Physics::CollisionSide Physics::getCollisionSide(const btRigidBody *body,
|
||||
const Vec3 &contact_point)
|
||||
{
|
||||
if(contact_point.getX()>0)
|
||||
return COL_RIGHT;
|
||||
else
|
||||
return COL_LEFT;
|
||||
|
||||
btVector3 aabb_min, aabb_max;
|
||||
static btTransform zero_trans(btQuaternion(0, 0, 0));
|
||||
body->getCollisionShape()->getAabb(zero_trans, aabb_min, aabb_max);
|
||||
@ -277,98 +282,78 @@ Physics::CollisionSide Physics::getCollisionSide(const btRigidBody *body,
|
||||
void Physics::KartKartCollision(Kart *kart_a, const Vec3 &contact_point_a,
|
||||
Kart *kart_b, const Vec3 &contact_point_b)
|
||||
{
|
||||
// Only one kart needs to handle the attachments, it will
|
||||
// fix the attachments for the other kart.
|
||||
kart_a->crashed(kart_b, /*handle_attachments*/true);
|
||||
kart_b->crashed(kart_a, /*handle_attachments*/false);
|
||||
|
||||
// If bouncing crashes is enabled, add an additional force to the
|
||||
// slower kart
|
||||
Kart *faster_kart, *slower_kart;
|
||||
Vec3 faster_cp, slower_cp;
|
||||
if(kart_a->getSpeed()>=kart_b->getSpeed())
|
||||
Kart *push_left, *push_right;
|
||||
|
||||
// Determine which kart is pushed to the left, and which one to the
|
||||
// right. Ideally the sign of the X coordinate of the local conact point
|
||||
// could decide the direction (negative X --> was hit on left side, gets
|
||||
// push to right), but that can lead to both karts being pushed in the
|
||||
// same direction (front left of kart hits rear left).
|
||||
// So we just use a simple test (which does the right thing in ideal
|
||||
// crashes, but avoids pushing both karts in corner cases
|
||||
// - pun intended ;) ).
|
||||
if(contact_point_a.getX() < contact_point_b.getX())
|
||||
{
|
||||
faster_kart = kart_a;
|
||||
faster_cp = contact_point_a;
|
||||
slower_kart = kart_b;
|
||||
slower_cp = contact_point_b;
|
||||
push_right = kart_a;
|
||||
push_left = kart_b;
|
||||
}
|
||||
else
|
||||
{
|
||||
faster_kart = kart_b;
|
||||
faster_cp = contact_point_b;
|
||||
slower_kart = kart_a;
|
||||
slower_cp = contact_point_a;
|
||||
push_right = kart_b;
|
||||
push_left = kart_a;
|
||||
}
|
||||
|
||||
CollisionSide faster_side = getCollisionSide(faster_kart->getBody(),
|
||||
faster_cp);
|
||||
CollisionSide slower_side = getCollisionSide(slower_kart->getBody(),
|
||||
slower_cp);
|
||||
// Add a scaling factor depending on the mass (avoid div by zero)
|
||||
float f_left = push_left->getKartProperties()->getMass() > 0
|
||||
? push_right->getKartProperties()->getMass()
|
||||
/ push_left->getKartProperties()->getMass()
|
||||
: 1.5f;
|
||||
// Add a scaling factor depending on speed (avoid div by 0)
|
||||
f_left *= push_left->getSpeed() > 0
|
||||
? push_right->getSpeed()
|
||||
/ push_left->getSpeed()
|
||||
: 1.5f;
|
||||
// Cap left to [0.8,1.25], which results in f_right being
|
||||
// capped in the same interval
|
||||
if(f_left > 1.25f)
|
||||
f_left = 1.25f;
|
||||
else if(f_left < 0.8f)
|
||||
f_left = 0.8f;
|
||||
|
||||
// This probably needs adjusting once we have different kart properties.
|
||||
// E.g. besides speed we might also want to take mass into account(?)
|
||||
if(faster_side==COL_FRONT)
|
||||
float f_right = f_left ==0 ? 1.5f : 1/f_left;
|
||||
f_left = f_left * f_left * f_left;
|
||||
f_right = f_right * f_right * f_right;
|
||||
|
||||
// First push one kart to the left (if there is not already
|
||||
// an impulse happening - one collision might cause more
|
||||
// than one impulse otherwise)
|
||||
if(push_left->getVehicle()->getCentralImpulseTime()<=0)
|
||||
{
|
||||
// Special case: the faster kart hits a kart front on. In this case
|
||||
// the slower kart will be pushed out of the faster kart's way
|
||||
Vec3 dir = faster_kart->getVelocity();
|
||||
|
||||
// The direction in which the impulse will be applied depends on
|
||||
// which side of the faster kart was hitting it: if the hit is
|
||||
// on the right side of the faster kart, it will push the slower
|
||||
// kart to the right and vice versa. This is based on the
|
||||
// assumption that a hit to the right indicates that it's
|
||||
// shorter to push the slower kart to the right.
|
||||
Vec3 impulse;
|
||||
if(faster_cp.getX()>0)
|
||||
impulse = Vec3( dir.getZ(), 0, -dir.getX());
|
||||
else
|
||||
impulse = Vec3(-dir.getZ(), 0, dir.getX());
|
||||
impulse.normalize();
|
||||
impulse *= faster_kart->getKartProperties()->getCollisionImpulse();
|
||||
float t =
|
||||
faster_kart->getKartProperties()->getCollisionImpulseTime();
|
||||
if(t>0)
|
||||
slower_kart->getVehicle()->setTimedCentralImpulse(t, impulse);
|
||||
else
|
||||
slower_kart->getBody()->applyCentralImpulse(impulse);
|
||||
slower_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
|
||||
// Apply some impulse to the slower kart as well?
|
||||
const KartProperties *kp = push_right->getKartProperties();
|
||||
Vec3 impulse(-kp->getCollisionImpulse()*f_left, 0, 0);
|
||||
impulse = push_left->getTrans().getBasis() * impulse;
|
||||
push_left->getVehicle()
|
||||
->setTimedCentralImpulse(kp->getCollisionImpulseTime(),
|
||||
impulse);
|
||||
push_left ->getBody()->setAngularVelocity(btVector3(0,0,0));
|
||||
}
|
||||
else
|
||||
|
||||
// Then push the other kart to the right (if there is no
|
||||
// impulse happening atm).
|
||||
if(push_right->getVehicle()->getCentralImpulseTime()<=0)
|
||||
{
|
||||
// Non-frontal collision, push the two karts away from each other
|
||||
// First the faster kart
|
||||
Vec3 dir = faster_kart->getVelocity();
|
||||
Vec3 impulse;
|
||||
if(faster_cp.getX()>0)
|
||||
impulse = Vec3(-dir.getZ(), 0, dir.getX());
|
||||
else
|
||||
impulse = Vec3( dir.getZ(), 0, -dir.getX());
|
||||
impulse.normalize();
|
||||
impulse *= slower_kart->getKartProperties()->getCollisionImpulse();
|
||||
float t =
|
||||
faster_kart->getKartProperties()->getCollisionImpulseTime();
|
||||
if(t>0)
|
||||
faster_kart->getVehicle()->setTimedCentralImpulse(t, impulse);
|
||||
else
|
||||
faster_kart->getBody()->applyCentralImpulse(impulse);
|
||||
faster_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
|
||||
|
||||
// Then the slower kart
|
||||
dir = slower_kart->getVelocity();
|
||||
if(slower_cp.getX()>0)
|
||||
impulse = Vec3(-dir.getZ(), 0, dir.getX());
|
||||
else
|
||||
impulse = Vec3( dir.getZ(), 0, -dir.getX());
|
||||
|
||||
impulse.normalize();
|
||||
impulse *= faster_kart->getKartProperties()->getCollisionImpulse();
|
||||
t = faster_kart->getKartProperties()->getCollisionImpulseTime();
|
||||
if(t>0)
|
||||
slower_kart->getVehicle()->setTimedCentralImpulse(t, impulse);
|
||||
else
|
||||
slower_kart->getBody()->applyCentralImpulse(impulse);
|
||||
slower_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
|
||||
const KartProperties *kp = push_left->getKartProperties();
|
||||
Vec3 impulse = Vec3(kp->getCollisionImpulse()*f_right, 0, 0);
|
||||
impulse = push_right->getTrans().getBasis() * impulse;
|
||||
push_right->getVehicle()
|
||||
->setTimedCentralImpulse(kp->getCollisionImpulseTime(),
|
||||
impulse);
|
||||
push_right->getBody()->setAngularVelocity(btVector3(0,0,0));
|
||||
}
|
||||
|
||||
} // KartKartCollision
|
||||
|
Loading…
x
Reference in New Issue
Block a user