2

检索 OGRE 3D 1.81 子网格数据时出现分段错误。我尝试使用http://alumni.cs.ucr.edu/~sorianom/cs134_09win/中的代码 来获取供子弹物理引擎使用的食人魔网格数据,但遇到了一条错误消息,指出段错误。减少代码找到原因后我发现它是“ submesh->indexData->indexStart“导致段错误。我在Ubuntu Linux 12.10(32bit x86)上运行(由于预算限制,我们买不起Windows),并使用g ++作为编译器。请帮助我,我是一名小学教师尝试为学生制作一些 CAI 程序来学习数学、英语……我知道网站上列出的 cs134 示例代码有点太旧了,我已经升级了所有的网格,dotsceneloader……但仍然无法弄清楚是什么必须更改。谢谢!以下是仍然使段错误错误消息的简化代码。

#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;
}

和错误信息:

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

以下是 gdb 输出:

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

ps:编译器设置:(上面的代码是由 CODE:BLOCK OGRE3D 模板修改的,可以编译,这个精简版不需要项目符号部分)

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

原始文件如下(来自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;
}
4

0 回答 0