views:

247

answers:

6

Hi,

I'm writing an MD3 model loader in C++ and I understand the file format and what I need to do but I can't seem to get the syntax right. I have a class for the model and within that class there are a set of structs which will have the model data read into them. In the implementation of the class there is a constructor which reads data in when initialised with an MD3 file. I am using C style casting to do this. The first struct seems to be working and the data appears to be read in correctly but the following two seem to have all values left as zero which shouldn't be the case. The code compiles without error but I'm fairly new to C++ so I've probably made a simple mistake here!

The main file just set up the object with an MD3 file and then goes on to set up some OpenGL things but that's all working correctly and doesn't effect the constructor.

The interface:GameObject.h

class GameObject1 {
public:
GameObject1();
GameObject1(const char * filename);
virtual ~GameObject1();

virtual void Draw();

private:
struct md3_header_t
{
    int  IDENT;         //id of file, always "IDP3"
    int  Version;       //version number, always 15
    char Name[64];      //name of character
    int  Flags;         //blank but needed
    int  Num_frames;    //number of Frames
    int  Num_surfaces;  // number of shaders
    int  Num_skins;     //...
    int  Num_triangles; //num triangles - important one
    int  Ofs_triangles; // offset of triangles
    int  Ofs_frames;    // frames offset
    int  Ofs_tags;      // tags offset
    int  Ofs_surfaces;  //offset to surfaces
    int  Ofs_eof;       //offset of end of header

};

typedef float vec3[3];

struct md3_frame_header_t
{
    vec3 Min_bounds;    //first corner of bounding box
    vec3 Max_bounds;    //other corner
    vec3 local_origin;  //usually 0 0 0
    float Radius;       //radius of bounding sphere
    char NAME[16];      // name of frame
};

struct md3_tag_header_t
{
    char NAME[64];      //name of tag
    vec3 origin;        //origin of tag eg head or torso
    vec3 Axis[3];       //axis stuff
};

struct md3_surface_header_t
{
    int IDENT;           //id, must be IDP3
    char Name[64];       //name of mesh
    int Flags;          // blank space
    int Num_frames;     // number of frames
    int Num_shaders;    // no shaders
    int Num_vert;       // number verts
    int Num_triangles;  //number of triangles
    int Ofs_triangles;  //offset of triangle data from surface start
    int Ofs_shaders;    // offset of shaders
    int Ofs_st;         // offset texture data
    int Ofs_xyznormal;  // offset of verts
    int Ofs_end;        // offset of end of surface section from start
};

and the interface GameObect.cpp, NOTE I've only included the constructor method here since the destructor and the draw method are both empty currently:

#include "GameObject1.h"

GameObject1::GameObject1() {
   //if we have no model...
}

//constructor if a model has been provided
GameObject1::GameObject1(const char * filename) {
ifstream md3file;
md3file.open(filename, ios::in|ios::binary);

// C stuff
md3_header_t * md3header = (struct md3_header_t *)
    malloc(sizeof(struct md3_header_t));
md3file.read((char *) md3header, sizeof (struct md3_header_t));


// Check the file
if (md3header->IDENT != 860898377) {
    // Error!
    cerr << "Error: bad version or identifier" << endl;
}  


// seekg to search through the file to add new data to structs
    // frame struct
md3_frame_header_t * md3frame = (struct md3_frame_header_t *)
            malloc(sizeof(struct md3_frame_header_t));
md3file.seekg(md3header->Ofs_frames);
md3file.read((char *) md3frame, sizeof (struct md3_frame_header_t));

//surface struct
md3_surface_header_t * md3surface = (struct md3_surface_header_t *)
                                 malloc(sizeof( md3_surface_header_t));
md3file.seekg(md3header->Ofs_surfaces);
md3file.read((char *) md3surface, sizeof (struct md3_surface_header_t));

md3file.close();
}

GameObject1::~GameObject1() {
// deconstructor
}

void GameObject1::Draw(){
 // eventually a method to draw the model to screen using OpenGL and SDL
}

I'm really lost on this one so any help would be greatly appreciated.

Thanks,

Jon

+1  A: 

Check the values of md3header->Ofs_frames and md3header->Ofs_surfaces to make sure they aren't trying to index past the end of the file. If they are, then the MD3 file may be corrupt or reading the file is not mapping properly to the struct.

Not sure if this is an issue but you may run into problems on 64 bit system if the the file was generated on a 32 bit (and vice versa) since the size of the ints would be different which would throw off the mapping to the struct.

May want to find a tool that you know can read the files properly and compare those values with the ones you are getting. Or use a hex editor to manually look through the file to verify the values.

Jesse
A: 

My suggestion :

The code has memory leaks in constructor since you have not released memory allocated on heap . so free the memory when its not of any use.

Ashish
+1  A: 

Have a look at the memory layout of your structs: print out sizeof(float), sizeof(int), sizeof(char), sizeof(md3_frame_header_t), etc. and see if they are exactly what you expect. If not, you might want to play around with #pragma pack, to force the momory layout of your struct to be the file layout. Also, is the endianness of the bytes in the file the same as the in-memory layout?

In general I would also advise against reading structs from files. The few CPU cycles you save by doing this have mattered in the 90ies, but these day's they don't anymore. You should rather implement proper read and write code that reads and parses the fields as specified in the file format documentation, and then store them with set methods in your own in-memory representation. This makes the in-memory layout independent from the file layout, makes the code easier to debug, and easier to port if you want to switch to a different architecture or such

Carsten Kuckuk
+1  A: 

Your structures need to be aligned properly, look here.

msuvajac
A: 

first you give exact valus and then check check size is properly or not

srikanth
A: 

Thanks for the help. I found the problem eventually by checking the size of the md3_header_t struct. There was an extra int in there (the Ofs_triangles) which shouldn't have been there. It's now reading the data perfectly so I'll get to work on the next part.

Thanks again,

Jon

Jon Hocking