How to skip a body in the ClosestRayResultCallback?

kakuro777
Posts: 11
Joined: Fri Jan 16, 2009 12:01 pm

How to skip a body in the ClosestRayResultCallback?

Post by kakuro777 »

Hi all - how to skip a particular body in the ClosestRayResultCallback? I want to check that the ray is colliding with some objects, but want to do not test (just skip) another. Any ideas?

Thanks!
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How to skip a body in the ClosestRayResultCallback?

Post by Erwin Coumans »

You can derive your custom class from btCollisionWorld::ClosestRayResultCallback and override the virtual 'addSingleResult'.

See for example in Bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp:

Code: Select all

class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
public:
        btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
        {
                m_me = me;
        }

        virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
        {
                if (rayResult.m_collisionObject == m_me)
                        return 1.0;

                return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
        }
protected:
        btCollisionObject* m_me;
};
Hope this helps,
Erwin
kakuro777
Posts: 11
Joined: Fri Jan 16, 2009 12:01 pm

Re: How to skip a body in the ClosestRayResultCallback?

Post by kakuro777 »

Thanks, but in this way, the ray test just stops on this body and return 1.0. I want to make this body "invisible" for the ray...
ola
Posts: 169
Joined: Sun Jan 14, 2007 7:56 pm
Location: Norway

Re: How to skip a body in the ClosestRayResultCallback?

Post by ola »

You need to re-implement the needsCollision function, so that it returns false in the cases where you don't want a hit. Here's an example from my engine, where sensors and the terrain is filtered out (I have my own sensor class that is derived from btCollisionObject).

Code: Select all

   struct MyPositionRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
   {
         MyPositionRayResultCallback(  const btVector3& rayFromWorld,
                                    const btVector3& rayToWorld)
      : btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld)
         {

         }
      
      virtual bool needsCollision(btBroadphaseProxy* proxy0) const
         {
         const btCollisionObject* co = (btCollisionObject*)proxy0->m_clientObject;
                 
         const MySensorObject* so = dynamic_cast<const MySensorObject*>(co);
         if(so)
            return false;
         
         if(co->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
            return false;
         
         bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
         collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
         return collides;
         }
   };
So you see, just do whatever checks you need, return false if it should be rejected.

The last 3 lines are copied from the original needsCollision function, could be that you could also just type

Code: Select all

return btCollisionWorld::ClosestRayResultCallback::needsCollision(proxy0) 
instead, or something like that, so that you're up-to-date if the original function is changed. Just haven't tried that myself yet.

Best regards,
Ola
kakuro777
Posts: 11
Joined: Fri Jan 16, 2009 12:01 pm

Re: How to skip a body in the ClosestRayResultCallback?

Post by kakuro777 »

That was very helpful! Thanks Ola!
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How to skip a body in the ClosestRayResultCallback?

Post by Erwin Coumans »

kakuro777 wrote:Thanks, but in this way, the ray test just stops on this body and return 1.0. I want to make this body "invisible" for the ray...
Are you sure and have you tested it? Returning 1.0 in 'addSingleResult' will basically ignore the object, making it effectively invisible to the ray.

Nevertheless, Ole's recommendation is better, 'needsCollision ' culls the object before testing, while 'addSingleResult' culls it after the actual ray-object test.
Thanks,
Erwin