Irrlicht Bullet Tutorial Modified

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
GameDude
Posts: 500
Joined: Thu May 24, 2007 12:24 am

Irrlicht Bullet Tutorial Modified

Post by GameDude »

Hello All,

while I have mostly used the code from the bullet tutorial on the Irrlicht wiki, I did modify a few things and added a song using cAudio library. The song is just something taken from Super Tux Kart. No intention of copyright infringement, just thought it would be nice to show and for those who are confused on getting everything running.

Notes: The softbody includes are in there, as at a later point I plan to add some deformation to the objects. Also, in the video I hadn't put the song code in there while I had recorded just the physics simulation without sound. Questions, suggestions, comments? Feel free to reply.

Code: Select all

#include <irrlicht.h>
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <cstdlib>
#include <cAudio.h>
#include <math.h>
 
#include <BulletSoftBody\btSoftRigidDynamicsWorld.h>
#include <BulletSoftBody\btSoftBodyRigidBodyCollisionConfiguration.h>
#include <BulletSoftBody\btSoftBodyHelpers.h>
#include <BulletSoftBody\btSoftBody.h>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
using namespace cAudio;
 
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;}
static void LoadMusic();
static void PlayMusic();
 
static bool Done = false;
static btDiscreteDynamicsWorld *World;
static IrrlichtDevice* Device;
static IVideoDriver* Driver;
static ISceneManager* Smgr;
static IGUIEnvironment* Env;
static IFileSystem* File;
static ITimer* Timer;
static ILogger* Log;
static list<btRigidBody*> Objects;
 
static btSoftBodyWorldInfo softBodyWorld;
 
cAudio::IAudioManager* Mgr; 
cAudio::IAudioSource* Song;
 
class EventReceiverClass : public IEventReceiver
{
    public:
            virtual bool OnEvent(const SEvent& event)
            {
                if(event.EventType == EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
                {
                    switch(event.KeyInput.Key)
                    {
                        case KEY_ESCAPE:
                            Done = true;
                        break;
                        case KEY_KEY_1:
                            CreateBox(btVector3(GetRandInt(10) - 5.0f, 7.0f, GetRandInt(10) - 5.0f), vector3df(GetRandInt(3) + 0.5f, GetRandInt(3) + 0.5f, GetRandInt(3) + 0.5f), 1.0f);
                        break;
                        case KEY_KEY_2:
                            CreateSphere(btVector3(GetRandInt(10) - 5.0f, 7.0f, GetRandInt(10) - 5.0f), GetRandInt(5) / 5.0f + 0.2f, 1.0f);
                        break;
                        case KEY_KEY_X:
                            CreateStartScene();
                        break;
                        default:
                            return false;
                        break;
                    }
                    
                    return true;
                }
                
                return false;
            }
            
};
 
int main()
{
    EventReceiverClass Receiver;
    Device = createDevice(video::EDT_OPENGL, dimension2d<u32>(800,600), 32, false, false, false, &Receiver);
    Env = Device->getGUIEnvironment();
    Timer = Device->getTimer();
    Smgr = Device->getSceneManager();
    Driver = Device->getVideoDriver();
    
    Device->getCursorControl()->setVisible(1);
    
    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);
    
    ICameraSceneNode* Cam = Smgr->addCameraSceneNode(0,vector3df(0,0,0),vector3df(0,0,100));
    Cam->setPosition(vector3df(0,5,-10));
    Cam->setTarget(vector3df(0,0,0));
    
    Driver->getTexture("ice0.jpg");
    Driver->getTexture("rust0.jpg");
    
    Mgr = cAudio::createAudioManager(true);
    Song = Mgr->create("song","Boom_boom_boom.ogg",false);
    
    IGUISkin* Skin = Env->getSkin();
    Skin->setColor(EGDC_BUTTON_TEXT, SColor(255,255,255,255));
    Env->addStaticText(L"Hit 1 to create a box\nHit 2 to create a sphere\nHit X to reset\nHit ESC to exit",rect<s32>(0,0,900,400),false);
    
    Driver->setFog(SColor(0,138,125,81), EFT_FOG_LINEAR,250,1000,.003f,true,false);
    
    Smgr->addLightSceneNode(0, core::vector3df(2,5,-2), SColorf(4,4,4,1));
    CreateStartScene();
    
    int lastFPS = -1;
    
       if(Song)
        {
            Song->play2d(true);
        }
    
    u32 TimeStamp = Timer->getTime(), DeltaTime = 0;
    while(!Done)
    {
        DeltaTime = Timer->getTime() - TimeStamp;
        TimeStamp = Timer->getTime();
        
        UpdatePhysics(DeltaTime);
        
        Driver->beginScene(true, true, SColor(255,20,0,0));
        Smgr->drawAll();
        Env->drawAll();
        Driver->endScene();
        Device->run();
        
        int fps = Driver->getFPS();
        
        if(lastFPS != fps)
        {
            core::stringw tmp(L"Physics - [");
            tmp += Driver->getName();
            tmp += L"] FPS:";
            tmp += fps;
            
            Device->setWindowCaption(tmp.c_str());
            lastFPS = fps;
        }
    }
    
    ClearObjects();
    delete World;
    delete solver;
    delete dispatcher;
    delete broadphase;
    delete collisionConfiguration;
    
    Mgr->shutDown();
    cAudio::destroyAudioManager(Mgr);
    
    Device->drop();
    
    return 0;
}
 
void UpdatePhysics(u32 TDeltaTime)
{
    World->stepSimulation(TDeltaTime * 0.001f, 60);
    
    for(list<btRigidBody*>::Iterator Iterator = Objects.begin(); Iterator != Objects.end(); ++Iterator)
    {
        UpdateRender(*Iterator);
    }
}
 
void CreateStartScene()
{
    ClearObjects();
    CreateBox(btVector3(0.0f, 0.0f, 0.0f), vector3df(10.0f,0.5f,10.0f),0.0f);
}
 
void CreateBox(const btVector3 &TPosition, const vector3df &TScale, btScalar TMass)
{
    ISceneNode* Node = Smgr->addCubeSceneNode(1.0f);
    Node->setScale(TScale);
    Node->setMaterialFlag(EMF_LIGHTING,1);
    Node->setMaterialFlag(EMF_NORMALIZE_NORMALS,true);
    Node->setMaterialTexture(0,Driver->getTexture("rust0.jpg"));
    
    btTransform Transform;
    Transform.setIdentity();
    Transform.setOrigin(TPosition);
    
    btDefaultMotionState* Motion = new btDefaultMotionState(Transform);
    
    btVector3 HalfExtents(TScale.X * 0.5f, TScale.Y * 0.5f, TScale.Z * 0.5f);
    btCollisionShape* Shape = new btBoxShape(HalfExtents);
    
    btVector3 LocalInertia;
    Shape->calculateLocalInertia(TMass, LocalInertia);
    
    btRigidBody* RigidBody = new btRigidBody(TMass, Motion, Shape, LocalInertia);
    RigidBody->setUserPointer((void*)(Node));
    
    World->addRigidBody(RigidBody);
    Objects.push_back(RigidBody);
}
 
void CreateSphere(const btVector3 &TPosition, btScalar TRadius, btScalar TMass)
{
    ISceneNode* Node = Smgr->addSphereSceneNode(TRadius, 32);
    Node->setMaterialFlag(EMF_LIGHTING,1);
    Node->setMaterialFlag(EMF_NORMALIZE_NORMALS,true);
    Node->setMaterialTexture(0,Driver->getTexture("ice0.jpg"));
    
    btTransform Transform;
    Transform.setIdentity();
    Transform.setOrigin(TPosition);
    
    btDefaultMotionState* MotionState = new btDefaultMotionState(Transform);
    
    btCollisionShape* Shape = new btSphereShape(TRadius);
    
    btVector3 LocalInertia;
    Shape->calculateLocalInertia(TMass, LocalInertia);
    
    btRigidBody* RigidBody = new btRigidBody(TMass, MotionState, Shape, LocalInertia);
    
    RigidBody->setUserPointer((void*)(Node));
    
    World->addRigidBody(RigidBody);
    Objects.push_back(RigidBody);
}
 
void UpdateRender(btRigidBody* TObject)
{
    ISceneNode* Node = static_cast<ISceneNode*>(TObject->getUserPointer());
    
    btVector3 Point = TObject->getCenterOfMassPosition();
    Node->setPosition(vector3df((f32)Point[0],(f32)Point[1],(f32)Point[2]));
    
    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);
}
 
 
void ClearObjects()
{
    for(list<btRigidBody*>::Iterator Iterator = Objects.begin(); Iterator != Objects.end(); ++Iterator)
    {
        btRigidBody* Object = *Iterator;
        
        ISceneNode* Node = static_cast<ISceneNode*>(Object->getUserPointer());
        Node->remove();
        
        World->removeRigidBody(Object);
        
        delete Object->getMotionState();
        delete Object->getCollisionShape();
        delete Object;
    }
    
    Objects.clear();
}
http://www.youtube.com/watch?v=Wo0nzTAszlQ
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Irrlicht Bullet Tutorial Modified

Post by robmar »

Nice work! In the video it looks like the parameters were adjusted for lunar gravity though...
GameDude
Posts: 500
Joined: Thu May 24, 2007 12:24 am

Re: Irrlicht Bullet Tutorial Modified

Post by GameDude »

Thanks, I think it just looks weird in the video because of the recording software I used. Caused it to jitter somewhat. I used BB Flashback express to record it. If anyone wants Bullet compiled for the GCC(MingW), I have them.
Post Reply