@ -24,45 +24,57 @@ ActorConvexCallback sweepHelper(const btCollisionObject *actor, const btVector3&
assert ( shape - > isConvex ( ) ) ;
const btVector3 motion = from - to ; // FIXME: this is backwards; means ActorConvexCallback is doing dot product tests backwards too
ActorConvexCallback newT raceCallback( actor , motion , btScalar ( 0.0 ) , world ) ;
ActorConvexCallback t raceCallback( actor , motion , btScalar ( 0.0 ) , world ) ;
// Inherit the actor's collision group and mask
newT raceCallback. m_collisionFilterGroup = actor - > getBroadphaseHandle ( ) - > m_collisionFilterGroup ;
newT raceCallback. m_collisionFilterMask = actor - > getBroadphaseHandle ( ) - > m_collisionFilterMask ;
t raceCallback. m_collisionFilterGroup = actor - > getBroadphaseHandle ( ) - > m_collisionFilterGroup ;
t raceCallback. m_collisionFilterMask = actor - > getBroadphaseHandle ( ) - > m_collisionFilterMask ;
if ( actorFilter )
newT raceCallback. m_collisionFilterMask & = ~ CollisionType_Actor ;
t raceCallback. m_collisionFilterMask & = ~ CollisionType_Actor ;
world - > convexSweepTest ( static_cast < const btConvexShape * > ( shape ) , transFrom , transTo , newT raceCallback) ;
return newT raceCallback;
world - > convexSweepTest ( static_cast < const btConvexShape * > ( shape ) , transFrom , transTo , t raceCallback) ;
return t raceCallback;
}
void ActorTracer : : doTrace ( const btCollisionObject * actor , const osg : : Vec3f & start , const osg : : Vec3f & end , const btCollisionWorld * world )
void ActorTracer : : doTrace ( const btCollisionObject * actor , const osg : : Vec3f & start , const osg : : Vec3f & end , const btCollisionWorld * world , bool attempt_short_trace )
{
const btVector3 btstart = Misc : : Convert : : toBullet ( start ) ;
btVector3 btend = Misc : : Convert : : toBullet ( end ) ;
bool do_fallback = false ;
if ( ( btend - btstart ) . length2 ( ) > 5.0 * 5.0 )
// Because Bullet's collision trace tests touch *all* geometry in its path, a lot of long collision tests
// will unnecessarily test against complex meshes that are dozens of units away. This wouldn't normally be
// a problem, but bullet isn't the fastest in the world when it comes to doing tests against triangle meshes.
// Therefore, we try out a short trace first, then only fall back to the full length trace if needed.
// This trace needs to be at least a couple units long, but there's no one particular ideal length.
// The length of 2.1 chosen here is a "works well in practice after testing a few random lengths" value.
// (Also, we only do this short test if the intended collision trace is long enough for it to make sense.)
const float fallback_length = 2.1f ;
bool doing_short_trace = false ;
// For some reason, typical scenes perform a little better if we increase the threshold length for the length test.
// (Multiplying by 2 in 'square distance' units gives us about 1.4x the threshold length. In benchmarks this was
// slightly better for the performance of normal scenes than 4.0, and just plain better than 1.0.)
if ( attempt_short_trace & & ( btend - btstart ) . length2 ( ) > fallback_length * fallback_length * 2.0 )
{
btend = btstart + ( btend - btstart ) . normalized ( ) * 5.0 ;
do_fallback = true ;
btend = btstart + ( btend - btstart ) . normalized ( ) * fallback_length ;
do ing_short_trace = true ;
}
auto newTraceCallback = sweepHelper ( actor , btstart , btend , world , false ) ;
auto t raceCallback = sweepHelper ( actor , btstart , btend , world , false ) ;
// Copy the hit data over to our trace results struct:
if ( newTraceCallback . hasHit ( ) )
if ( t raceCallback. hasHit ( ) )
{
mFraction = newTraceCallback . m_closestHitFraction ;
if ( ( end - start ) . length2 ( ) > 0.0 )
mFraction = traceCallback . m_closestHitFraction ;
// ensure fraction is correct (covers intended distance traveled instead of actual distance traveled)
if ( doing_short_trace & & ( end - start ) . length2 ( ) > 0.0 )
mFraction * = ( btend - btstart ) . length ( ) / ( end - start ) . length ( ) ;
mPlaneNormal = Misc : : Convert : : toOsg ( newT raceCallback. m_hitNormalWorld ) ;
mPlaneNormal = Misc : : Convert : : toOsg ( t raceCallback. m_hitNormalWorld ) ;
mEndPos = ( end - start ) * mFraction + start ;
mHitPoint = Misc : : Convert : : toOsg ( newT raceCallback. m_hitPointWorld ) ;
mHitObject = newT raceCallback. m_hitCollisionObject ;
mHitPoint = Misc : : Convert : : toOsg ( t raceCallback. m_hitPointWorld ) ;
mHitObject = t raceCallback. m_hitCollisionObject ;
}
else
{
if ( do _fallback )
if ( do ing_short_trace )
{
btend = Misc : : Convert : : toBullet ( end ) ;
auto newTraceCallback = sweepHelper ( actor , btstart , btend , world , false ) ;