Update BulletMeshbody and add it to Irrlicht

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
Mishaaa
Posts: 5
Joined: Sat Oct 03, 2015 9:57 am

Update BulletMeshbody and add it to Irrlicht

Post by Mishaaa »

Hi,

i posted this topic also in the bullet forum, but maybe someone can help me here as well. What i am trying to do is load a .obj file, create a BulletMeshbody and add this Meshbody to Irrlicht. So far so good, all of this works. Now i want to manually add (for the beginning) one triangle to the (already loaded) btTriangleMesh. I can add the triangle, i can create the new BulletMeshbody but now i don't know how to load the new BulletMeshbody to Irrlicht, since the function getMesh() only loads filepaths. See my code below, i created a new project only for trying that out thats why there is no classes etc, thanks for helping.

Code: Select all

#include <iostream>
#include <string>
#include "btBulletDynamicsCommon.h"
#include "irrlicht.h"
#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
#include "btGImpactShape.h"
#include <Windows.h>
 
using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
btRigidBody* CreateBulletBox(btVector3 &TPosition, btVector3 &TScale, btScalar TMass, btDiscreteDynamicsWorld *World);
scene::ISceneNode* IrrlichtCubeBody(btRigidBody* RigidBody, core::vector3df &TScale, scene::ISceneManager *irrScene, video::IVideoDriver *irrDriver);
void RunSimulation(u32 DeltaTime, u32 TimeStamp);
void CreateKinematicPart();
void createBulletMeshbody(btDiscreteDynamicsWorld *World, scene::ISceneManager* irrScene, IrrlichtDevice *irrDev);
btTriangleMesh* ConvertIrrMeshToBulletTriangleMesh(scene::IMesh* pMesh, const core::vector3df& scaling);
void IrrlichtMeshBody(scene::ISceneManager *irrScene, video::IVideoDriver *irrDriver);
void NewIrrlichtMeshBody(scene::ISceneManager *irrScene, video::IVideoDriver *irrDriver);
void UpdateKinematicPart();
void updateBulletMeshbody(btDiscreteDynamicsWorld *World, scene::ISceneManager* irrScene, IrrlichtDevice *irrDev);
 
//Definitions
static btDiscreteDynamicsWorld *World;
static IrrlichtDevice *irrDevice;
static IVideoDriver *irrDriver;
static ISceneManager *irrScene;
static IGUIEnvironment *irrGUI;
static ITimer *irrTimer;
btRigidBody *StatBody;
ISceneNode* StatNode;
btRigidBody *KinBody;
ISceneNode* KinNode;
btTriangleMesh* TrimeshData;
btTriangleMesh* NewTrimeshData;
btCollisionShape* KinMeshShape;
btCollisionShape* NewKinMeshShape;
btRigidBody *MovingRigidMeshBody;
btRigidBody *NewMovingRigidMeshBody;
btScalar friction;
btScalar restitution;
scene::ISceneNode* BodyNode;
scene::ISceneNode* NewBodyNode;
btTransform startTrans;
btVector3 startposition = { 15, 15, 0 };
btDefaultMotionState *MotionState = new btDefaultMotionState(startTrans);
btTransform temp_trans;
btVector3 act_position;
 
int main()
{
 
    //Init Bullet
    btDefaultCollisionConfiguration *CollisionConfiguration = new btDefaultCollisionConfiguration();
    btBroadphaseInterface *BroadPhase = new btDbvtBroadphase();
    btCollisionDispatcher *Dispatcher = new btCollisionDispatcher(CollisionConfiguration);
    btSequentialImpulseConstraintSolver *Solver = new btSequentialImpulseConstraintSolver;
    btGImpactCollisionAlgorithm::registerAlgorithm(Dispatcher);
    World = new btDiscreteDynamicsWorld(Dispatcher, BroadPhase, Solver, CollisionConfiguration);
    World->setGravity(btVector3(0, -9.81f, 0));
 
    //Init Irrlicht
    irrDevice = createDevice(video::EDT_OPENGL, dimension2d<u32>(800, 600), 32, false, false, false, 0);
    irrGUI = irrDevice->getGUIEnvironment();
    irrTimer = irrDevice->getTimer();
    irrScene = irrDevice->getSceneManager();
    irrDriver = irrDevice->getVideoDriver();
    irrDevice->getCursorControl()->setVisible(0);
 
    /** Add camera. */
    ICameraSceneNode *Camera = irrScene->addCameraSceneNodeFPS(0, 100, 10);
    Camera->setPosition(vector3df(5, 5, 5));
    Camera->setTarget(vector3df(0, 0, 0));
 
    /** Preload textures.*/
    irrDriver->getTexture("C:/Users/Michael/Documents/Masterarbeit/GitLab/VBF_Simulation_v2.0/irrlicht-1.8.1/media/terrain-texture.jpg");
 
    irrScene->addLightSceneNode(0, core::vector3df(2, 5, -2), SColorf(4, 4, 4, 1));
    irrScene->setAmbientLight(video::SColorf(0.3, 0.3, 0.3, 1));
 
    CreateKinematicPart();
 
    cout << "#################################" << endl;
    cout << "###" << "Simulation loop" << "###" << endl;
    cout << "#################################" << endl << endl << endl;
    Sleep(1000);
    u32 TimeStamp = irrTimer->getTime();
    u32 DeltaTime = 0;
 
    cout << "Number Triangles Before: " << TrimeshData->getNumTriangles() << endl;
 
    TrimeshData->addTriangle(btVector3(5.f, 5.f, 5.f), btVector3(4.f, 4.f, 4.f), btVector3(3.f, 3.f, 3.f), false);
 
    NewTrimeshData = TrimeshData;
 
    cout << "Number Triangles After: " << NewTrimeshData->getNumTriangles() << endl;
 
    //Comment this out for the regular BulletMeshBody
    UpdateKinematicPart();
 
    while (true)
    {
        RunSimulation(DeltaTime, TimeStamp);
    }
 
    return 0;
}
 
btRigidBody* CreateBulletBox(btVector3 &TPosition, btVector3 &TScale, btScalar TMass, btDiscreteDynamicsWorld *World) {
 
    // Set the initial position of the object
    btTransform Transform;
    Transform.setIdentity();
    Transform.setOrigin(TPosition);
 
    btDefaultMotionState *MotionState = new btDefaultMotionState(Transform);
 
    // Create the shape
    btVector3 HalfExtents(TScale[0] * 0.5f, TScale[1] * 0.5f, TScale[2] * 0.5f);
    btCollisionShape *Shape = new btBoxShape(HalfExtents);
    //std::cout << "Bullet Box: " << *TPosition << std::endl;
 
    // Add mass
    btVector3 LocalInertia;
    Shape->calculateLocalInertia(TMass, LocalInertia);
 
    // Create the rigid body object
    btRigidBody *RigidBody = new btRigidBody(TMass, MotionState, Shape, LocalInertia);
 
    // Set friction and restitution to Bullet Object
    RigidBody->setFriction(0.5);
    RigidBody->setRestitution(0.5);
 
    // Add it to the world
    World->addRigidBody(RigidBody);
 
    return RigidBody;
}
 
scene::ISceneNode* IrrlichtCubeBody(btRigidBody* RigidBody, core::vector3df &TScale, scene::ISceneManager *irrScene, video::IVideoDriver *irrDriver) {
 
    scene::ISceneNode *Node = irrScene->addCubeSceneNode(1.0f);
    Node->setMaterialFlag(video::EMF_LIGHTING, false);
    Node->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
    Node->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE) (Node->isDebugDataVisible() ^ scene::EDS_BBOX));
    Node->setScale(TScale);
 
    Node->setMaterialTexture(0, irrDriver->getTexture("C:/Users/Michael/Documents/Masterarbeit/GitLab/VBF_Simulation_v2.0/irrlicht-1.8.1/media/terrain-texture.jpg"));
 
    // Store a pointer to the irrlicht node so we can update it later
    RigidBody->setUserPointer((void *)(Node));
 
    return Node;
 
}
 
void RunSimulation(u32 DeltaTime, u32 TimeStamp) {
 
    DeltaTime = irrTimer->getTime() - TimeStamp;
    TimeStamp = irrTimer->getTime();
 
    /// Visualization
    irrDriver->beginScene(true, true, SColor(255, 20, 0, 0));
    irrScene->drawAll();
    irrGUI->drawAll();
    irrDriver->endScene();
    irrDevice->run();
    
}
 
void CreateKinematicPart() {
 
    createBulletMeshbody(World, irrScene, irrDevice);
    IrrlichtMeshBody(irrScene, irrDriver);
}
 
void createBulletMeshbody(btDiscreteDynamicsWorld *World, scene::ISceneManager* irrScene, IrrlichtDevice *irrDev) {
 
 
    // Set the initial position, scaling and motion state of the object
    startTrans.setIdentity();
    startTrans.setOrigin(startposition);
    
    cout << "Creating new Kinematic MeshBody!" << endl;
    // Read body from meshfile
    TrimeshData = new btTriangleMesh();
 
    scene::IMesh* IMeshObj = irrScene->getMesh("C:/Users/Michael/Documents/Masterarbeit/GitLab/VBF_Simulation_input/CAD_Daten/1_2x0_8x0_8.obj");
    if (IMeshObj)
    {
        TrimeshData = ConvertIrrMeshToBulletTriangleMesh(IMeshObj, vector3df(1,1,1));
        KinMeshShape = new btBvhTriangleMeshShape(TrimeshData, true);
        KinMeshShape->setLocalScaling(btVector3(1.f, 1.f, 1.f));
 
        btRigidBody::btRigidBodyConstructionInfo RigidMeshBodyCI(0, MotionState, KinMeshShape, btVector3(0, 0, 0));
        MovingRigidMeshBody = new btRigidBody(RigidMeshBodyCI);
 
        // Add it to the world (me)
        World->addRigidBody(MovingRigidMeshBody);
 
        irrScene->getMeshCache()->removeMesh(IMeshObj);
 
    }
    
    else
    {
        std::cout << std::endl << "Error: Mesh path not found: " << IMeshObj << std::endl;
    }
    
    return;
}
 
btTriangleMesh* ConvertIrrMeshToBulletTriangleMesh(scene::IMesh* pMesh, const core::vector3df& scaling)
{
    btVector3 vertices[3];
    u32 i, j, k, index, numVertices, numIndices;
    u16* mb_indices;
    btTriangleMesh *pTriMesh = new btTriangleMesh();
 
    for (i = 0; i<pMesh->getMeshBufferCount(); i++)
    {
        scene::IMeshBuffer* mb = pMesh->getMeshBuffer(i);
        if (mb->getVertexType() == video::EVT_STANDARD)
        {
            video::S3DVertex* mb_vertices = (video::S3DVertex*)mb->getVertices();
            mb_indices = mb->getIndices();
            numVertices = mb->getVertexCount();
            numIndices = mb->getIndexCount();
            for (j = 0; j<numIndices; j += 3)
            {
                for (k = 0; k<3; k++)
                {
                    index = mb_indices[j + k];
                    vertices[k] = btVector3(mb_vertices[index].Pos.X*scaling.X, mb_vertices[index].Pos.Y*scaling.Y, mb_vertices[index].Pos.Z*scaling.Z);
                }
                pTriMesh->addTriangle(vertices[0], vertices[1], vertices[2]);
            }
        }
        else if (mb->getVertexType() == irr::video::EVT_2TCOORDS)
        {
            video::S3DVertex2TCoords* mb_vertices = (video::S3DVertex2TCoords*)mb->getVertices();
            mb_indices = mb->getIndices();
            numVertices = mb->getVertexCount();
            numIndices = mb->getIndexCount();
            for (j = 0; j<numIndices; j += 3)
            {
                for (k = 0; k<3; k++)
                {
                    index = mb_indices[j + k];
                    vertices[k] = btVector3(mb_vertices[index].Pos.X*scaling.X, mb_vertices[index].Pos.Y*scaling.Y, mb_vertices[index].Pos.Z*scaling.Z);
                }
                pTriMesh->addTriangle(vertices[0], vertices[1], vertices[2]);
            }
        }
    }
    return pTriMesh;
}
 
void IrrlichtMeshBody(scene::ISceneManager *irrScene, video::IVideoDriver *irrDriver){
 
    scene::IAnimatedMesh* IMeshPath = irrScene->getMesh("C:/Users/Michael/Documents/Masterarbeit/GitLab/VBF_Simulation_input/CAD_Daten/1_2x0_8x0_8.obj");
 
    if (IMeshPath)
    {
        //Irrlicht
        BodyNode = irrScene->addAnimatedMeshSceneNode(IMeshPath);
        if (BodyNode)
        {
            BodyNode->setMaterialFlag(irr::video::EMF_LIGHTING, true);
            BodyNode->setDebugDataVisible((irr::scene::E_DEBUG_SCENE_TYPE) (BodyNode->isDebugDataVisible() ^ irr::scene::EDS_MESH_WIRE_OVERLAY));
            BodyNode->setMaterialTexture(0, irrDriver->getTexture("C:/Users/Michael/Documents/Masterarbeit/GitLab/VBF_Simulation_v2.0/irrlicht-1.8.1/media/rockwall.jpg"));
            BodyNode->setScale(vector3df(1,1,1));
        }
    }
    else
    {
        cout << std::endl << "Error: No Mesh File for visualization" << endl;
    }
 
    irrScene->getMeshCache()->removeMesh(IMeshPath);
    
    return;
 
}
 
void UpdateKinematicPart() {
 
    updateBulletMeshbody(World, irrScene, irrDevice);
    //What to do here??? Add NewMovingRigidMeshBody to Irrlicht
 
    return;
}
 
void updateBulletMeshbody(btDiscreteDynamicsWorld *World, scene::ISceneManager* irrScene, IrrlichtDevice *irrDev) {
 
    World->removeRigidBody(MovingRigidMeshBody);
    BodyNode->remove();
    
    NewKinMeshShape = new btBvhTriangleMeshShape(NewTrimeshData, true);
    NewKinMeshShape->setLocalScaling(btVector3(1.f, 1.f, 1.f));
 
    btRigidBody::btRigidBodyConstructionInfo RigidMeshBodyCI(0, MotionState, KinMeshShape, btVector3(0, 0, 0));
    NewMovingRigidMeshBody = new btRigidBody(RigidMeshBodyCI);
 
    // Add it to the world (me)
    World->addRigidBody(NewMovingRigidMeshBody);
 
    return;
}
Foaly
Posts: 142
Joined: Tue Apr 15, 2014 8:45 am
Location: Germany

Re: Update BulletMeshbody and add it to Irrlicht

Post by Foaly »

What exactly do you want to do?
Do you want to add geometry (triangles) to both the rendering and the physics simulation?

If so, how often do you want to do that?
Adding a few triangles to the rendering is no problem. But when you add them to the physics sim, it has to generate a new bvh for that mesh, which is a lot slower.

It would help, if you explain, what you are trying to achieve.
Mishaaa
Posts: 5
Joined: Sat Oct 03, 2015 9:57 am

Re: Update BulletMeshbody and add it to Irrlicht

Post by Mishaaa »

Hello,

yes i want to manipulate the mesh geometry (adding and deleting triangles, change positions of vertices..). With the addTriangle i can manipulate the loaded mesh, and then generate a new bvh and add it to the physics simulation but i don't know how to add the new mesh to the rendering (irrlicht) since the getMesh only loads files.
Mishaaa
Posts: 5
Joined: Sat Oct 03, 2015 9:57 am

Re: Update BulletMeshbody and add it to Irrlicht

Post by Mishaaa »

So i tried a few things, and i can manipulate the coordinates of certain vertices, and i can erase vertices and indices (refering to http://irrlicht.sourceforge.net/forum/v ... =4&t=27022). When i try the code below, i can not see a new triangle, what am i doing wrong?

Code: Select all

CMeshBuffer<S3DVertex>* buf = (CMeshBuffer<S3DVertex>*)IMeshObj->getMeshBuffer(0);
 
    numIndices = mb->getIndexCount();
    numVertices = mb->getVertexCount();
    cout << "Nr. Vertices Before: " << numVertices << endl; //8
    cout << "Nr. Indices Before: " << numIndices << endl; //36
    cout << "Nr. Triangles Before: " << numIndices / 3 << endl; //12
 
    //random vertices
    S3DVertex vertex1 = { -1.0f, -1.0f, -1.0f, 0, 0, 0, SColor(255, 0, 100, 0), 0, 0 };
    S3DVertex vertex2 = { 1.5f, 1.5f, 1.5f, 0, 0, 0, SColor(255, 0, 100, 0), 0, 0 };
    S3DVertex vertex3 = { 2.0f, 2.0f, 2.0f, 0, 0, 0, SColor(255, 0, 100, 0), 0, 0 };
    buf->Indices.push_back(10);
    buf->Indices.push_back(9);
    buf->Indices.push_back(8);
    buf->Vertices.push_back(vertex1);
    buf->Vertices.push_back(vertex2);
    buf->Vertices.push_back(vertex3);
    numIndices = mb->getIndexCount();
    numVertices = mb->getVertexCount();
    mb_vertices = (video::S3DVertex*)mb->getVertices();
    mb_indices = mb->getIndices();
    cout << "Nr. Vertices After: " << numVertices << endl; //11
    cout << "Nr. Indices After: " << numIndices << endl; //39
    cout << "Nr. Triangles After: " << numIndices / 3 << endl; //13
 
    //The Indices and Vertices have been inserted correctly
    /*for (int i = 0; i < numIndices; i++)
    {
        cout << "Index " << i << ": " << mb_indices[i] << endl;
    }
    for (int i = 0; i < numVertices; i++)
    {
        cout << "Vertex " << i << " X: " << mb_vertices[i].Pos.X << " Y: " << mb_vertices[i].Pos.Y << " Z: " << mb_vertices[i].Pos.Z << endl;
    }*/ 
 
    while (true)
    {
        RunSimulation(DeltaTime, TimeStamp);
        //The mesh changes if i comment the line below in 
        //mb_vertices[0].Pos.X += 0.0001;
        buf->recalculateBoundingBox();
    }
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Update BulletMeshbody and add it to Irrlicht

Post by CuteAlien »

Try calling mb->setDirty (); to inform the buffer that it has changed. Normals and uv's are both not set - but for a simple material it shouldn't matter. Front-back face mixed up would be possible (change index order to test or disabled backface culling in material). And it could be the triangle is so small you don't see it with your current camera settings.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Mishaaa
Posts: 5
Joined: Sat Oct 03, 2015 9:57 am

Re: Update BulletMeshbody and add it to Irrlicht

Post by Mishaaa »

ok so this code works now:

Code: Select all

//Update MeshBody
 
    SMeshBuffer* buf = new SMeshBuffer();
    buf = (SMeshBuffer*)IMeshObj->getMeshBuffer(0);
 
    //random vertices
    numIndices = buf->getIndexCount();
    numVertices = buf->getVertexCount();
    mb_vertices = (video::S3DVertex*)mb->getVertices();
    mb_indices = buf->getIndices();
    cout << "Nr. Vertices Before: " << numVertices << endl; //11
    cout << "Nr. Indices Before: " << numIndices << endl; //39
    cout << "Nr. Triangles Before: " << numIndices / 3 << endl; //13
    for (int i = 0; i < numIndices; i++)
    {
        cout << "Index " << i << ": " << mb_indices[i] << endl;
    }
    for (int i = 0; i < numVertices; i++)
    {
        cout << "Vertex " << i << " X: " << mb_vertices[i].Pos.X << " Y: " << mb_vertices[i].Pos.Y << " Z: " << mb_vertices[i].Pos.Z << endl;
    }
 
    S3DVertex vertex1 = { -1.5f, 0.9f, -0.9f, 0, 0, 0, SColor(255, 0, 100, 0), 0, 0 };
    S3DVertex vertex2 = { -1.5f, -0.9f, -0.9f, 0, 0, 0, SColor(255, 0, 100, 0), 0, 0 };
    S3DVertex vertex3 = { 1.5f, 0.9f, -0.9f, 0, 0, 0, SColor(255, 0, 100, 0), 0, 0 };
    buf->Indices.push_back(8);
    buf->Indices.push_back(9);
    buf->Indices.push_back(10);
    buf->Vertices.push_back(vertex1);
    buf->Vertices.push_back(vertex2);
    buf->Vertices.push_back(vertex3);
 
    numIndices = buf->getIndexCount();
    numVertices = buf->getVertexCount();
    mb_vertices = (video::S3DVertex*)mb->getVertices();
    mb_indices = buf->getIndices();
    cout << "Nr. Vertices After: " << numVertices << endl; //
    cout << "Nr. Indices After: " << numIndices << endl; //
    cout << "Nr. Triangles After: " << numIndices / 3 << endl; //
    for (int i = 0; i < numIndices; i++)
    {
        cout << "Index " << i << ": " << mb_indices[i] << endl;
    }
    for (int i = 0; i < numVertices; i++)
    {
        cout << "Vertex " << i << " X: " << mb_vertices[i].Pos.X << " Y: " << mb_vertices[i].Pos.Y << " Z: " << mb_vertices[i].Pos.Z << endl;
    }
    
    buf->recalculateBoundingBox();
    buf->setDirty();
 
    while (true)
    {
        RunSimulation(DeltaTime, TimeStamp);
        //The mesh changes if i comment the line below in 
        mb_vertices[0].Pos.X += 0.0001;
        mb_vertices[10].Pos.X += 0.0001;
    }
Just to make sure i am continuing correctly, what i need to do now is updating the bvh in the physics simulation, by changing the same vertices in the btTriangleMesh? Is there a way to save the SMeshBuffer in to a new IMesh?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Update BulletMeshbody and add it to Irrlicht

Post by CuteAlien »

You have to work with a SMesh or SAnimatedMesh (both derived from IMesh but you have to know which one is used - unfortunately no rtti there).
Those have functions to add meshbuffers.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Mishaaa
Posts: 5
Joined: Sat Oct 03, 2015 9:57 am

Re: Update BulletMeshbody and add it to Irrlicht

Post by Mishaaa »

Thanks for the help, i have a working code now. Should i post it here?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Update BulletMeshbody and add it to Irrlicht

Post by CuteAlien »

If you want to :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply