Page 1 of 1
Irrlicht + SPE Integration
Posted: Fri Jan 09, 2009 6:01 am
by IrrNoob
I've resently discovered a great physics engine called SPE (Simple Physics Engine) and am trying to integrate it into my Irrlicht project.
but I get a linker error:
Code: Select all
error LNK2019: unresolved external symbol "struct ISPEWorld * __cdecl CreateSPEWorld(void)" (?CreateSPEWorld@@YAPAUISPEWorld@@XZ) referenced in function "void __cdecl InitApp(void)" (?InitApp@@YAXXZ)
..\..\examples\SPEGame\SPEGame.exe : fatal error LNK1120: 1 unresolved externals
My code is based off of the first SPE sample which compiles.
there doesn't seem to be any syntax errors that I can notice.
Does anyone know what causes this error?
Posted: Fri Jan 09, 2009 6:53 am
by Katsankat
Tell to the linker where SPE.lib is. What is your IDE/compiler?
Posted: Fri Jan 09, 2009 7:12 am
by IrrNoob
You were right, I use MSVC 2008 but I'm real new to this IDE.
But now the program crashes after execution.
Why does this happen?
Posted: Fri Jan 09, 2009 9:25 am
by hybrid
You cannot call InitApp (which uses the global device pointer) without having Irrlicht initialized first. Try to remove all your global variables, or at least clean up your init scheme to use only initialized stuff. Oh, and a debugger will easily point to the place that uses non-initialized pointers etc.
Posted: Fri Jan 09, 2009 7:20 pm
by IrrNoob
ok, I got rid of the globals, cleaned up initApp and made changes to the code in my last message to reflect this, but at this line in main.cpp:
Code: Select all
video::IVideoDriver* driver = device->getVideoDriver();
I get this error when debugging:
Code: Select all
Unhandled exception at 0x0043261f in GameDebug.exe: 0xC0000005: Access violation reading location 0x00000000.
What is going on and what is this unhandled exception?
How do I fix this?
Posted: Fri Jan 09, 2009 8:53 pm
by drewbacca
Your code pretty clearly sets device = 0, then you immediately try using the -> operator on your 0.
You can't do anything with your device pointer until you create the device.
Posted: Fri Jan 09, 2009 9:37 pm
by IrrNoob
drewbacca wrote:Your code pretty clearly sets device = 0, then you immediately try using the -> operator on your 0.
You can't do anything with your device pointer until you create the device.
Ah, I guess that was pretty dumb, I thought I setup Irrlicht right
here is the new code:
Code: Select all
#include <irrlicht.h>
#include <SPE.h>
#include <iostream>
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(lib, "SPE.lib")
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
struct LMesh
{
SPEVertex *pVertex;
int *pIndex;
int NumVertices;
int NumIndices;
int NumFaces;
LMesh()
{
pVertex=0;
pIndex=0;
NumVertices=0;
NumIndices=0;
}
bool Load(scene::IAnimatedMesh* mesh, const SPEVector& Scale=SPEVector(1,1,1))
{
//Get number of vertices
u32 nMeshBuffer;
for( nMeshBuffer = 0 ; nMeshBuffer < mesh->getMeshBufferCount(); ++nMeshBuffer)
{
scene::IMeshBuffer *buffer = mesh->getMeshBuffer(nMeshBuffer);
NumVertices += buffer->getVertexCount();
}
pVertex = new SPEVertex[NumVertices]; // causes bad allocation of memory.
u32 n;
for( n = 0 ; n < mesh->getMeshBufferCount(); ++n)
{
scene::IMeshBuffer *buffer2 = mesh->getMeshBuffer(n);
NumIndices += buffer2->getIndexCount();
}
pIndex = new int[NumIndices];
NumFaces = NumIndices / 3;
for(int i=0; i<NumVertices; i++)
{
pVertex[i].p.x*=Scale.x;
pVertex[i].p.y*=Scale.y;
pVertex[i].p.z*=Scale.z;
}
return true;
}
void Release()
{
if(pVertex) delete[] pVertex;
if(pIndex) delete[] pIndex;
}
~LMesh()
{
Release();
}
};
int main()
{
SPEVector Eye, At;
LMesh Mesh;
LPSPEWORLD pWorld;
LPSPERIGIDBODY pMesh;
IrrlichtDevice* device = 0;
// select opengl as driver type
video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
// create device
device = createDevice(driverType, core::dimension2d<s32>(1024, 768), 32,
/*fullscreen*/true, /*stencilbuffer*/false, /*vsync*/true, 0);
ICameraSceneNode* camera = 0;
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
scene::IAnimatedMesh* lilman = smgr->getMesh("media/LittleMan.md2");
if (device == 0)
return 1; // could not create selected driver.
// add camera
// CREATE WASD KEYMAP ARRAY
SKeyMap keyMapWASD[5];
keyMapWASD[0].Action = EKA_MOVE_FORWARD;
keyMapWASD[0].KeyCode = KEY_KEY_W;
keyMapWASD[1].Action = EKA_MOVE_BACKWARD;
keyMapWASD[1].KeyCode = KEY_KEY_S;
keyMapWASD[2].Action = EKA_STRAFE_LEFT;
keyMapWASD[2].KeyCode = KEY_KEY_A;
keyMapWASD[3].Action = EKA_STRAFE_RIGHT;
keyMapWASD[3].KeyCode = KEY_KEY_D;
keyMapWASD[4].Action = EKA_JUMP_UP;
keyMapWASD[4].KeyCode = KEY_SPACE;
camera = smgr->addCameraSceneNodeFPS(0,100.0f,1.f,0,keyMapWASD, 5, true, 3);
camera->setPosition(core::vector3df(3800,-350,7400));
camera->setTarget(core::vector3df(4794,-686,3400));
camera->setFarValue(12000.0f);
camera->setNearValue(1.0f);
// disable mouse cursor
device->getCursorControl()->setVisible(false);
Eye=SPEVector(10,20,10)*0.8;
At=SPEVector(0,0,0);
Mesh.Load( lilman, SPEVector(20, 20, 0.5f));
pWorld = CreateSPEWorld();
pWorld->SetGravity (SPEVector(0, -9.8f, 0));; // this is the default value of gravity in SPE
LPSPESHAPE pShape = pWorld->CreateShape();
pShape->Initialize ((BYTE*)Mesh.pVertex, sizeof(SPEVertex), Mesh.pIndex, Mesh.NumFaces );
pMesh=pWorld->AddRigidBody (pShape);
pMesh->SetBeStatic(true);
pMesh->SetPosition (SPEVector(0,0,0));
pWorld->ReleaseShape(pShape);
u32 previous = device->getTimer()->getTime();
while(device->run()){
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
const u32 current = device->getTimer()->getTime();
float fElapsedTime = (float*)current - (float*)previous;
pWorld->Update (fElapsedTime);
previous = current;
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
if (device->isWindowActive())
{
driver->beginScene(true, true, 0 );
smgr->drawAll();
driver->endScene();
}}
device->drop();
return 0;
}
But still I am lost because I am getting a new error at this line:
Code: Select all
pVertex = new SPEVertex[NumVertices];
and this error message:
Code: Select all
Unhandled exception at 0x7c812aeb in SPEGameDebug.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0012fae4..
So why is it giving me a bad allocation of memory?
Posted: Sat Jan 10, 2009 12:47 am
by IrrNoob
I think the problem is maybe caused by the call to:
Code: Select all
bool Load(scene::IAnimatedMesh* mesh, const SPEVector& Scale=SPEVector(1,1,1))
{
//Get number of vertices
u32 nMeshBuffer;
for( nMeshBuffer = 0 ; nMeshBuffer < mesh->getMeshBufferCount(); ++nMeshBuffer)
{
scene::IMeshBuffer *buffer = mesh->getMeshBuffer(nMeshBuffer);
NumVertices += buffer->getVertexCount();
}
pVertex = new SPEVertex[NumVertices]; // causes bad allocation of memory.
u32 n;
for( n = 0 ; n < mesh->getMeshBufferCount(); ++n)
{
scene::IMeshBuffer *buffer2 = mesh->getMeshBuffer(n);
NumIndices += buffer2->getIndexCount();
}
pIndex = new int[NumIndices];
NumFaces = NumIndices / 3;
for(int i=0; i<NumVertices; i++)
{
pVertex[i].p.x*=Scale.x;
pVertex[i].p.y*=Scale.y;
pVertex[i].p.z*=Scale.z;
}
return true;
}
because I am trying to do in Irrlicht what is done in opengl in the first SPE sample:
Code: Select all
bool Load(char *FileName, const SPEVector& Scale=SPEVector(1,1,1))
{
FILE *fp=0;
fp=fopen(FileName,"rb");
if(!fp)
{
MessageBox(0, "Model file not found!", "GLMesh", 0);
return false;
}
fread(&NumVertices, sizeof(int), 1, fp);
pVertex=new SPEVertex[NumVertices];
fread(pVertex, sizeof(SPEVertex)*NumVertices, 1, fp);
int n;
fread(&n, sizeof(int), 1, fp);
pIndex=new int[n];
fread(pIndex, sizeof(int)*n, 1, fp);
NumFaces=n/3;
fclose(fp);
for(int i=0; i<NumVertices; i++)
{
pVertex[i].p.x*=Scale.x;
pVertex[i].p.y*=Scale.y;
pVertex[i].p.z*=Scale.z;
}
return true;
}
This is done so that one is able to make this call to:
Code: Select all
pShape->Initialize ((BYTE*)Mesh.pVertex, sizeof(SPEVertex), Mesh.pIndex, Mesh.NumFaces );
the documents say that the definition and usage of virtual SPERESULT Initialize is:
Code: Select all
struct ISPEShape
{
virtual SPERESULT Initialize(BYTE *pVertex, int StrideSize, int *pIndex, int NumTriangles) = 0;
Create a shape from tri-mesh data.
Parameters
pVertex
[in] Pointer to vertex buffer.
StrideSize
[in] Stride of one vertex, in bytes.
pIndex
[in] Pointer to index buffer, index must be 32BIT.
NumTriangles
[in] Number of triangles.
Return
SPE_OK if the method succeeds, else return SPE_FAILED.
How would I then correctly write the Load() to get the correct information
for Initialize(), using Irrlicht to abstract this data instead of opengl?
Posted: Sat Jan 10, 2009 12:54 am
by drewbacca
I didn't look at your code too in depth, so sorry if I'm not answering your bigger picture question. But anyway your crash says "bad_alloc" which is saying that it couldn't allocate the memory for your array of SPEVertex. If you were to use your debugger or just display the value of NumVertices, you'd see your problem.
You never initialize it to zero before adding to it, so its some random, probably huge number
Posted: Sat Jan 10, 2009 1:18 am
by IrrNoob
Your correct again, thanks drewbacca. I needed to initialize
NumVertices and NumIndices to zero in the LMesh constructor.
But now I get another unhandled exception:
Code: Select all
Unhandled exception at 0x0035c4c8 in SPEGameDebug.exe: 0xC0000005: Access violation reading location 0xe69f5cdc.
But the debugger says it cannot point to a location in my code that is
the cause.
Would this have to do with my Load()?
I need to know how to get a pointer to the vertex buffer for the loaded mesh, the stride of a vertex, in bytes, a pointer to the 32bit index buffer for the loaded mesh, and the number of triangles.
How do I get this data from Irrlicht?
UPDATE:
I'm looking at the Irrlicht API documents, and see the member function
getVertexBuffer() and getIndexBuffer(), but I'm a little lost on how to implement anything with these...
Posted: Sat Jan 10, 2009 3:16 am
by IrrNoob
After trying to get trying to implement getVertexBuffer() and getIndexBuffer() to get a pointer to the loaded mesh's vertex buffer and index buffer I have this for the LMesh class:
Code: Select all
struct LMesh
{
SPEVertex *pVertex;
int *pIndex;
int NumVertices;
int NumFaces;
scene::IDynamicMeshBuffer *VertexBuffer;
scene::IDynamicMeshBuffer *IndexBuffer;
LMesh()
{
pVertex =0;
pIndex=0;
NumVertices =0;
NumFaces =0;
VertexBuffer =0;
IndexBuffer =0;
}
bool Load(scene::IAnimatedMesh* mesh, const SPEVector& Scale=SPEVector(1,1,1))
{
pVertex = (SPEVertex*)VertexBuffer->getVertexBuffer().getData();
pIndex = (int*)IndexBuffer->getIndexBuffer().getData();
//Get number of vertices
u32 nMeshBuffer;
for( nMeshBuffer = 0 ; nMeshBuffer < mesh->getMeshBufferCount(); ++nMeshBuffer)
{
scene::IMeshBuffer *buffer = mesh->getMeshBuffer(nMeshBuffer);
NumVertices += buffer->getVertexCount();
}
NumFaces = NumVertices / 3;
for(int i=0; i<NumVertices; i++)
{
pVertex[i].p.x*=Scale.x;
pVertex[i].p.y*=Scale.y;
pVertex[i].p.z*=Scale.z;
}
return true;
}
void Release()
{
if(pVertex) delete[] pVertex;
if(pIndex) delete[] pIndex;
if(VertexBuffer) delete[] VertexBuffer;
if(IndexBuffer) delete[] IndexBuffer;
}
~LMesh()
{
Release();
}
};
But At this line of code
Code: Select all
pVertex = (SPEVertex*)VertexBuffer->getVertexBuffer().getData();
I am getting this error:
Code: Select all
Unhandled exception at 0x00432939 in SPEGameDebug.exe: 0xC0000005: Access violation reading location 0x00000000.
I'm still struggling to figure this out.
I need to provide a vertex buffer and indices to create the collision shape
Posted: Sat Jan 10, 2009 5:28 am
by twilight17
You initialise VertexBuffer to nothing, but you're getting data from it?
IrrNoob wrote:
Code: Select all
pVertex = (SPEVertex*)VertexBuffer->getVertexBuffer().getData();
Posted: Sat Jan 10, 2009 5:53 am
by IrrNoob
Code: Select all
LMesh()
{
pVertex =0;
pIndex=0;
NumVertices =0;
NumFaces =0;
VertexBuffer =0;
IndexBuffer =0;
}
I am initializing vertexBuffer here, correct? I want to get a pointer to the first vertex of a vertex buffer of a IAnimatedMesh* mesh. I'm not sure how to get that data from an IAnimatedMesh.
Do I need to create a vertex buffer, or does Irrlicht automatically produce one when calling the driver?
I want to do something like:
Code: Select all
mesh = VertexBuffer->getVertexBuffer().getData();
pVertex = (SPEVertex *)mesh;
but I the compiler is telling me I cannot convert from void * to irr::scene::IAnimatedMesh *.
Can someone show me the proper way to get a pointer to the first vertex of a vertex buffer of a IAnimatedMesh* mesh?
Posted: Sat Jan 10, 2009 1:34 pm
by IrrNoob
I have managed to put together this in order to get the pointer to the first vertex of a vertex buffer of a IAnimatedMesh* mesh:
Code: Select all
irr::u32 meshBufferCount = (irr::u32)mesh->getMesh(0)->getMeshBufferCount();
// pointer to the mesh buffer
scene::IMeshBuffer* mb = mesh->getMesh(0)->getMeshBuffer(0);
NumVertices = mb->getVertexCount(); // get vertex number
int* mbVertices = (int*)mb->getVertices(); // get pointer to vertices in the mesh buffer
irr::u32* mbIndices = (irr::u32*)mb->getIndices(); // get pointer to indices in the mesh buffer
pVertex = new SPEVertex[mbVertices];
But I'm stumped on how to get the first vertex of the vertex buffer into pVertex.