Académique Documents
Professionnel Documents
Culture Documents
Search:
We set the namespace for our Irrlicht library. You can also set the namespace for its 5 subnamespaces, but for this tutorial they are not set to show which stuff
Go belongs to which namespace.
// Functions
//For now, there's not much here. Just add them in as we create them
static int GetRandInt(int TMax) { return rand() % TMax; }
// Globals
//For now, there's not much here. Just add them in as we create them
static IrrlichtDevice *irrDevice;
static video::IVideoDriver *irrDriver;
static scene::ISceneManager *irrScene;
static gui::IGUIEnvironment* irrGUI;
static io::IFileSystem *irrFile;
static ITimer *irrTimer;
static ILogger *irrLog;
int main()
{
irrDevice = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(640, 480), 32, false, false, false, 0);
if (irrDevice == 0)
return 1; // could not create selected driver.
irrGUI = irrDevice->getGUIEnvironment();
irrTimer = irrDevice->getTimer();
irrDriver = irrDevice->getVideoDriver();
irrScene = irrDevice->getSceneManager();
//Add an FPS camera move it up and back and point it at the origin
scene::ICameraSceneNode *Camera = irrScene->addCameraSceneNodeFPS(0, 100, 10);
Camera->setPosition(core::vector3df(0, 5, -5));
Camera->setTarget(core::vector3df(0, 0, 0));
while(irrDevice->run())
{
if (irrDevice->isWindowActive())
{
irrDriver->beginScene(true, true, video::SColor(255,200,200,200));
irrScene->drawAll();
irrDriver->endScene();
}
else
irrDevice->yield();
}
Adding Bullet
http://www.irrlicht3d.org/wiki/index.php?n=Main.GettingStartedWithBullet 8/12/2017
Irrlicht Engine wiki - Getting Started With Bullet Page 2 of 7
At this point, there are no objects in our world yet so you won't be able to see anything. Let's start adding in some rigid bodies so we can finally start seeing some
Bullet action.
First we initialize Bullet. Before we can create btDiscreteDynamicsWorld, we must choose a broadphase algorithm to use, a collision configuration, and a constraint
solver. To learn more about these, check out the Hello World Tutorial at the Bullet Wiki.
Add the following global variables. The first variable is our "physical world", and the second one will hold all of our objects in it.
Now place the following code after you declare the irrGui, irrDriver, irrScene, etc.
// Initialize bullet
btBroadphaseInterface *BroadPhase = new btAxisSweep3(btVector3(-1000, -1000, -1000), btVector3(1000, 1000, 1000));
btDefaultCollisionConfiguration *CollisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher *Dispatcher = new btCollisionDispatcher(CollisionConfiguration);
btSequentialImpulseConstraintSolver *Solver = new btSequentialImpulseConstraintSolver();
World = new btDiscreteDynamicsWorld(Dispatcher, BroadPhase, Solver, CollisionConfiguration);
Creating Objects
Now we're going to create two functions: 1 for creating a box shape and another for creating a sphere. Both will be rigid bodies so they could interact using Bullet For
each of the two functions, we'll start of by creating an object in Irrlicht (that's what gets rendered), and then we set the position of the object in a way for Bullet to
figure out where it's at. We'll then give it a MotionState and describe to Bullet what that object is shaped like, give it some mass, and with all of those parameters,
Bullet can figure out how to create that rigid body in space.
// Add mass
btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass, LocalInertia);
// Add mass
btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass, LocalInertia);
You can grab the texture files from Jacky_J's post , or you could supply your own textures.
http://www.irrlicht3d.org/wiki/index.php?n=Main.GettingStartedWithBullet 8/12/2017
Irrlicht Engine wiki - Getting Started With Bullet Page 3 of 7
We're also going to need to create a function that creates the "ground" which our objects can interact with. The ground will basically be a large box we'll create with
our createBox function
ClearObjects();
CreateBox(btVector3(0.0f, 0.0f, 0.0f), core::vector3df(10.0f, 0.5f, 10.0f), 0.0f);
}
Don't forget to add their function declarations at the top of your code
// Event receiver
class EventReceiverClass : public IEventReceiver {
public:
return true;
}
return false;
}
};
For our Irrlicht engine to take note of these events, we have to instantiate this receiver and pass it along to our IrrlichtDevice. We're also going to have to change how
we create our IrrlichtDevice. Look for the line where we create our IrrlichtDevice, instantiate our receiver class and pass it in the createDevice function.
Notice that when we hit the Escape key, our receiver class sets a variable "Done" to true. We'll declare this variable with our other global variables.
We'll also modify our main loop so that when Done is true, our program will terminate.
Physics Simulation
Now that we have our objects set up, we need to actually start applying the physics calculations like gravity and collisions to our objects. Bullet does this by
"stepping" the simulation. A step is basically a discrete period of time and for each step, Bullet calculates how high or how fast an object falls, or how much a collision
throws back an object since the last frame.
So what we have to do is before we call on Irrlicht to draw our objects onto the screen, we first have to call on Bullet to give us the updated position of each of our
objects. For this, we create a new function called updatePhysics.
btRigidBody *TObject;
// Relay the object's orientation to irrlicht
for(core::list<btRigidBody *>::Iterator it = Objects.begin(); it != Objects.end(); ++it) {
//UpdateRender(*Iterator);
scene::ISceneNode *Node = static_cast<scene::ISceneNode *>((*it)->getUserPointer());
TObject = *it;
// Set position
http://www.irrlicht3d.org/wiki/index.php?n=Main.GettingStartedWithBullet 8/12/2017
Irrlicht Engine wiki - Getting Started With Bullet Page 4 of 7
// Set rotation
btVector3 EulerRotation;
QuaternionToEuler(TObject->getOrientation(), EulerRotation);
Node->setRotation(core::vector3df(EulerRotation[0], EulerRotation[1], EulerRotation[2]));
}
}
We then update our program's main loop to calculate the delta (the time since the last screen render), update the physics, and then render everything on screen. Our
main loop should now look something like this.
UpdatePhysics(DeltaTime);
if (lastFPS != fps)
{
core::stringw str = L"Irrlicht Engine - Quake 3 Map example [";
str += irrDriver->getName();
str += "] FPS:";
str += fps;
irrDevice->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
else
irrDevice->yield();
}
Finishing Up
You can preload the textures you'll be using by getting the textures beforehand in your main(), before going into your main program loop.
// Preload textures
irrDriver->getTexture("ice0.jpg");
irrDriver->getTexture("rust0.jpg");
As an added touch, we're going to add some GUI text on the upper-left corner of our screen explaining what keys the player can press.
// Create text
gui::IGUISkin* Skin = irrGUI->getSkin();
Skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255));
irrGUI->addStaticText(L"Hit 1 to create a box\nHit 2 to create a sphere\nHit x to reset", core::rect<s32>(0, 0, 200, 100), false);
And finally, before our main loop we put in some final bits of code to initialize our scene.
Other Notes
If you find a problem in this tutorial, contact me via punong_bisyonaryo _at_ yahoo_dot_com or at http://www.jplui.com/contact.php
To Compile on Linux
g++ example.cpp -o example -lIrrlicht -lGL -lGLU -lXrandr -lXext -lX11 `pkg-config --libs --cflags bullet`
http://www.irrlicht3d.org/wiki/index.php?n=Main.GettingStartedWithBullet 8/12/2017
Irrlicht Engine wiki - Getting Started With Bullet Page 5 of 7
//***************************************************************
// Bullet/irrlicht demo by Alan Witkowski
// http://www.cs.utah.edu/~witkowsk
// http://code.google.com/p/irrlamb/
//***************************************************************
#include <irrlicht.h>
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <cstdlib>
// Functions
static void CreateStartScene();
static void CreateBox(const btVector3 &TPosition, const vector3df &TScale, btScalar TMass);
static void CreateSphere(const btVector3 &TPosition, btScalar TRadius, btScalar TMass);
static void UpdatePhysics(u32 TDeltaTime);
static void UpdateRender(btRigidBody *TObject);
static void ClearObjects();
static int GetRandInt(int TMax) { return rand() % TMax; }
// Globals
static bool Done = false;
static btDiscreteDynamicsWorld *World;
static IrrlichtDevice *irrDevice;
static IVideoDriver *irrDriver;
static ISceneManager *irrScene;
static IGUIEnvironment *irrGUI;
static IFileSystem *irrFile;
static ITimer *irrTimer;
static ILogger *irrLog;
static list<btRigidBody *> Objects;
// Event receiver
class EventReceiverClass : public IEventReceiver {
public:
return true;
}
return false;
}
};
int main() {
// Initialize irrlicht
EventReceiverClass Receiver;
irrDevice = createDevice(video::EDT_OPENGL, dimension2d<u32>(800, 600), 32, false, false, false, &Receiver);
irrGUI = irrDevice->getGUIEnvironment();
irrTimer = irrDevice->getTimer();
irrScene = irrDevice->getSceneManager();
irrDriver = irrDevice->getVideoDriver();
irrDevice->getCursorControl()->setVisible(0);
// Initialize bullet
btDefaultCollisionConfiguration *CollisionConfiguration = new btDefaultCollisionConfiguration();
btBroadphaseInterface *BroadPhase = new btAxisSweep3(btVector3(-1000, -1000, -1000), btVector3(1000, 1000, 1000));
btCollisionDispatcher *Dispatcher = new btCollisionDispatcher(CollisionConfiguration);
btSequentialImpulseConstraintSolver *Solver = new btSequentialImpulseConstraintSolver();
World = new btDiscreteDynamicsWorld(Dispatcher, BroadPhase, Solver, CollisionConfiguration);
// Add camera
ICameraSceneNode *Camera = irrScene->addCameraSceneNodeFPS(0, 100, 10);
Camera->setPosition(vector3df(0, 5, -5));
Camera->setTarget(vector3df(0, 0, 0));
// Preload textures
irrDriver->getTexture("ice0.jpg");
irrDriver->getTexture("rust0.jpg");
// Create text
IGUISkin *Skin = irrGUI->getSkin();
Skin->setColor(EGDC_BUTTON_TEXT, SColor(255, 255, 255, 255));
irrGUI->addStaticText(L"Hit 1 to create a box\nHit 2 to create a sphere\nHit x to reset", rect<s32>(0, 0, 200, 100), false);
http://www.irrlicht3d.org/wiki/index.php?n=Main.GettingStartedWithBullet 8/12/2017
Irrlicht Engine wiki - Getting Started With Bullet Page 6 of 7
// Main loop
u32 TimeStamp = irrTimer->getTime(), DeltaTime = 0;
while(!Done) {
UpdatePhysics(DeltaTime);
ClearObjects();
delete World;
delete Solver;
delete Dispatcher;
delete BroadPhase;
delete CollisionConfiguration;
irrDevice->drop();
return 0;
}
UpdateRender(*Iterator);
}
}
ClearObjects();
CreateBox(btVector3(0.0f, 0.0f, 0.0f), vector3df(10.0f, 0.5f, 10.0f), 0.0f);
}
// Add mass
btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass, LocalInertia);
// Add mass
btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass, LocalInertia);
http://www.irrlicht3d.org/wiki/index.php?n=Main.GettingStartedWithBullet 8/12/2017
Irrlicht Engine wiki - Getting Started With Bullet Page 7 of 7
// Set position
btVector3 Point = TObject->getCenterOfMassPosition();
Node->setPosition(vector3df((f32)Point[0], (f32)Point[1], (f32)Point[2]));
// Set rotation
vector3df Euler;
const btQuaternion& TQuat = TObject->getOrientation();
quaternion q(TQuat.getX(), TQuat.getY(), TQuat.getZ(), TQuat.getW());
q.toEuler(Euler);
Euler *= RADTODEG;
Node->setRotation(Euler);
}
// Free memory
delete Object->getMotionState();
delete Object->getCollisionShape();
delete Object;
}
Objects.clear();
}
http://www.irrlicht3d.org/wiki/index.php?n=Main.GettingStartedWithBullet 8/12/2017