I return with another perplexing issue that I just can't figure out, a generic and unhelpful"std::bad_alloc at memory location" error. Before I get to the code, some background...
Having finished my uber-awesome 2D engine (thanks entirely to you guys) I decided it was time to break open the can of worms that is the third dimension! twiddled VC2008's dials and threw in some OpenGL (DirectX got old really fast).
So far every things gone swimmingly, I've got sprites, partials, 3d models, even a basic environment! It's not even close to optimised but it's just for learning and bragging rights really... Then down comes the hammer of my error.
What I'm basically doing is adding a function to load wavefront OBJ models, after some annoying glitches I got that working fine, happyfaces all around. However the problem seems to occur not when I generate one of these meshes, but rather when I try to use them in one of my more complex classes.
In short I have a mesh class that hold pointers to memory containing the lists of vertex's UV coords.. just generic data really.
This mesh class, is in-turn pointed to by a 'model' class, this is so that many models can use the same mesh without having to load it several times (and using up memory like magnetic tape in a 1960's render farm).
So far all this works (or at least seems to) work fine. function loads data into pointers, these are passed to the mesh that holds the pointers, the mesh (now full of data) has it's pointer passed to the 'model' that stores that and other data (for physics simulations etc), the problem arises when trying to allocate memory for the 'compiled' mesh class, this object contains a pointer to the model, reads the data from the model and produces a 'compiled' model (basically just optimised and stored on the GPU). This in turn pointed to by a model class containing render functions.
I can't post all my code (due to the sheer quanta of it would most likely take up half the forum) So I'll include any parts I consider relivent and if you need anything else I'll be happy to oblige.
Base data storage:
typedef struct
{
public:
float X,Y,Z,U,V;
} PJBStdVertex;
typedef struct
{
public:
PJBStdVertex Vertex[3];
} PJBStdTriangle;
//Mesh Loading function (OBJ model file reader)
PJBStdMesh* PJBLoadObjMesh(char* MeshFilePath)
{
FILE* TheMeshFile;
TheMeshFile = fopen(MeshFilePath, "rt");
int numtriangles; // Number Of Triangles In total
char oneline[255]; // String To Store Data In
char readString[255];
PJBStdMesh* Mesh;
vector<PJBStdTriangle> TriangleBuffer;
vector<PJBVec3Df> Verts;
vector<PJBVec2Df> Uvs;
if(TheMeshFile)
{
readstr(TheMeshFile,oneline); // Get Single Line Of Data
bool Done=false;
while(!feof(TheMeshFile))
{
readstr(TheMeshFile,oneline); // Get Single Line Of Data
sscanf(oneline, "%255s",&readString);
if(!strcmp(readString,"v"))
{
float Val1,Val2,Val3;
sscanf(oneline, "%*s %f %f %f\n", &Val1,&Val2,&Val3);
PJBVec3Df VertBuffer(Val1,Val2,Val3);
Verts.push_back(VertBuffer);
}
else if(!strcmp(readString,"vt"))
{
float Val1,Val2;
sscanf(oneline, "%*s %f %f\n", &Val1,&Val2);
PJBVec2Df UVBuffer(Val1,Val2);
Uvs.push_back(UVBuffer);
}
else if(!strcmp(readString,"f"))
{
int Val1,Val2,Val3,Val4,Val5,Val6;
sscanf(oneline, "%*s %i/%i %i/%i %i/%i \n", &Val1,&Val2,&Val3,&Val4,&Val5,&Val6);
PJBStdTriangle TriBuffer;
for(int VertLoop=0; VertLoop < 3; VertLoop++)
{
if(Val1<=Verts.size() && Val1>=1)//error checking, saves your arse!
{
TriBuffer.Vertex[VertLoop].X=Verts[Val1-1].x;
TriBuffer.Vertex[VertLoop].Y=Verts[Val1-1].y;
TriBuffer.Vertex[VertLoop].Z=Verts[Val1-1].z;
}
else
{
break;
}
if(Val2<=Uvs.size() && Val2>=1)//error checking, saves your arse!
{
TriBuffer.Vertex[VertLoop].U=Uvs[Val2-1].x;
TriBuffer.Vertex[VertLoop].V=Uvs[Val2-1].y;
}
else
{
break;
}
}
TriangleBuffer.push_back(TriBuffer);
}
}
fclose(TheMeshFile);
numtriangles=TriangleBuffer.size()-1;
Mesh = new PJBStdMesh;
Mesh->NumTri=numtriangles;
PJBStdTriangle* TriBuff;
TriBuff = new PJBStdTriangle[numtriangles];
for(int i=0;i<TriangleBuffer.size();i++)
{
for(int VertLoop=0; VertLoop < 3; VertLoop++)
{
TriBuff[i].Vertex[VertLoop].X=TriangleBuffer[i].Vertex[VertLoop].X;
TriBuff[i].Vertex[VertLoop].Y=TriangleBuffer[i].Vertex[VertLoop].Y;
TriBuff[i].Vertex[VertLoop].Z=TriangleBuffer[i].Vertex[VertLoop].Z;
TriBuff[i].Vertex[VertLoop].U=TriangleBuffer[i].Vertex[VertLoop].U;
TriBuff[i].Vertex[VertLoop].V=TriangleBuffer[i].Vertex[VertLoop].V;
}
}
Mesh->Polygons = TriBuff;
}
else
{
fclose(TheMeshFile);
return NULL;
}
return Mesh;
}
//Initial call from main engine
ModelTest = new PJBGLModel3D(ATexture,"ash.obj",Location,Velocity,Rotation);
//High level model constructor:
PJBGLModel3D::PJBGLModel3D(PJBGLTexture* texture, char* MeshPath, PJBVec3Df Pos, PJBVec3Df Vel, PJBVec3Df RotVel): PJBGLModel2D(texture,MeshPath,Pos.x,Pos.y,Vel.x,Vel.y,RotVel.x,RotVel.y)
{
Physics.SetPos(Pos);
Physics.SetVel(Vel);
Physics.SetRotVel(RotVel);
}
//High Level model parent constructor
PJBGLModel2D::PJBGLModel2D(PJBGLTexture* texture, char* MeshPath, float Xpos, float Ypos, float XVel, float YVel, float XRotVel, float YRotVel)
{
Properties.PJBEnable(PJBObjRender);
LocalMesh=true;
LocalCompiled=true;
Mesh = new PJBGLModelMesh(texture,MeshPath);
DisplayObject = new PJBGLModelCompiled(Mesh);
if(Mesh)MeshLoaded=true;
if(DisplayObject)MeshCompiled=true;
Physics.SetPos(Xpos,Ypos);
Physics.SetVel(XVel,YVel);
Physics.SetRotVel(XRotVel,YRotVel);
}
//Note, the memory allocation error occours on the DisplayObject = //new line, however I'm unsure if the address it reports is being //allocated on that line or the line previous...
//Low level model initialiser
PJBGLModelMesh::PJBGLModelMesh(PJBGLTexture* Texture, char* MeshPath)
{
ModelTexture=NULL;
ModelMesh=NULL;
ModelTexture=Texture;
ModelMesh = PJBLoadObjMesh(MeshPath);
}
//That section doesn't trigger any errors and it seems to be working //fine (checked with breakpoints etc)
//Compiled model initialiser
PJBGLModelCompiled::PJBGLModelCompiled(PJBGLModelMesh *CompileObj)
{
Compiled=CompileMesh(CompileObj);
Mesh = CompileObj;
}
The strange part is the previous section never gets called! it seems the failure happens on the 'new' statement inself!
I checked my memory usage and it doesn't appear to be going beyond 20%, I can't understand why it's failing to allocate memory.
Just as a final note the functions worked absolutely fine when using my previous (NeHe inspired) model loading system. For reference I'll post that below.
PJBStdMesh* PJBLoadRawMesh(char* MeshFilePath)
{
FILE* TheMeshFile;
TheMeshFile = fopen(MeshFilePath, "rt");
int numtriangles; // Number Of Triangles In Sector
char oneline[255]; // String To Store Data In
float x,y,z,u,v;
PJBStdMesh* Mesh;
PJBStdTriangle* TriangleBuffer;
if(TheMeshFile)
{
Mesh = new PJBStdMesh;
readstr(TheMeshFile,oneline); // Get Single Line Of Data
sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles); // Read In Number Of Triangles
TriangleBuffer = new PJBStdTriangle[numtriangles];
Mesh->NumTri=numtriangles;
for(int TriLoop=0; TriLoop < numtriangles; TriLoop++)
{
for(int VertLoop=0; VertLoop < 3; VertLoop++)
{
readstr(TheMeshFile,oneline); // Get Single Line Of Data
sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
TriangleBuffer[TriLoop].Vertex[VertLoop].X=x;
TriangleBuffer[TriLoop].Vertex[VertLoop].Y=y;
TriangleBuffer[TriLoop].Vertex[VertLoop].Z=z;
TriangleBuffer[TriLoop].Vertex[VertLoop].U=u;
TriangleBuffer[TriLoop].Vertex[VertLoop].V=v;
}
}
fclose(TheMeshFile);
}
else
{
fclose(TheMeshFile);
return NULL;
}
Mesh->Polygons=TriangleBuffer;
return Mesh;
}
Now I will admit that the originally loaded models where not very complex, (10-50 polygons at most) meanwhile the OBJ model is quite complex (1500 polygons).
For further reference here are two sample model files.
Original test model (NeHe format)
NUMPOLLIES 6
-1 -1 0 0 0
1 -1 0 1 0
1 1 0 1 1
1 1 0 1 1
-1 1 0 0 1
-1 -1 0 0 0
1 1 0 1 0
1 -1 0 0 1
2 -2 1 0 0
2 -2 1 0 0
2 2 1 1 0
1 1 0 1 0
-1 -1 0 0 1
-2 -2 1 0 0
2 -2 1 1 0
2 -2 1 1 0
1 -1 0 1 1
-1 -1 0 0 1
New model (Obj Format, is rather large, so I've added it as an attachment.)
Finally I realise no one has any interest in 'stealing' my (rather poor) code, however if you do for some unbeknown reason use it, please credit myself and NeHe.