I am currently working on working with collision detection in terrain. The terrain that I am using is coming from a .scene format. I am using Bullet for a physics library, but do not wish to use OgreBullet, as it seems to be dead. My current approach is to do the following:
First, get the location of the entity with entity->getPosition(). This vector is then used to get the height of the terrain at the position with terrain->getHeightAtWorldPosition(position). The terrain is coming from when I am loading the .scene file and getting the terrain at the position from the TerrainGroup that comes with loading the .scene file. I then plan to create a plane or something similar in bullet and then proceed with the normal way of doing physics with the physics engine.
However, this seems overly complicated, as it would be just as easy to do all the collisions with a RaySceneQuery at this point. It also seems like this technique would have some issues with uneven terrain. I also plan to manage collision detection for .bsp maps as well at some point, meaning I would have to redesign this for that type of map, which isn't managed by the whole terrain system as far as I know.
Anyone have any suggestions or alternate ways I could do this? I would like to integrate bullet as it seems to be a fairly reliable physics engine, although I plan to rewrite parts of it or write my own physics engine at some point. I also plan to allow different map types in my final game, so I would like to make the technique as flexible as possible for the map type.
EDIT: I have now thought of somehow processing the entire terrain into an object in bullet during the loading of the scene, and hopefully the broadphase in bullet will stop unnecessary computation. Does anyone have any comments on this technique or suggestions of how to do it (I know how to get the height at a specific point, but not much else)?
Collision Physics with Terrain
-
dunderwood
- Gnoblar
- Posts: 7
- Joined: Mon Feb 10, 2014 11:50 pm
- Location: Raleigh, NC
- Herb
- Orc
- Posts: 412
- Joined: Thu Jun 04, 2009 3:21 am
- Location: Kalamazoo,MI
- x 38
Re: Collision Physics with Terrain
Yeah, I would agree on OgreBullet. Take a look at BtOgre It's a really thin wrapper on Bullet, really just providing some helper methods on type conversions and such. As for terrain, here are some snippets on a game I was developing that might help. I scratched my head for a bit till I worked out the terrain integration too.
Okay, in my main game state start-up, here is my physics (btOgre setup). Notice I'm using a DotSceneLoader too.
Here is that createHeightfieldShape method reference in the above method
Then in the my active game state's frameStarted method (tied to the OgreFrameListener), I do:
Hope that helps and gives you a starting point at least! 
Okay, in my main game state start-up, here is my physics (btOgre setup). Notice I'm using a DotSceneLoader too.
Code: Select all
// setup Physics engine
/// @todo have no idea if this is the right configuration....what configuration would be better?
mBroadphase = new btDbvtBroadphase();
mCollisionConfig = new btDefaultCollisionConfiguration();
mDispatcher = new btCollisionDispatcher(mCollisionConfig);
mSolver = new btSequentialImpulseConstraintSolver();
mPhyWorld = new btDiscreteDynamicsWorld(mDispatcher, mBroadphase, mSolver, mCollisionConfig);
/// @todo what is the best gravity? Using setting from the demo
mPhyWorld->setGravity(btVector3(0,-9.8,0)); // hmm... another demo has y being 100...
mPhyDebugDraw = new BtOgre::DebugDrawer(mSceneMgr->getRootSceneNode(), mPhyWorld);
mPhyWorld->setDebugDrawer(mPhyDebugDraw);
// load all the height data (each terrain page) as a static mesh for bullet to create as a static geometry mesh
Ogre::TerrainGroup* group = mDotSceneLoader->getTerrainGroup();
Ogre::TerrainGroup::TerrainIterator terrainIterator = mDotSceneLoader->getTerrainGroup()->getTerrainIterator();
while(terrainIterator.hasMoreElements())
{
Ogre::Terrain* terrain = terrainIterator.getNext()->instance;
createHeightfieldShape(terrain->getSize(),
terrain->getHeightData(),
terrain->getMinHeight(),
terrain->getMaxHeight(),
terrain->getPosition(),
terrain->getWorldSize()/(terrain->getSize()-1)
);
}
Code: Select all
void ActiveGameState::createHeightfieldShape(int size, float* data, const Ogre::Real& minHeight, const Ogre::Real& maxHeight, const Ogre::Vector3& position, const Ogre::Real& scale)
{
// Convert height data in a format suitable for the physics engine
float *terrainHeights = new float[size * size];
assert(terrainHeights != 0);
for (int i = 0; i < size; i++)
{
memcpy(terrainHeights + size * i, data + size * (size - i - 1), sizeof(float) * size);
}
btScalar heightScale = 1.f;
btVector3 localScaling(scale, heightScale, scale);
btHeightfieldTerrainShape *terrainShape = new btHeightfieldTerrainShape(size, size, terrainHeights, 1/*ignore*/, minHeight, maxHeight, 1, PHY_FLOAT, true);
terrainShape->setUseDiamondSubdivision(true);
terrainShape->setLocalScaling(localScaling);
//Create Rigid Body using 0 mass so it is static
btRigidBody *body = new btRigidBody(BT_LARGE_FLOAT, new btDefaultMotionState(), terrainShape);
body->setFriction(0.8f);
body->setHitFraction(0.8f);
body->setRestitution(0.6f);
body->getWorldTransform().setOrigin(btVector3(position.x, position.y + (maxHeight - minHeight) / 2, position.z));
body->getWorldTransform().setRotation(BtOgre::Convert::toBullet(Ogre::Quaternion::IDENTITY));
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
mPhyWorld->addRigidBody(body);
}
Code: Select all
//Update Bullet world
mPhyWorld->stepSimulation(evt.timeSinceLastFrame);
mPhyWorld->debugDrawWorld();
//Shows debug if F3 key down.
mPhyDebugDraw->setDebugMode(mInputMgr->getKeyboard()->isKeyDown(OIS::KC_F3));
mPhyDebugDraw->step();
-
dunderwood
- Gnoblar
- Posts: 7
- Joined: Mon Feb 10, 2014 11:50 pm
- Location: Raleigh, NC
Re: Collision Physics with Terrain
Thanks! I haven't gotten to poke around the code much yet, but hopefully I will later today, and it looks like it will help at least a bit. I looked up BtOgre, and the latest commit was about a year ago. What version of Ogre and Bullet have you used it with? Additionally, at first glance of that code, there isn't anything that is using btOgre. Is that correct? EDIT: Nevermind, just saw mPhyDebugDraw.
Also, I don't know how recent this code is, but in the first code snippet where you set the gravity and there's a comment about another demo being 100, typical gravity is the -9.8 if you are scaling the game world to the real world. The 100 would be if you were using some soft of weird scaling system. In addition, if the value was actually positive 100, the other demo either had the y-axis reversed or was using some sort of weird constant system for the gravity. I hope this may have helped you with that point if you were still wondering about that bit.
EDIT: I'm messing with the code a bit now. It was working fine, until I got to linking with BtOgre, where I get the following errors:
BtOgre itself was built fine, so I'm assuming that it's linking to Bullet successtully. I've looked through the source for bullet and the constructors with the given overloads are still there. I've even tried including the headers for the individual shapes.
Any suggestions?
EDIT 2: I was able to fix the referencing problem by just integrating BtOgre's source into the code for my project. It would be nice to know what was going on there, though.
EDIT 3: Is there any effect on your FPS when you press F3 for the debug draw? Mine is dropping from about 900 to less than 1.
Also, I don't know how recent this code is, but in the first code snippet where you set the gravity and there's a comment about another demo being 100, typical gravity is the -9.8 if you are scaling the game world to the real world. The 100 would be if you were using some soft of weird scaling system. In addition, if the value was actually positive 100, the other demo either had the y-axis reversed or was using some sort of weird constant system for the gravity. I hope this may have helped you with that point if you were still wondering about that bit.
EDIT: I'm messing with the code a bit now. It was working fine, until I got to linking with BtOgre, where I get the following errors:
Code: Select all
/home/danielunderwood/Documents/btOgreBuilds/03102014/libBtOgre.a(BtOgre.cpp.o): In function `BtOgre::VertexIndexToShape::createBox()':
BtOgre.cpp:(.text+0x1291): undefined reference to `btBoxShape::btBoxShape(btVector3 const&)'
/home/danielunderwood/Documents/btOgreBuilds/03102014/libBtOgre.a(BtOgre.cpp.o): In function `BtOgre::VertexIndexToShape::createCylinder()':
BtOgre.cpp:(.text+0x13ff): undefined reference to `btCylinderShapeX::btCylinderShapeX(btVector3 const&)'
/home/danielunderwood/Documents/btOgreBuilds/03102014/libBtOgre.a(BtOgre.cpp.o): In function `BtOgre::VertexIndexToShape::createConvex()':
BtOgre.cpp:(.text+0x14e0): undefined reference to `btConvexHullShape::btConvexHullShape(float const*, int, int)'
/home/danielunderwood/Documents/btOgreBuilds/03102014/libBtOgre.a(BtOgre.cpp.o): In function `BtOgre::VertexIndexToShape::createTrimesh()':
BtOgre.cpp:(.text+0x15df): undefined reference to `btTriangleMesh::btTriangleMesh(bool, bool)'
BtOgre.cpp:(.text+0x17d1): undefined reference to `btTriangleMesh::addTriangle(btVector3 const&, btVector3 const&, btVector3 const&, bool)'
/home/danielunderwood/Documents/btOgreBuilds/03102014/libBtOgre.a(BtOgre.cpp.o): In function `BtOgre::VertexIndexToShape::createCapsule()':
BtOgre.cpp:(.text+0x19cf): undefined reference to `btCapsuleShape::btCapsuleShape(float, float)'
BtOgre.cpp:(.text+0x1a40): undefined reference to `btCapsuleShapeX::btCapsuleShapeX(float, float)'
BtOgre.cpp:(.text+0x1a99): undefined reference to `btCapsuleShapeZ::btCapsuleShapeZ(float, float)'
/home/danielunderwood/Documents/btOgreBuilds/03102014/libBtOgre.a(BtOgre.cpp.o): In function `BtOgre::AnimatedMeshToShapeConverter::createAlignedBox(unsigned char, Ogre::Vector3 const&, Ogre::Quaternion const&)':
BtOgre.cpp:(.text+0x2e49): undefined reference to `btBoxShape::btBoxShape(btVector3 const&)'
/home/danielunderwood/Documents/btOgreBuilds/03102014/libBtOgre.a(BtOgre.cpp.o): In function `BtOgre::AnimatedMeshToShapeConverter::createOrientedBox(unsigned char, Ogre::Vector3 const&, Ogre::Quaternion const&)':
BtOgre.cpp:(.text+0x355f): undefined reference to `btBoxShape::btBoxShape(btVector3 const&)'
Any suggestions?
EDIT 2: I was able to fix the referencing problem by just integrating BtOgre's source into the code for my project. It would be nice to know what was going on there, though.
EDIT 3: Is there any effect on your FPS when you press F3 for the debug draw? Mine is dropping from about 900 to less than 1.
- Herb
- Orc
- Posts: 412
- Joined: Thu Jun 04, 2009 3:21 am
- Location: Kalamazoo,MI
- x 38
Re: Collision Physics with Terrain
Yeah, I never did much testing on the setup of Bullet (ie what gravity and such to set). It really was me trying to get all the terrain data loaded into Bullet, which works. As for the debug draw, it is a huge FPS penalty if you have a lot of terrain. It's because it creates manual objects to render to show all the terrain that Bullet is keeping track of. I think my test map had 4 terrain pages that were not that big and had limited vertex counts, so it wasn't as bad as you're seeing... If you're terrain is huge, you might need to modify how the debug draw is happening if you want to still see it. It's not really that complicated. Glad this helped you get going with Bullet. 