Ray Test With Incorrect Hit Fraction

duser
Posts: 16
Joined: Wed Feb 02, 2011 6:48 pm

Ray Test With Incorrect Hit Fraction

Post by duser »

Hi,

I have been using ray tests for clicking and selecting objects for an RTS style game. When I do sometimes I get a hit position on the object that is too far past it (like the ray missed and somehow got an impact response at a further distance).

What some factors may be are:
- ray test length is 2,500,000 (yes long, but it is a large scaled game and this still occurs when I split the ray into 1000 raytests of 2500)
- click objects are fairly complex (as in they are compound objects of compound objects of convex hulls to allow for concave shapes with our model export/import pipeline)

When the ray test goes wrong, I can get it to reproduce when clicking in spaces between shapes in the compound shape (like 1 out of 20 - 30 tries):
example drawing (sorry just using keyboard art, ignore the "-" as they are blank spaces)
- click right here -||
--------________-V-__________
-------|-----------\x/--------------|
-------|------------/---------------|
-------|_________|___________|

There may be other ways to reproduce it, but this was the easiest way I found in the game. What I get is that when I click in the spot (where the "x" is and yes it is a valid hit result) I sometimes get a hit fraction of 0.08-0.95 when an accurate value should have been about 0.001. So from 2,500,000 ray length, the distance is 200000-2375000 instead of an expected 2500. This does not seem to occur with sweep tests in the same scenario (if it does it would seem to be extremely rare).

My question is, what could be causing the hit fraction to be off like that?

I have traced back to where it is getting the hit fraction. It comes from the btSubsimplexConvexCast convexCastor => convexCastor.calcTimeOfImpact(...).



void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback)
{
btSphereShape pointShape(btScalar(0.0));
pointShape.setMargin(0.f);
const btConvexShape* castShape = &pointShape;

if (collisionShape->isConvex())
{
// BT_PROFILE("rayTestConvex");
btConvexCast::CastResult castResult;
castResult.m_fraction = resultCallback.m_closestHitFraction;

btConvexShape* convexShape = (btConvexShape*) collisionShape;
btVoronoiSimplexSolver simplexSolver;
#define USE_SUBSIMPLEX_CONVEX_CAST 1
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
#else
//btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
#endif //#USE_SUBSIMPLEX_CONVEX_CAST

if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
{
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
//rotate normal into worldspace
castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
#endif //USE_SUBSIMPLEX_CONVEX_CAST

castResult.m_normal.normalize();
btCollisionWorld::LocalRayResult localRayResult
(
collisionObject,
0,
castResult.m_normal,
castResult.m_fraction
);

bool normalInWorldSpace = true;
resultCallback.addSingleResult(localRayResult, normalInWorldSpace);

}
}
}
}



Thank you for any information