This is my very first attempt in using a ghost object so I'm probably not doing it correctly. Trying to attach a ghost object to my kinematic controller so I can detect collisions when my kinematic object hits a static object. But the program crashes 1-2 seconds after adding the ghost object to the world.
Any help welcome. I've been trying to figure it out for days!
(Using bullet 2.81 on windows 7)
Here's the code for initializing the world.
Code: Select all
// Initialize Bullet Physics
collisionConfig=new btDefaultCollisionConfiguration();
dispatcher=new btCollisionDispatcher(collisionConfig);
broadphase=new btDbvtBroadphase();
broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
solver=new btSequentialImpulseConstraintSolver();
world=new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfig);
world->getDispatchInfo().m_useContinuous=Ccd; //for fast objects
world->setGravity(btVector3(0,-10,0)); //gravity on Earth
Code: Select all
float mass=0;
btTransform cam;
cam.setIdentity();
cam.setOrigin(btVector3(CamPosition.x,CamPosition.y,CamPosition.z));
cam.setRotation(btQuaternion(btVector3(0,1,0), 0)); //Tank matrix
ViewCam.setRotation(btQuaternion(btVector3(0,1,0), 0)); //View Matrix (tank turrent)
btBoxShape* cbox=new btBoxShape(btVector3(CAMSIZE/2.0,CAMSIZE/2.0,CAMSIZE/2.0));
btMotionState* motion=new btDefaultMotionState(cam);
btVector3 inertia(0,0,0);
cbox->calculateLocalInertia(mass, inertia);
btRigidBody::btRigidBodyConstructionInfo info(mass,motion,cbox,inertia);
btRigidBody* cambox=new btRigidBody(info);
cambox->setActivationState(DISABLE_DEACTIVATION);
cambox->setCollisionFlags(cambox->getCollisionFlags() | btCollisionObject:: CF_KINEMATIC_OBJECT);
world->addRigidBody(cambox);
camera.push_back(new BulletObject(cambox,CAM,(camera.size()-1), 0, 0, 0));
CamID=camera.size()-1;
cambox->setUserPointer(camera[CamID]);
// Add Ghost object that is synchonized with rigid body.
btPairCachingGhostObject* ghostobject = new btPairCachingGhostObject();
ghostobject->setCollisionShape(cbox);
ghostobject->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
ghostobject->setWorldTransform(cam);
world->addCollisionObject(ghostobject, btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
Code: Select all
/// Check for ghostobject collisions
void GhostCollisions(BulletObject* tmp)
{
btRigidBody* Tank=tmp->body;
btManifoldArray manifoldArray;
btBroadphasePairArray& pairArray = ghostobject->getOverlappingPairCache()->getOverlappingPairArray();
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 = world->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];
if(manifold->getBody0() == Tank)
continue;
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;
/// work here
}
}
}
}
}
Code: Select all
/// Move tank and the tank turrent view
void UpdateTank(BulletObject* view)
{
int Difference;
double angle;
Velocity= Vec3f(0,0,0);
btTransform t;
btRigidBody* cam=view->body;
cam->getMotionState()->getWorldTransform(t);
btMatrix3x3 camAng = cam->getWorldTransform().getBasis(); //Get rotation Matrix
btVector3 leftAxis=camAng.getColumn(0); //X-axis (left)
btVector3 upAxis=camAng.getColumn(1); //Y-axis (up)
btVector3 aheadAxis=camAng.getColumn(2); //Z-axis (ahead or forward)
btVector3 Cpos=t.getOrigin(); //Get position of camera
CamPosition.x=Cpos.getX();
CamPosition.y=Cpos.getY();
CamPosition.z=Cpos.getZ();
CamAhead.x=aheadAxis.getX();
CamAhead.y=aheadAxis.getY();
CamAhead.z=aheadAxis.getZ();
if (LeftMouseButtonFlag && !CenterFlag) //Skip if turrent is moving to home position
{
Difference = NewXmouse-OldXmouse; //Get distance mouse moved in X-axis
if (Difference !=0)
{
angle = (Difference/8)*TORADIANS;
Hangle=Hangle+angle;
ViewCam *=btMatrix3x3(btQuaternion(upAxis,angle));
}
Difference = NewYmouse-OldYmouse; //Get distance mouse moved in Y-axis
if (Difference !=0)
{
angle = Difference/8;
Vangle=Vangle+angle;
if (Vangle>60) Vangle=60; //limit vertical movement of turrent
if (Vangle<-5) Vangle=-5;
Upoffset=sinf(Vangle*TORADIANS);
}
}
if (CenterFlag) //Rotate turrent view back to home position
{
if (ViewCount>-1)
{
Vangle=Vangle-Ydivang;
Upoffset=sinf(Vangle*TORADIANS);
ViewCam *=btMatrix3x3(btQuaternion(upAxis,Xdivang*TORADIANS));
ViewCount--;
}
else
{
Vangle=0;
Hangle=0;
CenterFlag=false;
ViewCam=camAng;
}
}
if (GetAsyncKeyState(0x41)) //Rotate tank & turrent left
{
angle=1*TORADIANS;
camAng *= btMatrix3x3(btQuaternion(upAxis, angle));
ViewCam *= btMatrix3x3(btQuaternion(upAxis, angle));
}
if (GetAsyncKeyState(0x44)) //Rotate tank & turrent right
{
angle=-1*TORADIANS;
camAng *= btMatrix3x3(btQuaternion(upAxis, angle));
ViewCam *= btMatrix3x3(btQuaternion(upAxis, angle));
}
if (GetAsyncKeyState(87)) //Move tank ahead
{
Velocity=CamAhead*Camspeed;
Velocity.y=0; //Ignore Y-axis. Keep tank on ground
CamPosition+=Velocity;
}
if (GetAsyncKeyState(83)) //Move tank backwards
{
Velocity=CamAhead*Camspeed;
Velocity.y=0;
CamPosition-=Velocity;
Velocity=-Velocity;
}
t.setOrigin(btVector3(CamPosition.x,CamPosition.y,CamPosition.z));
t.setBasis(camAng);
cam->getMotionState()->setWorldTransform(t);
ghostobject->setWorldTransform(cam->getWorldTransform()); //Sync ghost to tank (FPS camera)
}
Code: Select all
UpdateTank(camera[CamID]); //Move the tank (FPS camera)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear screen and depth buffer.
glLoadIdentity();
btVector3 ahead=ViewCam.getColumn(2);
Vec3f tmp;
tmp.x=ahead.getX();
tmp.z=ahead.getZ();
tmp.y=Upoffset;
tmp=tmp.Normalize();
gluLookAt(CamPosition.x, CamPosition.y, CamPosition.z,
CamPosition.x+tmp.x, CamPosition.y+tmp.y, CamPosition.z+tmp.z,
0,1,0); //Aim camera in this direction
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
ExtractFrustum(); //Get observable space so we don't draw outside of it.
for(int i=0;i<bodies.size();i++) //Clear collision flags
bodies[i]->hit=false;
CheckPillars(); //Draw grid of pillars on plane (flat ground)
world->stepSimulation(1/60.0f,10); //Have bullet do all the dirty work
GhostCollisions(camera[CamID]); //Check if tank (camera) hit something
CheckCollisions(); //Check all other collisions