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