Page 1 of 1

Irrlicht Mesh to Bullet TriangleMesh

Posted: Mon Jul 01, 2013 2:09 am
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.

Re: Irrlicht Mesh to Bullet TriangleMesh

Posted: Mon Jul 01, 2013 3:03 am
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)

Re: Irrlicht Mesh to Bullet TriangleMesh

Posted: Mon Jul 01, 2013 3:09 am
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.

Re: Irrlicht Mesh to Bullet TriangleMesh

Posted: Mon Jul 01, 2013 6:34 am
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.

Re: Irrlicht Mesh to Bullet TriangleMesh

Posted: Mon Jul 01, 2013 7:22 pm
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!

Re: Irrlicht Mesh to Bullet TriangleMesh

Posted: Tue Jul 02, 2013 6:24 pm
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.