2

Segmentation fault when retrieving OGRE 3D 1.81 submesh data. I tried to make use of the code from http://alumni.cs.ucr.edu/~sorianom/cs134_09win/ to get ogre mesh data for Bullet physics engine to use, but encountered an error message that said Segment Fault. After reducing the code to find the reason I found it's "submesh->indexData->indexStart" that caused segment fault. I am running on Ubuntu Linux 12.10 ( 32bit x86)(Due the budget limit, we can not afford to buy Windows), and use g++ as compiler. Please help me, I am an elementary school teacher who are trying to make some CAI programs for students to learn Math, English... I know cs134 sample code listed on the site is a little bit too old, I've upgrade all the meshes, dotsceneloader... but still cannot figure out what have to change. Thank you! The following is the reduced code that still makes the segment fault error message.

#include <Ogre.h>
#include <ExampleApplication.h>
#include <btBulletCollisionCommon.h>
class SampleApp : public ExampleApplication
{
public:
    // Basic constructor
    SampleApp()
    {}

protected:

    // Just override the mandatory create scene method
    void createScene(void)    {         
            mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");              
            Ogre::Light* myLight = mSceneMgr->createLight("Light0");
            myLight->setType(Light::LT_POINT);
            myLight->setPosition(0, 40, 0);
            myLight->setDiffuseColour(1, 1, 1);
            myLight->setSpecularColour(1, 1, 1);
            Ogre::Entity* entity = mSceneMgr->createEntity("ogre", "ogrehead.mesh");  
            mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entity);                    
            Ogre::MeshPtr mesh = entity->getMesh();
            Ogre::Mesh::SubMeshIterator j = mesh->getSubMeshIterator();
            while (j.hasMoreElements()) {
                Ogre::SubMesh* submesh = j.getNext(); 
                std::cout << " submesh:" << submesh << "\n";
                std::cout << " submesh->indexData:" << submesh->indexData << "\n";
                //std::cout << " submesh->indexData->indexStart:" << submesh->indexData->indexStart << "\n";
                int idxStart = submesh->indexData->indexStart;          
                int nIdx = submesh->indexData->indexCount;       
            }

    }
};


// ----------------------------------------------------------------------------
// Main function, just boots the application object
// ----------------------------------------------------------------------------
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
    // Create application object
    SampleApp app;

    try
    {
        app.go();
    }
    catch( Exception& e )
    {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else

        std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
    }

    return 0;
}

And the error message:

....
submesh:0xb752c080
submesh->indexData:0x8d042444
Segmentation fault (core dumped)
------------------
(program exited with code: 139)

The following is the gdb output:

 (gdb) print submesh->indexData
 $5 = (Ogre::IndexData *) 0x8d042444
 (gdb) print submesh->indexData->indexStart
 Cannot access memory at address 0x8d042458
 (gdb) 

ps: compiler setting: (You can compile the above code which is modified from CODE:BLOCK OGRE3D template , and bullet part isn't necessary in this reduced version)

g++ -o "%e" "%f" pkg-config --cflags --libs OGRE OIS bullet -I/usr/local/include/OGRE -I/usr/include/bullet

The original file is as following ( from http://tutorialsdl.googlecode.com/svn/trunk/Lab3/Lab3/OgreToBtMeshConverter.cpp) :

#include <Ogre.h>
#include <ExampleApplication.h>
#include <btBulletCollisionCommon.h>

class SampleApp : public ExampleApplication
{
public:
    // Basic constructor
    SampleApp()
    {}

protected:

    // Just override the mandatory create scene method
    void createScene(void)    {         
            mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");              
            Ogre::Light* myLight = mSceneMgr->createLight("Light0");
            myLight->setType(Light::LT_POINT);
            myLight->setPosition(0, 40, 0);
            myLight->setDiffuseColour(1, 1, 1);
            myLight->setSpecularColour(1, 1, 1);
            Ogre::Entity* entity = mSceneMgr->createEntity("ogre", "ninja.mesh");  
            mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entity);
              //
            // initialize bullets collision detection system
            //
            btVector3 worldAabbMin(-1000,-1000,-1000);
            btVector3 worldAabbMax(1000,1000,1000);
            btDefaultCollisionConfiguration* mColConfig; 
            btCollisionWorld* mColWorld;
            btCollisionDispatcher* mDispatcher;
            btAxisSweep3* mBroadphase;       
            mBroadphase = new btAxisSweep3(worldAabbMin, worldAabbMax); // broadphase
            mColConfig = new btDefaultCollisionConfiguration();
            mDispatcher = new btCollisionDispatcher(mColConfig); // narrowphase pair-wise checking
            mColWorld = new btCollisionWorld(mDispatcher, mBroadphase, mColConfig);

            //
            // Registers every mesh in OGREs scene manager with the
            // collision world. You should be adding your environment
            // to the scene manager before this call. Your moveable
            // character should be created after this call as to avoid
            // having his mesh become part of the static level geometry.
            //
            // All meshes here are placed into group 2 and set to
            // collide with group 1. You character should be in group
            // 1, and set to collide with group 2. More about contact groups
            // in the manual.
            btCollisionWorld* colWorld=0;
            registerEntityAsCollider(entity,colWorld);               
    }

    void registerEntityAsCollider(Entity* entity, btCollisionWorld* colWorld)
    {
        // if you wish to do instancing you will have to share one
        // btTriangleMesh amongst multiple btBvhTriangleMeshShape
        // instances
        btTriangleMesh* btMesh = new btTriangleMesh();

        MeshPtr mesh = entity->getMesh();
        Mesh::SubMeshIterator j = mesh->getSubMeshIterator();
        while (j.hasMoreElements()) {
            SubMesh* submesh = j.getNext(); 

            int idxStart = submesh->indexData->indexStart;
            int nIdx = submesh->indexData->indexCount;

            HardwareIndexBuffer* idxBuffer 
                = submesh->indexData->indexBuffer.get();

            HardwareVertexBufferSharedPtr virtBuffer;
            VertexDeclaration* virtDecl;

            if (submesh->useSharedVertices) {
                virtDecl = mesh->sharedVertexData->vertexDeclaration;
                assert(mesh->sharedVertexData->vertexBufferBinding->getBufferCount() > 0);
                virtBuffer = mesh->sharedVertexData->vertexBufferBinding->getBuffer(0);
            } else {
                virtDecl = submesh->vertexData->vertexDeclaration;
                assert(submesh->vertexData->vertexBufferBinding->getBufferCount() > 0);
                virtBuffer = submesh->vertexData->vertexBufferBinding->getBuffer(0);
            }

            unsigned char* pVert = static_cast<unsigned char*>(virtBuffer->lock(HardwareBuffer::HBL_READ_ONLY));

            // need to lock the buffer since vertex data resides on GPU
            // and we need synchronization
            unsigned short* sindices = NULL;
            unsigned long* lindices = NULL;

            if (idxBuffer->getType() == HardwareIndexBuffer::IT_16BIT) {
                sindices = static_cast<unsigned short*>(idxBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
            } else if (idxBuffer->getType() == HardwareIndexBuffer::IT_32BIT) {
                lindices = static_cast<unsigned long*>(idxBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
            } else {
                assert(true == false);
            }

            const VertexElement* elm = virtDecl->findElementBySemantic(VES_POSITION, 0);
            int offset = elm->getOffset();
            assert(elm->getType() == VET_FLOAT3);

            for (int k = idxStart; k < idxStart + nIdx; k += 3) {
                unsigned int indices[3];
                btVector3 vertices[3];

                if (idxBuffer->getType() == HardwareIndexBuffer::IT_16BIT) {
                    for (int l = 0; l < 3; ++l) {
                        indices[l] = sindices[k + l];
                    }
                } else {
                    for (int l = 0; l < 3; ++l) {
                        indices[l] = lindices[k + l];
                    }
                }

                for (int l = 0; l < 3; ++l) { // for each vertex
                    Real* posVert = (Real*)(pVert + indices[l] * virtBuffer->getVertexSize() + offset);
                    for (int m = 0; m < 3; ++m) { // for each vertex component
                        vertices[l][m] = posVert[m];
                    }
                }

                btMesh->addTriangle(vertices[0], vertices[1], vertices[2]);
            }

            idxBuffer->unlock();
            virtBuffer->unlock();
        }

        btBvhTriangleMeshShape* btMeshShape = new btBvhTriangleMeshShape(btMesh, true, true);

        btCollisionObject* btObj = new btCollisionObject();
        btObj->setCollisionShape(btMeshShape);

        Vector3 pos = entity->getParentSceneNode()->getPosition();
        Quaternion orient = entity->getParentSceneNode()->getOrientation();
        Vector3 scale = entity->getParentSceneNode()->getScale();

        btMeshShape->setLocalScaling(btVector3(scale[0], scale[1], scale[2]));
        btMeshShape->setMargin(0.0);

        btTransform btTrans;
        btTrans.setIdentity();
        btTrans.setOrigin(btVector3(pos[0], pos[1], pos[2]));
        btTrans.setRotation(btQuaternion(orient[1], orient[2], orient[3], orient[0]));
        btObj->setWorldTransform(btTrans);

        // the last 2 parameters are bit strings representing group membership
        // and the groups which it is allowed to collide with
        colWorld->addCollisionObject(btObj, 2, 1);
    }

//
// This method will take every entity in your scene and register it as
// a mesh in the btCollisionWorld. NOTE: Be sure to call this function after
// you've added your static entities (environment) to the scene manager but
// before you add your characters. 
// 
    void registerAllEntitiesAsColliders(SceneManager* sceneMgr, btCollisionWorld* colWorld)
    {
        SceneManager::MovableObjectIterator 
            i = sceneMgr->getMovableObjectIterator("Entity");

        while (i.hasMoreElements()) {
            Entity* entity = static_cast<Entity*>(i.getNext());
            registerEntityAsCollider(entity, colWorld);
        }
    }



};


// ----------------------------------------------------------------------------
// Main function, just boots the application object
// ----------------------------------------------------------------------------
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
    // Create application object
    SampleApp app;

    try
    {
        app.go();
    }
    catch( Exception& e )
    {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else

        std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
    }

    return 0;
}
志誠 徐
  • 41
  • 4
  • 1
    `submesh->indexData` points to an invalid memory location. It is a bug, but it is hard to tell who is responsible. Have you tried to run an unmodified example? – n. m. could be an AI Apr 13 '13 at 14:51
  • I've added the original file OgreToBtMeshConverter.cpp, and tried again, and the problem is still the same. Is this a bug of gcc or of Ogre3D 1.81 or because the program written in 2009 not compatible with today's framework? How can I modify them? – 志誠 徐 Apr 14 '13 at 03:42
  • I think you may have better luck asking this at Ogre forums. – n. m. could be an AI Apr 14 '13 at 03:50
  • Yes, I have. But no response yet, except for the only one by myself. I saw many questions unanswered there. – 志誠 徐 Apr 14 '13 at 03:58
  • Are you running on a big-endian machine? – StarPinkER Apr 14 '13 at 04:25
  • My machine is little endian, Intel x86 quad core, system: Ubuntu 12.10 32bits. OgreToBtMeshConverter.cpp is a program to convert Ogre 3D engine's meshes to bullet physics meshes for which to detect collision. – 志誠 徐 Apr 14 '13 at 05:01

0 Answers0