Pickupable Items (weapons, medpacks, etc.)

Post Reply
SyncViews
Posts: 5
Joined: Tue Aug 26, 2014 8:12 pm

Pickupable Items (weapons, medpacks, etc.)

Post by SyncViews »

I am trying to work out how best to implement items/entities that players (and possibly) NPC's can drop/pickup.
  • They need to be physically simulated in respect to gravity, terrain and certain select large objects (e.g. elevators)
  • They should not collide with each other or any objects not above (e.g. players), or maybe more correctly, not react to the collision (e.g. block the btKinematicCharacterController from moving)
  • I want to detect whenever a player starts to collide/overlap with them (so when the player runs over them the player picks them up)
I worked out how to get the first 2 points to work using the collision filters stuff (based on http://bulletphysics.org/mediawiki-1.5. ... _Filtering ), but not how to efficiently then do the 3rd point (since in order to the player physically interacting with them, e.g. blocking doors, etc., there not in the collision filter...).

Code: Select all

btDiscreteDynamicsWorld *bulletWorld;
//Player, uses btPairCachingGhostObject with btKinematicCharacterController
bulletWorld->addCollisionObject(&ghostObject, COL_PLAYER, COL_TERRAIN);
//Terrain, uses a btRigidBody with a custom btConcaveShape
bulletWorld->addRigidBody(&terrainBody, COL_TERRAIN, (short)(COL_ALL ^ COL_TERRAIN));
//ItemEntity, uses btRigidBody
bulletWorld->addRigidBody(&btObject, COL_ITEM, COL_TERRAIN);
Collision Detection in Player entity class (based on http://bulletphysics.org/mediawiki-1.5. ... d_Triggers)

Code: Select all

btManifoldArray manifoldArray;
auto bulletWorld = world->getPhysics().getBulletWorld();
auto &pairArray = ghostObject.getOverlappingPairCache()->getOverlappingPairArray();
for (int i = 0; i < pairArray.size(); ++i)
{
    auto &pair = pairArray[i];
    //TODO: Is it possible to look at pair directory for instances I
    //only care that an overlapp happened between 2 objects?
    btBroadphasePair* collisionPair = bulletWorld->getPairCache()->findPair(pair.m_pProxy0, pair.m_pProxy1);
    if (collisionPair->m_algorithm)
        collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);

    for (int j = 0; j < manifoldArray.size(); j++)
    {
        btPersistentManifold* manifold = manifoldArray[j];
        auto otherObject = manifold->getBody0() != &ghostObject ?
            manifold->getBody0() : manifold->getBody1();
        auto userData = (BulletUserData*)otherObject->getUserPointer();
        if (userData && userData->isEntity() && userData->asEntity()->isAlive())
        {
            //TODO: Come up with a design to avoid the dynamic_cast...
            ItemEntity *item = dynamic_cast<ItemStackEntity*>(userData->asEntity());
            if (item)
            {
                item->addToInventory(inventory);
            }
        }
    }
}
I think I could do it by having another ghost object mirror the item object with a filter to collide with the player, or maybe using contactPairTest explicitly, but I suspect there is a proper way to do this and I am doing it wrong.
Post Reply