Showing posts with label IrrLicht. Show all posts
Showing posts with label IrrLicht. Show all posts

Monday, August 26, 2013

Update 1 - Progress so far - IrrlichtDotNet - .Net library for irrlicht that works under Linux

For original article, please go to this article.

After I made the declaration of starting this project on irrlicht forums, roxaz from the forums expressed interest in the project and immediately forked it on github. We bounced around ideas and while I won't yet merge all of his modifications into my repo, I did like many of this ideas and implemented them after tweaking them to fit in with my code. The ideas that I implemented from his repo are:
  1. folder reorganization
  2. a python script that refreshes the CS project file with all the SWIG generated cs files
  3. make.sh file to automate many initial steps
I also spent some time getting myself more familiar with SWIG typemaps and was able to map irr::core::stringc to System.String for almost all instances. These originally got translated to a SWIG generated generic wrapper which wasn't any useful unless you created a companion helper class in C++ to handle the translation both ways between irr::core::stringc and char *, which gets mapped correctly to System.String. Once all occurrences of irr::core::stringc are mapped to System.String, helper class won't be necessary any more. I will also attempt to deploy more typemaps to handle other such mappings in IrrlichtDotNet project.

Friday, July 26, 2013

Linux compatible .Net bindings for irrLicht using SWIG


Ever since I tried IrrLicht, an Open Source 3d Graphics library, I fell in love with it. It is a C++ library and my C++ isn't as good as I'd like it to be and I am more comfortable with C# under .Net.

Since IrrLicht is open source, I figured, someone might have written an .Net binding for it, and I was correct. A few such bindings do exist, although, they are truly only .Net bindings for IrrLicht for Windows platform only.
I also attempted to use MonoGame, which is known to work under Linux, but without any success.

A few days ago, while researching an unrelated subject, I stumbled across SWIG. SWIG stands for Simple Wrapper and Interface Generator. It is used when you want write wrappers to your C/C++ code for other languages. It also happens to support C#. So I decided to give it SWIG a swing and initial results were more than promising.

I decided to test it but exposing the Main method of my C++ test code written to try IrrLicht and called it from a .Net application. It worked!
I decided to take a shot at generating a wrapper for IrrLicht itself. So far, using the bindings that I was able to create with SWIG, I have been able to create simple 3d scenes in C# code.

I've created a project on GitHub to create a Linux compatible .Net binding for IrrLicht using SWIG. The repo is at https://github.com/jimmy00784/IrrlichtDotNet.

Initially, much of the focus will be on creating a Linux centric binding. However, since SWIG is cross platform, if the community is interested in the effort, it could become more cross platform than that.

Tuesday, September 11, 2012

3d graphics programming - adding some physics

Now that we got the basics of 3d game programming using Irrlicht out of the way, how about adding some physics? I'll demonstrate how physics could be added to a 3d application using the open source Tokamak Physics library. In order to better illustrate the source code, I've uploaded it to GitHub. It is accessible via the 3dGraphicsExamples repository.
Update the Qt project file to include Tokamak library:
In order to use Tokamak in C++ code, you'll need to include its header file:
Before Tokamak can take over as the physics engine behind your application, you need to provide it with some details about the simulation as well as information about your 3d models. In Tokamak, 3d objects that are supposed to be mobile are called rigid bodies, while bodies that are supposed to stay in their position are called animated bodies. In order for Tokamak to run, it needs to know how many objects are needed to be tracked in the simulation as well as information about gravity.
In our simulation, we'll start with poker cards initially suspended in air at varying distances from the a point and all cards facing this point. These cards will fall on a inanimate floor. Create the floor in Irrlicht and record it's attributes in Tokamak:
Create cards using the routine from the previous example however this time also set their physical attributes in Tokamak:
In order to run the simulation, Tokamak requires you to provide an advance interval. In order to get a consistent feel, you'll need to use a timer object and keep track of elapsed time interval. Luckily, Irrlicht provides you with a timer object as well:
You'll also need to ensure that your simulation runs consistently regardless of the amount of processing that goes on in your render loop. The below code is adaptation of code used by Adam Dawes on his site:
In your render loop, you'll have to traverse through your catalog of 3d objects in Tokamak and apply the position and rotation to the corresponding Irrlicht scene nodes.
There you go! You should now see your 3d objects, all initially facing in different directions, falling from on the floor, colliding with each other and bouncing. The complete source file can be found on github: example2.h

Tuesday, August 28, 2012

Introduction to 3d graphics programming using IrrLicht

IrrLicht is free and open source 3d graphics library written in C++. I came across IrrLicht when I was looking for a graphics library that was simple to understand and easy to follow. I had tried DirectX SDK under Windows a few years ago and remember having to blindly copy-paste code samples to get something to work without being able to understand how the code in front of me worked. I had since read about Ogre3d and couple other graphics engines.

When I found IrrLicht, I was surprised by how soon I was able to get myself up and running. The few tutorials on their site covered enough ground to make me feel confident about spending more time experimenting with the library. In this post, I'll do a walkthrough of some code that I've written.
You'll need to download IrrLicht library or compile it from source. IrrLicht is available for download from their website. It is also available as a download from official repositories of major Linux distributions. IrrLicht is also cross-platform and you'll be able to write 3d graphics applications for Linux, Mac, and Windows.

I use QtCreator to do C++ development but you could use any text editor or IDE of your choice. Just remember to include path to IrrLicht header link against IrrLicht library.

Here is how my Qt project file looks like:



TEMPLATE = app
CONFIG += console
CONFIG -= qt

unix:!macx:!symbian: LIBS += -L/usr/lib/ -lIrrlicht

INCLUDEPATH += /usr/include/irrlicht
DEPENDPATH += /usr/include/irrlicht

SOURCES += \
    program.cpp



Add the following lines to your cpp file:

#include <irrlicht.h>
#include <iostream>

using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;

int main(int &argc, char ** argv)
{
    //Create an Irrlicht Device.
    IrrlichtDevice * device = createDevice(EDT_OPENGL,dimension2d(800,600));

    //Get the Scene Manager from the device.
    ISceneManager * smgr = device->getSceneManager();

    //Get the Video Driver from the device.
    IVideoDriver * driver = device->getVideoDriver();

    //Add a Cube to the Scene.
    ISceneNode * node = smgr->addCubeSceneNode();

    //Needed to make the object's texture visible without a light source.
    node->setMaterialFlag(EMF_LIGHTING, false);

    //Add texture to the cube.
    node->setMaterialTexture(0,driver->getTexture("/usr/share/irrlicht/media/wall.jpg"));

    //Set cube 100 units further in forward direction (Z axis).
    node->setPosition(vector3df(0,0,100));

    //Add FPS Camera to allow movement using Keyboard and Mouse.
    smgr->addCameraSceneNodeFPS();

    //Run simulation
    while(device->run())
    {
        //Begin Scene with a gray backdrop #rgb(125,125,125)
        driver->beginScene(true,true,SColor(0,125,125,125));

        //Render the scene at this instant.
        smgr->drawAll();

        //End the scene
        driver->endScene();

        //Logic to update the scene will go here.
    }
    return 0;
}


Compile and Run.
You should see a textured cube in the middle of the screen. You will also notice that using your mouse and keyboard, you can move aroud the redered world.



Let's extend this example to do some fancy stuff. How about loading pictures from your computer in a 3d world? Let us do just that. Let's add a routine to to which we'll pass path to a directory as an argument.

We'll traverse this directory for picture files and for each picture file we find, we'll throw a cube on the screen and scale it to right proportion.

#include <irrlicht.h>
#include <iostream>

using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;

#define PICSCOUNT 800 //Maximum number of pictures to load.

void processFolder(IrrlichtDevice * device, const path &newDirectory)
{
    //Get the File System from the device.
    IFileSystem * fs = device->getFileSystem();

    //Get the Scene Manager from the device.
    ISceneManager * smgr = device->getSceneManager();

    //Get the Video Driver from the device.
    IVideoDriver * driver = device->getVideoDriver();

    //If maximum number of pictures already loaded, then don't load anymore.
    if(driver->getTextureCount() >= PICSCOUNT)
    {
        return;
    }

    //Change working directory.
    fs->changeWorkingDirectoryTo(newDirectory);

    //Get List of files and sub folders.
    IFileList * flist = fs->createFileList();

    //Sort by file names and folder names.
    flist->sort();

    //Loop through the contents of the working directory.
    for(u32 i = 0; i < flist->getFileCount(); i++)
    {
        //If current item is a directory
        if(flist->isDirectory(i))
        {
            //and it is not "Parent Directory .."
            if(strcmp(flist->getFileName(i).c_str(),"..") != 0)
            {
                //process contents of the current sub directory
                processFolder(device,flist->getFullFileName(i));
            }
        }
        else //If current item is a file
        {
            //Get file name
            path filename = flist->getFileName(i);

            //Get extension from file name
            std::string extension = filename.subString(filename.size() - 4,4).c_str();

            //If file extension is .png
            if(strcasecmp(extension.data(),".png") == 0)
            {
                //Create a new cube node with unit dimention
                ISceneNode * node = smgr->addCubeSceneNode(1.0f);

                //Scale the cube to the dimentions of our liking - 75x107x0.1
                node->setScale(vector3df(75,107,0.1f));

                //Set random X cordinate between -500 and 500
                long x = random()% 1000 - 500;

                //Set random Y cordinate between -500 and 500
                long y = random()% 1000 - 500;

                //Set random Z cordinate between -500 and 500
                long z = random()% 1000 - 500;

                //Create a position vector
                vector3df pos(x,y,z);

                //Change cordinates such that direction is preserved and length is 800 units
                pos = pos.normalize() * 800.0f;

                //Apply new position to cube
                node->setPosition(pos);

                //Get active camera
                ICameraSceneNode * cam = smgr->getActiveCamera();

                //Set camera to "look" at cube
                cam->setTarget(node->getPosition());

                //Apply camera's new rotation (as a result of above) to the node
                node->setRotation(cam->getRotation());

                //Make cube's texture visible without light
                node->setMaterialFlag(EMF_LIGHTING, false);

                //Set the file's graphics as texture to the cube
                node->setMaterialTexture(0,driver->getTexture(flist->getFullFileName(i).c_str()));

                //If maximum number of pictures already loaded, then don't load anymore.
                if(driver->getTextureCount() >= PICSCOUNT)
                {
                    return;
                }
            }
        }
    }
}

int main(int &argc, char ** argv)
{
    //Create an Irrlicht Device.
    IrrlichtDevice * device = createDevice(EDT_OPENGL,dimension2d(800,600));

    //Get the Scene Manager from the device.
    ISceneManager * smgr = device->getSceneManager();

    //Get the Video Driver from the device.
    IVideoDriver * driver = device->getVideoDriver();

    //Add FPS Camera to allow movement using Keyboard and Mouse.
    smgr->addCameraSceneNodeFPS();

    //Process contents of this folder.
    processFolder(device, "/home/karim/Images/Cards-Large/150/");

    //Run simulation
    while(device->run())
    {
        //Begin Scene with a gray backdrop #rgb(125,125,125)
        driver->beginScene(true,true,SColor(0,125,125,125));

        //Render the scene at this instant.
        smgr->drawAll();

        //End the scene
        driver->endScene();

        //Logic to update the scene will go here.
    }
    return 0;
}

The images will appear as though they are spread around and stuck on the inside/outside of a transparent sphere.



Let change it a little. Make the following changes:

From:

//Change cordinates such that direction is preserved and length is 800 units
pos = pos.normalize() * 800.0f;


To:

//Set Y cordinate to 0
pos.Y = 0;




The images will now appear as though they are spread around like the stone henge. How about a little more fun? Make the following change:


From:

//Set Y cordinate to 0
pos.Y = 0;


To:

//Set Y cordinate to 0
//pos.Y = 0; //Comment




I hope you this tutorial proves helpful in getting you started in your journey through the facinating world of 3d graphics programming.

Wednesday, August 22, 2012

3d world creation and simulation using Open Source tools and libraries

Over past few weeks I've been looking into 3D world simulation. I checked out Ogre3d however I found it to be way too complex with a steep learning curve. I then came across irrLicht and was greately impressed with its simplicity of use and how quickly it let me jump from following their tutorials to creating my own code. The tutorials on their site are well documented and very easy to follow. Among other things, the tutorials also address basic collision detection. Simple simulations were very easy to make, however, I ran into a road block when attempting to implement slightly more complex physics. I soon realized that while it was possible, I'd have to hand code almost all physics, for instance, gravity, friction, momentum, etc.
After doing some research I came across Tokamak physics engine. I found Tokamak to be surprisingly easy to learn however I only found very few example. Right around the same time I also found Bullet Physics which I found to be very well documented with plenty of tutorials and examples available online. Bullet is also a more comprehensive physics engine than Tokamak and comes with a slight learning curve over Tokamak. On the other hand, Tokamak can get you started and running in no time.
I am currently exploring IrrLicht and both Bullet and Tokamak in couple hobby projects. If the projects gain critical mass, I'll share the experience and perhaps example code in future posts.