Ray testing not working with btCompoundShape of one

Post Reply
Toymaker
Posts: 5
Joined: Tue Mar 11, 2014 6:57 pm
Contact:

Ray testing not working with btCompoundShape of one

Post by Toymaker »

I hope somebody can help me.

I have imported a mesh from an FBX file and created a btBvhTriangleMeshShape from it. I turn debug line drawing on and there in the world is the nice blue wireframe of the physics shape in all it's glory. I'm attaching the bvh tm to a btCompoundShape and everything still looks good. Next I pick/rayTest from screenspace through the model BUT nothing happens. The hasHit() call always returns false. I have verified that the ray is correct.

Now here's the interesting thing.

1) If I load models with only one submesh thus creating only one btBvhTriangleMeshShape in my compound shape then ray testing never works. If on the other hand I load a model that has more than one submesh and produces multiple triangle mesh shapes then it works!

2) And yet if the camera angle is looking down +X and I cast my ray through the object even on the working model the rayTest fails.

Here's some code. The swap of z and y is because my coordinate system is +X right, +Y forward and +Z up. Has that anything to do with it?

Code: Select all

        void rayTest( btDiscreteDynamicsWorld* world, const ray3& ray, const Entity::RaycastResult& lambda ){
          btVector3 rayTo(
              btScalar( ray.p.x + ray.d.x ),
              btScalar( ray.p.z + ray.d.z ),
              btScalar( ray.p.y + ray.d.y ));
          btVector3 rayFrom(
              btScalar( ray.p.x ),
              btScalar( ray.p.z ),
              btScalar( ray.p.y ));
          btCollisionWorld::ClosestRayResultCallback cb( rayFrom, rayTo );
          world->rayTest( rayFrom, rayTo, cb );
          ray3 rays[2];
          rays[1]=ray;
          if( cb.hasHit() ){
            btRigidBody* bt = (btRigidBody*)cb.m_collisionObject;
            pt3 P;
            P.x = cb.m_hitPointWorld.x();
            P.y = cb.m_hitPointWorld.z();
            P.z = cb.m_hitPointWorld.y();
            vec3 N;
            N.x = cb.m_hitNormalWorld.x();
            N.y = cb.m_hitNormalWorld.z();
            N.z = cb.m_hitNormalWorld.y();
            if( !N.valid() ){
              N = vec3( 0, 1, 0 );
            }
            Entity::Instance& instance = *(Entity::Instance*)bt->getUserPointer();
            rays[0] = ray3( P, N );
            lambda( rays, &instance );
          }else{
            lambda( rays, nullptr );
          }
        }
Thanks a lot for any help given.

BpH
Toymaker
Posts: 5
Joined: Tue Mar 11, 2014 6:57 pm
Contact:

Re: Ray testing not working with btCompoundShaoe of one.

Post by Toymaker »

Figured it out!

You cannot use

Code: Select all

tm.setBulletObject( new btTriangleIndexVertexArray( s32( ibo.size()/3 ), pIndex, 12, s32( vbo.size() ), pVertex, 12 ));
It simply won't work.

You have to use:

Code: Select all

btTriangleMesh* pTM = new btTriangleMesh( true, false );
pTM->preallocateVertices( u32( ibo.size() / 3 ));
for( u64 n=ibo.size(), i=0; i<n; ){
  const btScalar* va = pVertex + pIndex[ i++ ]*3;
  const btScalar* vb = pVertex + pIndex[ i++ ]*3;
  const btScalar* vc = pVertex + pIndex[ i++ ]*3;
  pTM->addTriangle(
    btVector3( va[0], va[1], va[2] ),
    btVector3( vb[0], vb[1], vb[2] ),
    btVector3( vc[0], vc[1], vc[2] )
  );
}
tm.setBulletObject( pTM );
Post Reply