I wonder if anyone could help me. I am integrating bullet into my renderer. i require the ability to collide trimeshes with trimeshes. I am using the
btTriangleIndexVertexArray and btBvhTriangleMeshShape classes to read in my trimeshes. However, I have not had any luck colliding them.
As I advance the simulation, the objects do move, however, no collision.
Thinking that I was creating my btTriangleIndexVertexArray incorrectly, I copied the mesh directly into two arrays, very similarly to the code in many of the example demos such as ConcacePhysicsDemo, and tried colliding. The code is, as far as I can see, basically identical to the demo, yet they do not collide. Interestingly, if I change one of the meshes to a btBoxShape (I am in fact using a mesh of a box for debugging, and I set the btBoxShape to be identical in size), they collide fine.
I have ruled out my renderer being at fault because I am manually watching the world positions.
Here is my code (was put together from the HelloWorld demo):
Code: Select all
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;
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0,-10,0));
///create a few basic rigid bodies
//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;
// Here's where we manually set the mesh
int vertStride = sizeof(btVector3);
int indexStride = 3*sizeof(int);
const int totalTriangles = 12;
const int totalVerts = 8;
btVector3 * gVertices = new btVector3[totalVerts];
int* gIndices = new int[totalTriangles*3];
for(i = 0; i < totalTriangles*3; i++)
{
gIndices[i] = sc.mod[0].triangles[i];
}
for(i = 0; i < totalVerts; i++)
{
gVertices[i].setX(sc.mod[0].vertices[i].coords[0]);
gVertices[i].setY(sc.mod[0].vertices[i].coords[1]);
gVertices[i].setZ(sc.mod[0].vertices[i].coords[2]);
}
btTriangleIndexVertexArray* m_indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles,gIndices,indexStride, totalVerts,(btScalar*) &gVertices[0].x(),vertStride);
bool useQuantizedAabbCompression = true;
btVector3 aabbMin(-1,-1,-1),aabbMax(1,1,1);
btBvhTriangleMeshShape* trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,aabbMin,aabbMax);
btBvhTriangleMeshShape* trimeshShape2 = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,aabbMin,aabbMax);
//btCollisionShape* trimeshShape = new btBoxShape(btVector3(btScalar(1.),btScalar(1.),btScalar(1.)));
//btCollisionShape* trimeshShape2 = new btBoxShape(btVector3(btScalar(1.),btScalar(1.),btScalar(1.)));
collisionShapes.push_back(trimeshShape);
collisionShapes.push_back(trimeshShape2);
/// Create Dynamic Objects
btTransform startTransform;
btTransform startTransform2;
startTransform.setIdentity();
startTransform2.setIdentity();
btScalar mass(1.0f);
btScalar mass2(0.0f);
// Setting this for dynamic shapesss
btVector3 localInertia(0,0,0);
btVector3 localInertia2(0,0,0);
trimeshShape->calculateLocalInertia(mass,localInertia);
trimeshShape2->calculateLocalInertia(mass2,localInertia2);
startTransform.setOrigin(btVector3(0,10,0));
startTransform2.setOrigin(btVector3(0,0,0));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,trimeshShape,localInertia);
sc.mod[0].rigid = new btRigidBody(rbInfo);
dynamicsWorld->addRigidBody(sc.mod[0].rigid);
sc.mod[0].rigid->getAabb(aabbMin, aabbMax);
for(i = 0; i < 3; i++)
{
sc.mod[0].bounding_box.min[i] = aabbMin.m_floats[i];
sc.mod[0].bounding_box.max[i] = aabbMax.m_floats[i];
}
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState2 = new btDefaultMotionState(startTransform2);
btRigidBody::btRigidBodyConstructionInfo rbInfo2(mass2,myMotionState2,trimeshShape2,localInertia2);
sc.mod[1].rigid = new btRigidBody(rbInfo2);
dynamicsWorld->addRigidBody(sc.mod[1].rigid);
sc.mod[1].rigid->getAabb(aabbMin, aabbMax);
Code: Select all
dynamicsWorld->stepSimulation(1.f/60.f,10);
for(j = 0; j < dynamicsWorld->getNumCollisionObjects(); j++)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
btTransform trans;
body->getMotionState()->getWorldTransform(trans);
printf("world pos = %f,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()));
// Update AABB, copy for renderer
sc.mod[j].rigid->getAabb(aabbMin, aabbMax);
sc.mod[j].bounding_box.min[0] = aabbMin.m_floats[0];
sc.mod[j].bounding_box.min[1] = aabbMin.m_floats[1];
sc.mod[j].bounding_box.min[2] = aabbMin.m_floats[2];
sc.mod[j].bounding_box.max[0] = aabbMax.m_floats[0];
sc.mod[j].bounding_box.max[1] = aabbMax.m_floats[1];
sc.mod[j].bounding_box.max[2] = aabbMax.m_floats[2];
}
}
Cheers.