Code: Select all
struct YourContext {
};
struct ContactSensorCallback : public btCollisionWorld::ContactResultCallback {
//! Constructor, pass whatever context you want to have available when processing contacts
/*! You may also want to set m_collisionFilterGroup and m_collisionFilterMask
* (supplied by the superclass) for needsCollision() */
ContactSensorCallback(btRigidBody& tgtBody , YourContext& context /*, ... */)
: btCollisionWorld::ContactResultCallback(), body(tgtBody), ctxt(context) { }
btRigidBody& body; //!< The body the sensor is monitoring
YourContext& ctxt; //!< External information for contact processing
//! If you don't want to consider collisions where the bodies are joined by a constraint, override needsCollision:
/*! However, if you use a btCollisionObject for #body instead of a btRigidBody,
* then this is unnecessary—checkCollideWithOverride isn't available */
virtual bool needsCollision(btBroadphaseProxy* proxy) const {
// superclass will check m_collisionFilterGroup and m_collisionFilterMask
if(!btCollisionWorld::ContactResultCallback::needsCollision(proxy))
return false;
// if passed filters, may also want to avoid contacts between constraints
return body.checkCollideWithOverride(static_cast<btCollisionObject*>(proxy->m_clientObject));
}
//! Called with each contact for your own processing (e.g. test if contacts fall in within sensor parameters)
virtual btScalar addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0,int partId0,int index0,
const btCollisionObjectWrapper* colObj1,int partId1,int index1)
{
btVector3 pt; // will be set to point of collision relative to body
if(colObj0->m_collisionObject==&body) {
pt = cp.getPositionWorldOnA();
cprintf ("%f %f %f\n", pt.getX(), pt.getY(), pt.getZ());
} else {
assert(colObj1->m_collisionObject==&body && "body does not match either collision object");
pt = cp.m_localPointB;
}
// do stuff with the collision point
return 0; // not actually sure if return value is used for anything...?
}
};
//-------------------------------------------------------------------------------------
Cooperative_Pathfinding_Test::Cooperative_Pathfinding_Test(void)
{
initPhysics();
}
//-------------------------------------------------------------------------------------
Cooperative_Pathfinding_Test::~Cooperative_Pathfinding_Test(void)
{
}
//-------------------------------------------------------------------------------------
void Cooperative_Pathfinding_Test::initPhysics() {
///-----includes_end-----
int i;
///-----initialization_start-----
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
m_dynamicsWorld->setGravity(btVector3(0,-10,0));
///-----initialization_end-----
///create a few basic rigid bodies
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
btAlignedObjectArray<btCollisionShape*> collisionShapes;
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-56,0));
{
btScalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}
{
//create a dynamic rigidbody
btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
//btCollisionShape* colShape = new btSphereShape(btScalar(1.));
collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(btVector3(2,10,0));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, colShape);
tgtBody = new btRigidBody(cInfo);
m_dynamicsWorld->addRigidBody(tgtBody);
}
}
bool Cooperative_Pathfinding_Test::frameRenderingQueued(const Ogre::FrameEvent& evt) {
m_dynamicsWorld->stepSimulation(1.f/60.f,10);
YourContext foo;
ContactSensorCallback callback(*tgtBody, foo);
m_dynamicsWorld->contactTest(tgtBody,callback);
return FrameListener::frameRenderingQueued(evt);
}
It seems like a sphere shape is far more stable than a box shape, didn't understand why?