I'm trying to make a version of the CharacterDemo using the Irrlicht graphics engine, and I'm getting a segfault when the capsule and my static plane collide. I understand I may need to react to contact myself, but a segfault?
The code is simple, it's mostly the CharacterDemo code with a little Irrlicht thrown in. Running the code in gdb gives me the following:
Code: Select all
Program received signal SIGSEGV, Segmentation fault.
0x082bc2e0 in btKinematicClosestNotMeConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult&, bool) ()Code: Select all
#include <irrlicht.h>
#include "btBulletDynamicsCommon.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletDynamics/Character/btKinematicCharacterController.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// Parameters for Irrlight Window/Device
SIrrlichtCreationParameters initIrrParams(){
SIrrlichtCreationParameters cp;
cp.DriverType = EDT_OPENGL;
cp.WindowSize = dimension2d<s32>(640,480);
cp.Bits = 32;
cp.Fullscreen = false;
cp.Vsync = false;
cp.Stencilbuffer = false;
cp.AntiAlias = 8;
cp.EventReceiver = 0;
cp.WindowId = 0;
return cp;
}
int main(int argc,char** argv){
// Set up Irrlicht
IrrlichtDevice *device = createDeviceEx( initIrrParams() );
device->setWindowCaption(L"Irrlicht+Bullet Character Movement");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
// Set up Bullet
btDefaultCollisionConfiguration* m_collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
btVector3 worldMin(-1000,-1000,-1000);
btVector3 worldMax(1000,1000,1000);
btAxisSweep3* sweepBP = new btAxisSweep3(worldMin,worldMax);
btBroadphaseInterface* m_overlappingPairCache = sweepBP;
btConstraintSolver* m_constraintSolver = new btSequentialImpulseConstraintSolver();
btDiscreteDynamicsWorld* m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
/// Setup Character Controlable Capsule Shape
btTransform startTransform;
startTransform.setIdentity ();
startTransform.setOrigin (btVector3(0.0, 150.0, 0.0)); // Create it 150 units in the air, so we have some time before contact with the plane
btPairCachingGhostObject* m_ghostObject = new btPairCachingGhostObject();
m_ghostObject->setWorldTransform(startTransform);
sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
btScalar characterHeight=1.75;
btScalar characterWidth =1.75;
btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
m_ghostObject->setCollisionShape (capsule);
m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
m_dynamicsWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
btScalar stepHeight = btScalar(0.35);
btKinematicCharacterController* m_character = new btKinematicCharacterController (m_ghostObject,capsule,stepHeight);
m_dynamicsWorld->addAction(m_character);
// Create a Cube to follow the Ghost/Character Capsule and a few lights and a camera so we can see the world
ISceneNode* scene_node = smgr->addCubeSceneNode(2);
smgr->addLightSceneNode(0, vector3df(6,8,-5), SColorf(0.58f,0.73f,0.89f,1.0f), 19.0f);
smgr->addLightSceneNode(0, vector3df(-6,1,5), SColorf(0.58f,0.73f,0.89f,1.0f), 19.0f);
ICameraSceneNode* my_cam = smgr->addCameraSceneNode(0, vector3df(17,80,-17), vector3df((5*2.1)/2,(5*2.1)/2,(5*2.1)/2));
/// Create a Static Plane to walk around on
// Segfaults- I think it's segfaulting when the objects collide in the loop
btDefaultMotionState* bullet_MotionState = new btDefaultMotionState( btTransform(btQuaternion(0,0,0,1), btVector3(0,0,0)));
btCollisionShape* bullet_Shape = new btStaticPlaneShape( btVector3(0,1,0), 1); // Create Plane Shape
btRigidBody::btRigidBodyConstructionInfo bullet_RigidBodyCI( 0, bullet_MotionState, bullet_Shape, btVector3(0,0,0) );
btRigidBody* bullet_RigidBody = new btRigidBody( bullet_RigidBodyCI );
m_dynamicsWorld->addRigidBody( bullet_RigidBody );
// Creating the Terrain in Irrlicht
float scale_val = 1;
float hm_size = 512;
float offset = ((hm_size*scale_val)/2)*-1;
ITerrainSceneNode *node = smgr->addTerrainSceneNode("tileable_hm.png", 0, -1, vector3df( offset, 0, offset ) , vector3df(0.f, 0.f, 0.f), vector3df(scale_val, 0.0, scale_val) );
node->setMaterialFlag(EMF_LIGHTING, true);
node->setMaterialFlag(EMF_WIREFRAME, !node->getMaterial(0).Wireframe);
node->setMaterialTexture( 0, driver->getTexture("tileable_hm.png") );
// These controls will eventually be activated by keyboard or mouse
bool goLeft = false;
bool goRight = false;
bool goForward = false;
bool goBackward = false;
/// The Game Loop
ITimer* const timer = device->getTimer();
u32 then = timer->getTime();
while(device->run()){
const u32 now = timer->getTime();
const btScalar dt = (btScalar)(now - then)*0.001; // Time in seconds
then = now;
// Set walkDirection and Speed for our character
btTransform xform;
xform = m_ghostObject->getWorldTransform ();
btVector3 forwardDir = xform.getBasis()[2];
// printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]);
btVector3 upDir = xform.getBasis()[1];
btVector3 strafeDir = xform.getBasis()[0];
forwardDir.normalize ();
upDir.normalize ();
strafeDir.normalize ();
btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
btScalar walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s
btScalar walkSpeed = walkVelocity * dt;
//rotate view
if (goLeft){
btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis();
orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),0.01));
m_ghostObject->getWorldTransform ().setBasis(orn);
}
if (goRight){
btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis();
orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),-0.01));
m_ghostObject->getWorldTransform ().setBasis(orn);
}
if (goForward){ walkDirection += forwardDir; }
if (goBackward){ walkDirection -= forwardDir; }
m_character->setWalkDirection(walkDirection*walkSpeed);
// Set my cube's position and rotation to match m_ghostObject's
btTransform my_trans;
my_trans = m_ghostObject->getWorldTransform();
matrix4 matr;
my_trans.getOpenGLMatrix(matr.pointer());
scene_node->setRotation(matr.getRotationDegrees());
scene_node->setPosition(matr.getTranslation());
my_cam->setTarget( scene_node->getPosition() ); // Follow with the camera
// Step the simulation and draw everything
m_dynamicsWorld->stepSimulation(dt,10.0f);
driver->beginScene(true, true, SColor(255,28,28,30));
smgr->drawAll();
driver->endScene();
}
return 0;
}