Some collisions not getting detected?

tasche
Posts: 5
Joined: Tue Sep 13, 2011 10:27 pm

Some collisions not getting detected?

Post by tasche »

hi ive setup my project to use bullet for collision detection.
i use a heightfield pass it to the world as a static rigidbody and use a ghost object as the collider, simulating a bullet (or some projectile)
this works for like 70-80% of the cases, the impact of the bullet gets calculated correctly, but like every 5th od 6th collision test completely fails, and the bullet penetrates the heightfield w/o registering a collision. this behaviour seems to correlate with the geometry of the height field, because 'shooting' the same spot several times seems more prone to trigger a collision failure., also it seems to have to do with penetration angle.

any ideas what i could tweak to eliminate this behaviour?

this is how i setup the world:

Code: Select all

    m_broadphase = new btDbvtBroadphase();
    m_collisionConfiguration = new btDefaultCollisionConfiguration();
    m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
    m_solver = new btSequentialImpulseConstraintSolver;
    m_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback);
    m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
    m_dynamicsWorld->setGravity(btVector3(0,-9.8f,0));
the terrain

Code: Select all

    m_terrCollShape = new btHeightfieldTerrainShape(xSize,zSize, m_pGridData, 60.0f, min, max, 1, PHY_FLOAT, false);
    btVector3 scaling;
    scaling.setX(PLANESCALE);
    scaling.setY(1.0f);
    scaling.setZ(PLANESCALE);
    m_terrCollShape->setLocalScaling(scaling);
    float cX=(xSize*PLANESCALE)/2.0f+m_tData.globalOffsetX;
    float cZ=(zSize*PLANESCALE)/2.0f+m_tData.globalOffsetZ;
    m_terrMS = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(cX,(min+max)/2.0f,cZ)));
    btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,m_terrMS,m_terrCollShape,btVector3(0,0,0));
    m_terrRB = new btRigidBody(groundRigidBodyCI);
    m_terrRB->setUserPointer(this);
the ghost object

Code: Select all

            m_objGO = new btPairCachingGhostObject();
            m_objGO->setWorldTransform(t);
            m_objGO->setCollisionShape(m_mesh->GetCollShape());
            m_objGO->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
            m_objGO->setUserPointer(this);
i add it to the world with

Code: Select all

         m_dynamicsWorld->addCollisionObject(pObj->m_objGO, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
the broadphase shouldnt matter at all, since the g.o.'s AABB is always completely contained in that of the the heightfield (at least in the debug runs i made, but its hard to debug a bug that seems random to reproduce)

EDIT: this might be useful too, the collision procedure (mostly a copypasty from collisioninterfacedemo). it lacks precision, but that not neccesary for my app

Code: Select all

    btManifoldArray   manifoldArray;
    btBroadphasePairArray& pairArray = m_objGO->getOverlappingPairCache()->getOverlappingPairArray();
    worldHitPoint->setValue(0,0,0);
    int numPairs = pairArray.size();
    for (int i=0;i<numPairs;i++)
    {
        manifoldArray.clear();
        const btBroadphasePair& pair = pairArray[i];
        //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
        btBroadphasePair* collisionPair = dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
        if (!collisionPair)
        continue;

        if (collisionPair->m_algorithm)
        collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);

        for (int j=0;j<manifoldArray.size();j++)
        {
            btPersistentManifold* manifold = manifoldArray[j];
            btScalar directionSign = manifold->getBody0() == m_objGO ? btScalar(-1.0) : btScalar(1.0);
            for (int p=0;p<manifold->getNumContacts();p++)
            {
                const btManifoldPoint&pt = manifold->getContactPoint(p);
                if (pt.getDistance()<0.f)
                {
                    const btVector3& ptA = pt.getPositionWorldOnA();
                    const btVector3& ptB = pt.getPositionWorldOnB();
                    const btVector3& normalOnB = pt.m_normalWorldOnB;
                    (*worldHitPoint) = ptB;
                    m_type = OBJ_TYPE_DELETED;
                    dynamicsWorld->removeCollisionObject(m_objGO);
                    return true;
                }
            }
        }
    }
    return false;
}
cheers,
tasche
MaxDZ8
Posts: 149
Joined: Fri Jun 24, 2011 8:53 am

Re: Some collisions not getting detected?

Post by MaxDZ8 »

Ok, what about the projectile (is it m_objGO)?
My first step would be to slow it down to see if it affects the problem.
Keep in mind that kinematic object must have SetActivationState(DISABLE_DEACTIVATION) always set, otherwise, they'll effectively update internal bullet state only a few times per second (I'd say every 4-5 ticks) as they will be deactivated.

In general, fast-moving objects must be checked by the means of continuous collision. Either do a ray-cast or a sweep. Relying on "standard" collision detection is in my opinion quite a bit of a stretch (I'm dealing with low performance hardware so this is exaggerated in my case).
tasche
Posts: 5
Joined: Tue Sep 13, 2011 10:27 pm

Re: Some collisions not getting detected?

Post by tasche »

hey max, thanks for the answer.

i tried slowing the projectile down, should've mentioned that in the original post. the time the collsion shape (a box) of the projectile coincides with the surface of the heightfield is at least 2 seconds (thats 120 ticks at standard interval) , which should trigger a collision; i get this info by my own graphical representation of the objects, but that should fit, since everything else works with that, like dynamic rigid bodies and raycasts.

tried turning off deactivation, didnt change anything...

at first i thought somethings wrong with my heightfield or maybe the collision shape or something, but after extensive testing with raycasts and dynamic rigid bodies everything seems to be fine. also colliding kinematic objects with each other seems to work, i havent tried that too much yet. also i dont want to test out too much new features (and waste time learning them), since i may remove bullet from my project entirely, bite the bullet (no pun intended) and write my own physics/collision, since i'm obviously to stupid to get it to work properly :/

anyway, thanks for the help sofar, if anyone has other ideas, pls mention them :).
i'd also be interested to find out if anyone has had similar problems, or if im really the only one who cant get it to work :D

cheers,
tasche
User avatar
Dr.Shepherd
Posts: 168
Joined: Tue Jan 04, 2011 11:47 pm

Re: Some collisions not getting detected?

Post by Dr.Shepherd »

How about set a smaller time step?
tasche
Posts: 5
Joined: Tue Sep 13, 2011 10:27 pm

Re: Some collisions not getting detected?

Post by tasche »

ok, seems ive tried everything i can, have eventually removed bullets someshape-terrain collision and have replaced it with my own DDA/voxel algorithm. i use this as raycasting collision now, seems to perform quite a bit better then bullet's raycast, especially when the line segment is very long (with bullet i had the issue of severe framerate drops from 600 to 20 for very long rays). for short rays i really cant tell the difference.

too bad, seems like i only use bullet for static and dynamic objects, and the largest static object i calculate by hand now too :(