Irrlicht Mesh to Bullet TriangleMesh

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
rcalvin
Posts: 31
Joined: Tue Jan 08, 2013 1:58 am

Irrlicht Mesh to Bullet TriangleMesh

Post by rcalvin »

Hello fella's!

So I'm trying to use Bullet in my project (for the first time), and though I've gotten to terms with it fairly quickly, I'm having troubles trying to convert a mesh from Irrlicht to Bullet. I'm fairly certain I remember reading something quite a long time ago about this, but searching has yielded no useful results. The bullet forums are also seemingly dying a painful death (pages not found left right and center...) (?) So now I come to you!

So, basically, I'm trying to construct a btTriangleIndexVertexArray from IMeshBuffer, but I'm having a hard time. Can anyone shed some light on this whole situation for me?

Thanks!

Edit: I just wanted to sort of clarify. If you know of a way to convert irrlicht meshes to a Bullet trianglemesh, then please share! I've got some of it down, but I'm having problems converting the Vertices. Specifically, Bullet wants a stride for the vertex array and I'm not really sure what I need to put there. I mean, the stride for the indices should be sizeof(int)*3 right, because an index is an integer and there are three of them per triangle. But I don't know what to do with the vertex array, because you don't necessarily know how many vertices are going to make up the next triangle, since it might be 3 for a brand new one, 2 for a triangle that shares a vertex with another, or 1 for a triangle that shares two vertices with others.
Last edited by rcalvin on Mon Jul 01, 2013 3:07 am, edited 1 time in total.
Cube_
Posts: 1010
Joined: Mon Oct 24, 2011 10:03 pm
Location: 0x45 61 72 74 68 2c 20 69 6e 20 74 68 65 20 73 6f 6c 20 73 79 73 74 65 6d

Re: Irrlicht Mesh to Bullet TriangleMesh

Post by Cube_ »

I can't bother explaining it, here have some code:

Code: Select all

//Global bullet vars
static bool Done = false;
static btDiscreteDynamicsWorld *dynamicsWorld;
static list<btRigidBody *> objects;
 
//Global Irrlicht vars
static IrrlichtDevice *device;
static IVideoDriver *driver;
static ISceneManager *smgr;
static ITimer *timer;
//static IGUIEnvironment *guienv;
//static IFileSystem *filesys;
//static ILogger *logger;
 
//Bullet Related 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);
void UpdatePhysics(u32 TDeltaTime);
static void UpdateRender(btRigidBody *TObject);
static void ClearObjects();
static int GetRandInt(int TMax) {return rand() % TMax; }
 
class EventReceiverClass : public IEventReceiver
{
    public:
 
            virtual bool OnEvent(const SEvent &TEvent)
            {
 
                if(TEvent.EventType == EET_KEY_INPUT_EVENT && !TEvent.KeyInput.PressedDown)
                {
                    switch(TEvent.KeyInput.Key)
                    {
                        case KEY_ESCAPE:
                        Done=true;
                        break;
 
                        case KEY_KEY_Q:
                        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_W:
                        createSphere(btVector3(GetRandInt(10) - 5.0f, 7.0f, GetRandInt(10) - 5.0f), GetRandInt(5) / 5.0f + 0.2f, 1.0f);
                        break;
 
                        case KEY_KEY_E:
                        createStartScene();
                        break;
 
                        default:
                        return false;
                        break;
                    }
                return true;
            }
            return false;
        }
};
 
int main()
{
    srand(time(NULL));
    int screenHeight = 800, screenWidth = 600;
 
    EventReceiverClass receiver;
    device = createDevice(EDT_OPENGL, dimension2d<u32>(screenHeight, screenWidth), 32, false, false, false, &receiver);
 
    if (device == 0)
    {
        return 1;
    }
 
    //guienv = device->getGUIEnvironment();
    timer = device->getTimer();
    driver = device->getVideoDriver();
    smgr = device->getSceneManager();
 
    device->getCursorControl()->setVisible(false);
 
    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();
    dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadPhase, solver, collisionConfiguration);
 
    ICameraSceneNode *camera = smgr->addCameraSceneNodeFPS(0,100,25);
    camera->setPosition(vector3df(0,5,-5));
    camera->setTarget(vector3df(0,0,0));
 
    /*IGUISkin* skin = guienv->getSkin();
    skin->setColor(EGDC_BUTTON_TEXT, SColor(255,200,200,200));
    guienv->addStaticText(L"Hit Q to spawn a cube, W for a sphere and E to reset or escape to exit.", rect<s32>(0,0,200,100), false);
    IGUIStaticText* versionText = guienv->addStaticText(L"", rect<s32>(0,0,300,200),false);
    versionText->setText(string);*/
 
    smgr->addLightSceneNode(0, vector3df(2, 5, -2), SColorf(4, 4, 4, 1));
    createStartScene();
 
    driver->getTexture("resources/textures/tex.jpg");
    driver->getTexture("resources/textures/tex1.jpg");
 
    u32 timeStamp = timer->getTime(), DeltaTime = 0;
 
    while(Done == false)
    {
        device->run();
        if(device->isWindowActive())
        {
            DeltaTime = timer->getTime() - timeStamp;
            timeStamp = timer->getTime();
 
            UpdatePhysics(DeltaTime);
 
            driver->beginScene(true,true,SColor(255,55,0,155));
            smgr->drawAll();
            //guienv->drawAll();
            driver->endScene();
 
            int FPS = driver->getFPS(), lastFPS = -1;
 
            if(lastFPS != FPS)
            {
                stringw str = L"COLLISION TEST [";
                str += driver->getName();
                str += "] FPS:";
                str += FPS;
                str += " VERSION:";
                str += auto__RC_FILEVERSION_STRING;
 
                device->setWindowCaption(str.c_str());
                lastFPS=FPS;
            }
        }
        device->yield();
    }
    ClearObjects();
    delete dynamicsWorld;
    delete solver;
    delete dispatcher;
    delete broadPhase;
    delete collisionConfiguration;
 
    device->drop();
    getchar();
    return 0;
}
 
void UpdatePhysics(u32 TDeltaTime)
{
    dynamicsWorld->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("resources/textures/tex.jpg"));
 
    btTransform bulletTransform;
    bulletTransform.setIdentity();
    bulletTransform.setOrigin(TPosition);
 
    btDefaultMotionState *motionState = new btDefaultMotionState(bulletTransform);
 
    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, motionState, shape, localInertia);
 
    rigidBody->setUserPointer((void*)(node));
 
    dynamicsWorld->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("resources/textures/tex1.jpg"));
 
    btTransform bulletTransform;
    bulletTransform.setIdentity();
    bulletTransform.setOrigin(TPosition);
 
    btDefaultMotionState *motionState = new btDefaultMotionState(bulletTransform);
 
    btCollisionShape *shape = new btSphereShape(TRadius);
 
    btVector3 localInertia;
    shape->calculateLocalInertia(TMass, localInertia);
 
    btRigidBody *rigidBody = new btRigidBody(TMass,motionState,shape,localInertia);
 
    rigidBody->setUserPointer((void*)(node));
 
    dynamicsWorld->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& TQuaternion = TObject->getOrientation();
    quaternion q(TQuaternion.getX(), TQuaternion.getY(), TQuaternion.getZ(), TQuaternion.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();
 
        dynamicsWorld->removeRigidBody(object);
 
        delete object->getMotionState();
        delete object->getCollisionShape();
        delete object;
    }
    objects.clear();
}
That's from my current project but it's pretty standard stuff. (am I doing this converstion wrong btw? It looks right but I don't actually know)
"this is not the bottleneck you are looking for"
rcalvin
Posts: 31
Joined: Tue Jan 08, 2013 1:58 am

Re: Irrlicht Mesh to Bullet TriangleMesh

Post by rcalvin »

Thanks for your time, but I think you misunderstood my question, unless I'm missing something in your code. You don't seem to be dealing with non-primitive meshes at all.
Otaka
Posts: 17
Joined: Fri Nov 16, 2012 1:47 pm

Re: Irrlicht Mesh to Bullet TriangleMesh

Post by Otaka »

I think this project will help you:
http://code.google.com/p/irrbp/source/b ... /convert.h
http://code.google.com/p/irrbp/source/b ... shBody.cpp

In convert.h you can find method irrMeshToBulletTriangleMesh, that make actual conversion.
rcalvin
Posts: 31
Joined: Tue Jan 08, 2013 1:58 am

Re: Irrlicht Mesh to Bullet TriangleMesh

Post by rcalvin »

Wonderful! That's exactly what I was looking for. I'm not sure if I looked through irrbp, but I looked through another Irrlicht/Bullet project and, though I came across the use of functions such as irrMeshToTriangleMesh, I couldn't actually find the declaration/implementation anywhere! I haven't tried this out yet, so if it doesn't work, I'll come back, but reading over it, it seems to do what I need it to!

Thanks again!
Otaka
Posts: 17
Joined: Fri Nov 16, 2012 1:47 pm

Re: Irrlicht Mesh to Bullet TriangleMesh

Post by Otaka »

It works, I have checked in my own project. There are troubles with some models in X format. You should make Reset X Form in 3dsMax before export.
Also it is very usefull to enable debug view in Bullet to see whats going wrong.
Post Reply