SXtheOne
28-05-2010 20:28:05
UPDATE: From now on this tutorial can be reached also from OgreBullet Wiki: http://www.ogre3d.org/wiki/index.php/OgreBullet
Hi!
This tutorial will guide you through the configuration of an OgreBullet project from configuring the components to creating the first simple demo which will have some collision detection.
My native language is not english so if you find grammatical errors, please post a comment. Thanks!
What you need:
- Ogre 1.65 (must be already configured)
- Bullet 2.76 (you can download from here: http://code.google.com/p/bullet/downloads/list)
- OgreBullet (I used rev. 2902, svn at the time of writing: https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/ogrebullet)
IDE what I used and will refer to:
- Visual Studio 2008 C++ Express SP1
Also good if you have:
- Ogre AppWizard (the basic project is generated with this. Wiki: http://www.ogre3d.org/wiki/index.php/The_Complete_Blanks_Guide_To_Using_The_OGRE_SDK_AppWizard)
Preparation:
- Unpack Bullet and fetch OgreBullet to a place in the hard drive.
- set an environment variable:
BULLET_HOME C:\OgreSDK\AddOns\bullet-2.76 (if this is were you unpacked bullet)
You can find the place in Windows XP following this path: open Control Panel (classic view) / System / Advanced / Environment Variables. Set it in the User Variables box.
- build Bullet in your IDE (I do it in VS2008 Express)
The project file for VS 2008 is here: ....\bullet-2.76\msvc\2008\BULLET_PHYSICS.sln
Build it in debug and release mode. It should compile without any problem.
- build OgreBullet also: ....\OgreBullet\OgreBullet_SDK.sln
VS2008 converted the project without any errors for me.
When you build the debug version of the demos you may have some errors about missing .lib files.
Put these files to ....\OgreBullet\lib\Debug\:
BulletCollision.lib, can be found here: ....\bullet-2.76\msvc\2008\src\BulletCollision\Debug\
BulletDynamics.lib, can be found here: ....\bullet-2.76\msvc\2008\src\BulletDynamics\Debug\
ConvexDecomposition.lib, can be found here: ....\bullet-2.76\msvc\2008\Extras\ConvexDecomposition\Debug\
GIMPACTUtils.lib, can be found here: ....\bullet-2.76\msvc\2008\Extras\GIMPACTUtils\Debug\
LinearMath.lib, can be found here:....\bullet-2.76\msvc\2008\src\LinearMath\Debug\
There may some files what we don't need now but later. For example BulletSoftBody.lib. If something is missing when you use more from Bullet, don't forget to copy it to the right place.
If you want to RUN the demos and it can't find resources.cfg don't wonder. This tutorial is not about these demos but I think you can solve it yourself. There are some problems with paths
If you want to build the release version of the demos (or any OgreBullet project!) you have to put the Bullet .lib files to the ....\OgreBullet\lib\Release folder.
But beware! You have to put the RELEASE version of Bullet .lib files to this dir, not the same files what were listed before.
Now we have the required files, let's close this project and start a new!
If you have Ogre Appwizard installed, create a new Ogre project:
New project – Ogre SDK Application – OgreBullet_Collision_test – Finish
I refer to the classes with the names what are generated from the project name. If you want to use another name, be careful with the different names.
If you don't have Appwizard just create a basic Ogre application what is able to create a window, fire up a FrameListener and able to handle keyboard/mouse input. From now on I refer to Appwizard basic project.
Before we start coding we need to do some configuration:
- Open Project\Properties (Alt+F7)
- Go to Configuration Properties\C/C++\General
- Find Additional Include Directories, open with '...' button
- Put $(BULLET_HOME)\src to the end of the list.
- Change the Configuration (in the top-left corner of the window) to Release and do the same here as well.
- Now go to Configuration Properties\Linker\Input
- Find Additional Dependencies
- Add required elements. In the end it should contain these:
OgreMain_d.lib OIS_d.lib OgreBulletCollisions_d.lib OgreBulletDynamics_d.lib bulletcollision.lib bulletdynamics.lib LinearMath.lib GIMPACTutils.lib ConvexDecomposition.lib
- Change the Configuration (in the top-left corner of the window) to Release and insert these to the same place as before:
OgreMain.lib OIS.lib OgreBulletCollisions.lib OgreBulletDynamics.lib bulletcollision.lib bulletdynamics.lib LinearMath.lib GIMPACTutils.lib ConvexDecomposition.lib
- Now close this window and go to Tools\Options\Projects and Solutions\VC++ Directories\
- Set Show directories for: Include files
- Put these into the list (your path to OgreBullet needed):
....\OgreBullet\Collisions\include
....\OgreBullet\Dynamics\include
Change to Library files and put these to the list:
....\OgreBullet\lib\Debug
....\OgreBullet\lib\Release
Build the project. It should be working
We won't change OgreBullet_Collision_test.cpp so you can close it if you want.
Open OgreBullet_Collision_test.h. From now on everything happens here.
You can split it to .h and .cpp file if you like. It's not a big program so I won't
Note: I won't use namespaces. It's because this way you can see what class contains what function.
The coding part starts here!
We need this header to be able to use OgreBullet:
Now change the constuctor of your basic program (insert two extra fields):
The gravityVector defines the gravity in our example and I thought that the bounds defines the bounds where Bullet is active. But it seems that it has no effect. Anyway we need it
Find createFrameListener(void) function and change the call of the previously modified function:
Now we have our frameListener as before but with the new parameters included.
Maybe try to run it. Nothing changed yet. So, define these variables in the OgreBullet_Collision_testFrameListener class:
mWorld will be the main variable for OgreBullet (like mRoot for Ogre).
debugDrawer will be explained soon.
mBodies and mShapes will handle the Bullet shapes and bodies. We need them to be able to free the memory and therefore get rid of memory leaks.
Let's set up the basics of OgreBullet. Go to OgreBullet_Collision_testFrameListener constructor and paste these:
mMoveSpeed is declared in ExampleFrameListener.h and is responsible for the maximum speed of the camera movement.
mNumEntitiesInstanced is a counter what we use when we create objects dynamically (we can't have two object using the same name).
mSceneMgr is the Ogre Scene Manager.
mWorld is the OgreBullet main variable.
debugDrawer will be used to show graphical debug information about OgreBullet. We use the setDrawWireframe(true) function to set the bounding Box/Sphere/etc. what Bullet uses for collisions visible. Turn is off if you don't want to see but it's very good for debuging.
Debugdrawer needs Ogre to be able to draw to the screen. That's why we create a node for it.
Of course we need to delete the variables/deques in the destructor:
Set the position of the camera. Find createCamera(void) and change the setPosition to this:
Let's create the scene. Go to OgreBullet_Collision_testApp class and find the createScene(void) function. Delete the rows which defines the default OgreHead (these were the first three row in my code).
We won't create the scene here because this function is called before the frameListener. I don't want to change the ExampleApplication.h file so let's go back to OgreBullet_Collision_testFrameListener constructor and insert this code after the last row.
First, create the floor:
If you run the program now, you can see an endless (at least it seems endless) plane with texture. Let's add collision detection to it!
Try to run it and you can see there are some errors. We need a header to be included:
Now the plane is detecting collisions! But how to test it when the camera is going through it? Let's create some boxes and throw them into the scene!
This header is needed to be able to create a box...:
...and we need boxes. Let's redefine the processUnbufferedKeyInput() function. Originally it is defined in the ExampleFrameListener. I won't start to explain it, so if you didn't already know this start reading the Ogre basic tutorials
The code is well commented here so I won't explain everything in detail. If you press the 'B' key a box will be created.
The box is created in several phase like the plane before. First we create the Ogre-box by loading a mesh. This is needed to be able to see the actual box with texture.
After this we create the shape for Bullet what is a BoxCollisionShape this time. This means that we want a box-shaped collision object.
When this is ready we arrived to the last step. We need a RigidBody and we use the setShape() function to bind together the box the shape and the RigidBody.
The size variable is self-explanatory but it is good to know that getBoundingBox() will give us the smallest box what can be drawn around the object (in our case the cube).
When you run this demo and push the 'B' key, you can see the created box floating in the air. That's not what we want.
So, the last step is to make the box move. We need to override the frameStarted() and frameEnded() functions. Here they are:
The only needed function to make Bullet functional is the stepSimulation().
That's it. You can throw boxes!
I hope this tutorial was helpful. If it was or if you found grammatical/coding error please post a comment!
Thanks for reading and have a nice day!
Hi!
This tutorial will guide you through the configuration of an OgreBullet project from configuring the components to creating the first simple demo which will have some collision detection.
My native language is not english so if you find grammatical errors, please post a comment. Thanks!
What you need:
- Ogre 1.65 (must be already configured)
- Bullet 2.76 (you can download from here: http://code.google.com/p/bullet/downloads/list)
- OgreBullet (I used rev. 2902, svn at the time of writing: https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/ogrebullet)
IDE what I used and will refer to:
- Visual Studio 2008 C++ Express SP1
Also good if you have:
- Ogre AppWizard (the basic project is generated with this. Wiki: http://www.ogre3d.org/wiki/index.php/The_Complete_Blanks_Guide_To_Using_The_OGRE_SDK_AppWizard)
Preparation:
- Unpack Bullet and fetch OgreBullet to a place in the hard drive.
- set an environment variable:
BULLET_HOME C:\OgreSDK\AddOns\bullet-2.76 (if this is were you unpacked bullet)
You can find the place in Windows XP following this path: open Control Panel (classic view) / System / Advanced / Environment Variables. Set it in the User Variables box.
- build Bullet in your IDE (I do it in VS2008 Express)
The project file for VS 2008 is here: ....\bullet-2.76\msvc\2008\BULLET_PHYSICS.sln
Build it in debug and release mode. It should compile without any problem.
- build OgreBullet also: ....\OgreBullet\OgreBullet_SDK.sln
VS2008 converted the project without any errors for me.
When you build the debug version of the demos you may have some errors about missing .lib files.
Put these files to ....\OgreBullet\lib\Debug\:
BulletCollision.lib, can be found here: ....\bullet-2.76\msvc\2008\src\BulletCollision\Debug\
BulletDynamics.lib, can be found here: ....\bullet-2.76\msvc\2008\src\BulletDynamics\Debug\
ConvexDecomposition.lib, can be found here: ....\bullet-2.76\msvc\2008\Extras\ConvexDecomposition\Debug\
GIMPACTUtils.lib, can be found here: ....\bullet-2.76\msvc\2008\Extras\GIMPACTUtils\Debug\
LinearMath.lib, can be found here:....\bullet-2.76\msvc\2008\src\LinearMath\Debug\
There may some files what we don't need now but later. For example BulletSoftBody.lib. If something is missing when you use more from Bullet, don't forget to copy it to the right place.
If you want to RUN the demos and it can't find resources.cfg don't wonder. This tutorial is not about these demos but I think you can solve it yourself. There are some problems with paths
If you want to build the release version of the demos (or any OgreBullet project!) you have to put the Bullet .lib files to the ....\OgreBullet\lib\Release folder.
But beware! You have to put the RELEASE version of Bullet .lib files to this dir, not the same files what were listed before.
Now we have the required files, let's close this project and start a new!
If you have Ogre Appwizard installed, create a new Ogre project:
New project – Ogre SDK Application – OgreBullet_Collision_test – Finish
I refer to the classes with the names what are generated from the project name. If you want to use another name, be careful with the different names.
If you don't have Appwizard just create a basic Ogre application what is able to create a window, fire up a FrameListener and able to handle keyboard/mouse input. From now on I refer to Appwizard basic project.
Before we start coding we need to do some configuration:
- Open Project\Properties (Alt+F7)
- Go to Configuration Properties\C/C++\General
- Find Additional Include Directories, open with '...' button
- Put $(BULLET_HOME)\src to the end of the list.
- Change the Configuration (in the top-left corner of the window) to Release and do the same here as well.
- Now go to Configuration Properties\Linker\Input
- Find Additional Dependencies
- Add required elements. In the end it should contain these:
OgreMain_d.lib OIS_d.lib OgreBulletCollisions_d.lib OgreBulletDynamics_d.lib bulletcollision.lib bulletdynamics.lib LinearMath.lib GIMPACTutils.lib ConvexDecomposition.lib
- Change the Configuration (in the top-left corner of the window) to Release and insert these to the same place as before:
OgreMain.lib OIS.lib OgreBulletCollisions.lib OgreBulletDynamics.lib bulletcollision.lib bulletdynamics.lib LinearMath.lib GIMPACTutils.lib ConvexDecomposition.lib
- Now close this window and go to Tools\Options\Projects and Solutions\VC++ Directories\
- Set Show directories for: Include files
- Put these into the list (your path to OgreBullet needed):
....\OgreBullet\Collisions\include
....\OgreBullet\Dynamics\include
Change to Library files and put these to the list:
....\OgreBullet\lib\Debug
....\OgreBullet\lib\Release
Build the project. It should be working
We won't change OgreBullet_Collision_test.cpp so you can close it if you want.
Open OgreBullet_Collision_test.h. From now on everything happens here.
You can split it to .h and .cpp file if you like. It's not a big program so I won't
Note: I won't use namespaces. It's because this way you can see what class contains what function.
The coding part starts here!
We need this header to be able to use OgreBullet:
#include "OgreBulletDynamicsRigidBody.h"
Now change the constuctor of your basic program (insert two extra fields):
OgreBullet_Collision_testFrameListener(
SceneManager *sceneMgr,
RenderWindow* win,
Camera* cam,
Vector3 &gravityVector,
AxisAlignedBox &bounds)
: ExampleFrameListener(win, cam),
mSceneMgr(sceneMgr)
The gravityVector defines the gravity in our example and I thought that the bounds defines the bounds where Bullet is active. But it seems that it has no effect. Anyway we need it
Find createFrameListener(void) function and change the call of the previously modified function:
void createFrameListener(void)
{
mFrameListener= new OgreBullet_Collision_testFrameListener( mSceneMgr,
mWindow,
mCamera,
Vector3(0,-9.81,0), // gravity vector for Bullet
AxisAlignedBox (Ogre::Vector3 (-10000, -10000, -10000), //aligned box for Bullet
Ogre::Vector3 (10000, 10000, 10000)));
mRoot->addFrameListener(mFrameListener);
}
Now we have our frameListener as before but with the new parameters included.
Maybe try to run it. Nothing changed yet. So, define these variables in the OgreBullet_Collision_testFrameListener class:
class OgreBullet_CollisiontestFrameListener : public ExampleFrameListener
{
private:
SceneManager* mSceneMgr;
OgreBulletDynamics::DynamicsWorld *mWorld; // OgreBullet World
OgreBulletCollisions::DebugDrawer *debugDrawer;
int mNumEntitiesInstanced;
std::deque<OgreBulletDynamics::RigidBody *> mBodies;
std::deque<OgreBulletCollisions::CollisionShape *> mShapes;
mWorld will be the main variable for OgreBullet (like mRoot for Ogre).
debugDrawer will be explained soon.
mBodies and mShapes will handle the Bullet shapes and bodies. We need them to be able to free the memory and therefore get rid of memory leaks.
Let's set up the basics of OgreBullet. Go to OgreBullet_Collision_testFrameListener constructor and paste these:
mMoveSpeed = 50; // defined in ExampleFrameListener
mNumEntitiesInstanced = 0; // how many shapes are created
mSceneMgr = sceneMgr;
// Start Bullet
mWorld = new OgreBulletDynamics::DynamicsWorld(mSceneMgr, bounds, gravityVector);
// add Debug info display tool
debugDrawer = new OgreBulletCollisions::DebugDrawer();
debugDrawer->setDrawWireframe(true); // we want to see the Bullet containers
mWorld->setDebugDrawer(debugDrawer);
mWorld->setShowDebugShapes(true); // enable it if you want to see the Bullet containers
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("debugDrawer", Ogre::Vector3::ZERO);
node->attachObject(static_cast <SimpleRenderable *> (debugDrawer));
mMoveSpeed is declared in ExampleFrameListener.h and is responsible for the maximum speed of the camera movement.
mNumEntitiesInstanced is a counter what we use when we create objects dynamically (we can't have two object using the same name).
mSceneMgr is the Ogre Scene Manager.
mWorld is the OgreBullet main variable.
debugDrawer will be used to show graphical debug information about OgreBullet. We use the setDrawWireframe(true) function to set the bounding Box/Sphere/etc. what Bullet uses for collisions visible. Turn is off if you don't want to see but it's very good for debuging.
Debugdrawer needs Ogre to be able to draw to the screen. That's why we create a node for it.
Of course we need to delete the variables/deques in the destructor:
~OgreBullet_Collision_testFrameListener(){
// OgreBullet physic delete - RigidBodies
std::deque<OgreBulletDynamics::RigidBody *>::iterator itBody = mBodies.begin();
while (mBodies.end() != itBody)
{
delete *itBody;
++itBody;
}
// OgreBullet physic delete - Shapes
std::deque<OgreBulletCollisions::CollisionShape *>::iterator itShape = mShapes.begin();
while (mShapes.end() != itShape)
{
delete *itShape;
++itShape;
}
mBodies.clear();
mShapes.clear();
delete mWorld->getDebugDrawer();
mWorld->setDebugDrawer(0);
delete mWorld;
}
Set the position of the camera. Find createCamera(void) and change the setPosition to this:
mCamera->setPosition(Vector3(0,18,70));
Let's create the scene. Go to OgreBullet_Collision_testApp class and find the createScene(void) function. Delete the rows which defines the default OgreHead (these were the first three row in my code).
We won't create the scene here because this function is called before the frameListener. I don't want to change the ExampleApplication.h file so let's go back to OgreBullet_Collision_testFrameListener constructor and insert this code after the last row.
First, create the floor:
// Define a floor plane mesh
Entity *ent;
Plane p;
p.normal = Vector3(0,1,0); p.d = 0;
MeshManager::getSingleton().createPlane(
"FloorPlane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
p, 200000, 200000, 20, 20, true, 1, 9000, 9000, Vector3::UNIT_Z);
// Create an entity (the floor)
ent = mSceneMgr->createEntity("floor", "FloorPlane");
ent->setMaterialName("Examples/BumpyMetal");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
If you run the program now, you can see an endless (at least it seems endless) plane with texture. Let's add collision detection to it!
OgreBulletCollisions::CollisionShape *Shape;
Shape = new OgreBulletCollisions::StaticPlaneCollisionShape(Ogre::Vector3(0,1,0), 0); // (normal vector, distance)
OgreBulletDynamics::RigidBody *defaultPlaneBody = new OgreBulletDynamics::RigidBody(
"BasePlane",
mWorld);
defaultPlaneBody->setStaticShape(Shape, 0.1, 0.8); // (shape, restitution, friction)
// push the created objects to the deques
mShapes.push_back(Shape);
mBodies.push_back(defaultPlaneBody);
Try to run it and you can see there are some errors. We need a header to be included:
#include "Shapes/OgreBulletCollisionsStaticPlaneShape.h" // for static planes
Now the plane is detecting collisions! But how to test it when the camera is going through it? Let's create some boxes and throw them into the scene!
This header is needed to be able to create a box...:
#include "Shapes/OgreBulletCollisionsBoxShape.h" // for Boxes
...and we need boxes. Let's redefine the processUnbufferedKeyInput() function. Originally it is defined in the ExampleFrameListener. I won't start to explain it, so if you didn't already know this start reading the Ogre basic tutorials
bool processUnbufferedKeyInput(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::processUnbufferedKeyInput(evt);
// create and throw a box if 'B' is pressed
if(mKeyboard->isKeyDown(OIS::KC_B) && mTimeUntilNextToggle <=0)
{
Vector3 size = Vector3::ZERO; // size of the box
// starting position of the box
Vector3 position = (mCamera->getDerivedPosition() + mCamera->getDerivedDirection().normalisedCopy() * 10);
// create an ordinary, Ogre mesh with texture
Entity *entity = mSceneMgr->createEntity(
"Box" + StringConverter::toString(mNumEntitiesInstanced),
"cube.mesh");
entity->setCastShadows(true);
// we need the bounding box of the box to be able to set the size of the Bullet-box
AxisAlignedBox boundingB = entity->getBoundingBox();
size = boundingB.getSize(); size /= 2.0f; // only the half needed
size *= 0.96f; // Bullet margin is a bit bigger so we need a smaller size
// (Bullet 2.76 Physics SDK Manual page 18)
entity->setMaterialName("Examples/BumpyMetal");
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(entity);
node->scale(0.05f, 0.05f, 0.05f); // the cube is too big for us
size *= 0.05f; // don't forget to scale down the Bullet-box too
// after that create the Bullet shape with the calculated size
OgreBulletCollisions::BoxCollisionShape *sceneBoxShape = new OgreBulletCollisions::BoxCollisionShape(size);
// and the Bullet rigid body
OgreBulletDynamics::RigidBody *defaultBody = new OgreBulletDynamics::RigidBody(
"defaultBoxRigid" + StringConverter::toString(mNumEntitiesInstanced),
mWorld);
defaultBody->setShape( node,
sceneBoxShape,
0.6f, // dynamic body restitution
0.6f, // dynamic body friction
1.0f, // dynamic bodymass
position, // starting position of the box
Quaternion(0,0,0,1));// orientation of the box
mNumEntitiesInstanced++;
defaultBody->setLinearVelocity(
mCamera->getDerivedDirection().normalisedCopy() * 7.0f ); // shooting speed
// push the created objects to the deques
mShapes.push_back(sceneBoxShape);
mBodies.push_back(defaultBody);
mTimeUntilNextToggle = 0.5;
}
return ret;
}
The code is well commented here so I won't explain everything in detail. If you press the 'B' key a box will be created.
The box is created in several phase like the plane before. First we create the Ogre-box by loading a mesh. This is needed to be able to see the actual box with texture.
After this we create the shape for Bullet what is a BoxCollisionShape this time. This means that we want a box-shaped collision object.
When this is ready we arrived to the last step. We need a RigidBody and we use the setShape() function to bind together the box the shape and the RigidBody.
The size variable is self-explanatory but it is good to know that getBoundingBox() will give us the smallest box what can be drawn around the object (in our case the cube).
When you run this demo and push the 'B' key, you can see the created box floating in the air. That's not what we want.
So, the last step is to make the box move. We need to override the frameStarted() and frameEnded() functions. Here they are:
bool frameStarted(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::frameStarted(evt);
mWorld->stepSimulation(evt.timeSinceLastFrame); // update Bullet Physics animation
return ret;
}
bool frameEnded(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::frameEnded(evt);
mWorld->stepSimulation(evt.timeSinceLastFrame); // update Bullet Physics animation
return ret;
}
The only needed function to make Bullet functional is the stepSimulation().
That's it. You can throw boxes!
I hope this tutorial was helpful. If it was or if you found grammatical/coding error please post a comment!
Thanks for reading and have a nice day!