C++ BinaryReader?

Started by
17 comments, last by Ectara 11 years, 11 months ago
Hey guys, im trying to read in data from a binary file, but i cant seem to read it correctly,
the file is a MD3 format, Here is the code i use to read the first few bytes


ifstream md3file;
md3file.open(filename.c_str(), ios::in|ios::binary|ios::ate|ios_base::binary);
// C stuff
md3_header * md3Header = (struct md3_header *)
malloc(sizeof(struct md3_header));//Malloc seems to read the data correctly
//new vector<int>(sizeof(struct md3_header));
// it involves evil casting.
md3file.read((char *) &md3Header, sizeof(struct md3_header));

if((md3Header->ident != 860898377)||(md3Header->version !=15)
||((md3Header->fileID[0] != 'I')
||(md3Header->fileID[1] != 'D')
||(md3Header->fileID[2] != 'P')
||(md3Header->fileID[3] != '3')))
{
cout<<"Bad Version or identifier"<<endl;
cout << md3Header->fileID[0] << md3Header->fileID[1] <<
md3Header->fileID[2] << md3Header->fileID[3] << endl;
cout << md3Header->version << endl;
cout << md3Header->ident << endl;
}


Now this is what is displayed in my console

Bad Version or identifier
?B??
-23510312
52
now i know this MD3 is correct as another MD3 loader loads it fine :),
Now i want to try and do something different, my code above takes in the struct from my header and places a template inside md3Header, it then puts all the data from the file provided through the parameter into that struct, but as you can see im getting the wrong data,

So here is the question, how can i actually manually tell that my md3Header.fileID[0] to be = to the frist byte in my MD3 file?

in C# i can see it would be so easy just a nice simple md3Header.fileID = getTest(enc.GetString(reader.ReadBytes(4)));
for your information fileID is fileID[4], each has a letter or a number inside it,

Now im not sure if getting the first byte is the way to go, but i want to actually manually put each bit of data into my header pointer
myself instead of trusting "read" function and sizeof

If anyone could help that would be awesome

Canvas
Advertisement
If you want to read a byte at a time, you want a vector<char>, not a vector<int>.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

but what if i wanted to read 4 bytes? or 32 bytes?,

so how would i set my md3Header.fileID[0] be?
md3Header.fileID[0] = new vector[char]....???
Your specific problem is here: "(char *) &md3Header" - that should be "(char *) md3Header" instead as md3Header is already a pointer.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

without the & i still get this in the console


Bad Version or identifier
8H??
-23508936
52

which is wrong, also i feel that myabe ifstream is wrong? it doesnt seem to be reading my binary md3 file correctly or is that just my code? my header is correct for the format,
i just want to be able to set md3Header.fileID[0] to the first byte or maybe first 4 bytes, once i know how to do that i maybe able to fix the problem
Is your md3_header struct packed as tightly as possible?
tell you the truth, i dont understand whta you mean by packed? here is my md3header


#include <GL/glew.h>
#include <GL/gl.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <vector>
#include "GameAsset.h"
using namespace std;
#ifndef MD3ASSET_H_
#define MD3ASSET_H_
class Md3Asset : public GameAsset {
public:
Md3Asset(const string &filename);
virtual ~Md3Asset();
virtual void update();
private:
void import_md3_asset(const string &filename);
//May need this
typedef float vec3[3];
struct md3_header
{
char fileID[4]; //Stores the file IDs
int ident; //Stores the identity
int version; //Stores the version, Must be 15
char name[64]; //Stores the name of the file
int flags; //Stores the flags
int num_frames; //Stores number of frames
int num_tags; //Stores number of tags
int num_surfaces; //Stores number of surfaces
int num_skins; //Stores number of skins
int ofs_frames; //Stores offset number of frames
int ofs_tags; //Stores offset number of tags
int ofs_surfaces; //Stores offset number of surfaces
int ofs_eof; //Stores offset end and finish???
};
struct md3_frame
{
float min_bounds[3]; //Min (x,y,z) value for the frame
float max_bounds[3]; //Max (x,y,a) value for the frame
float local_origin[3]; //Stores the frame position
float radius; //Scale/Radius of the frame
char name[16]; //Modeler used to create the loaded model
};
struct md3_tag
{
char name[64]; //Stores the name of the tag
Vector3 origin; //Stores the translation that should be performed
Vector3 axis[3][3]; //Stores the 3x3 rotation matrix for this frame
};
struct md3_surface
{
int ident; //Stores the identity
char name[64]; //Stores the surface name
int flags; //Stores the flags
int num_frames; //Stores the number of frames
int num_shaders; //Stores the number of shaders
int num_verts; //Stores the number of vertices
int num_triangles; //Stores the number of triangles
int ofs_triangles; //Stores the offset triangles
int ofs_shaders; //Stores the offset shaders
int ofs_ST; //Stores the offset starts
int ofs_xyzNormal; //Stores the offset starting positions
int ofs_end; //Stores the offset surface ends
};
struct md3_shader
{
char name[64]; //Stores the file name
int shader_index; //Stores the shader index number
};
struct md3_triangle
{
int indexes[3]; //Stores a list of offset values for Vertex
};
struct md3_texCoord
{
float st[3]; //Stores s & t texture coordinates
};
struct md3_vertex
{
short coord[3]; //x,y,z coordinates in right-handed 3-space
short normal; //Stores angles
};
md3_frame *md3Frame;
md3_tag *md3Tag;
md3_surface *md3Surface;
md3_shader *md3Shader;
md3_triangle *md3Triangle;
md3_texCoord *md3TexCords;
md3_vertex *md3Vertex;
};
#endif


does packed me, i actually define how long a int, short, char is?
Assuming your struct is packed, try this:

ifstream md3file;
md3file.open(filename.c_str(), ios::in | ios::binary | ios::ate);
md3_header md3Header;
md3file.read(reinterpret_cast<char *>(&md3Header), sizeof(md3_header));

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Ok ApochPiQ, i tried your code with one little change

I removed the & and made my md3Header a pointer

ifstream md3file;
md3file.open(filename.c_str(), ios::in | ios::binary | ios::ate);
md3_header * md3Header;
md3file.read(reinterpret_cast<char *>(md3Header), sizeof(md3_header));

Now my program opens and then just closes, doesnt display anything in console, a window will appear for a tiny second and then boom its gone
Just did some testing if i remove my check to see if the ident or version is correct it comes up with a window, here is the code for my version checker

if((md3Header->ident != 860898377)||(md3Header->version !=15)
||((md3Header->fileID[0] != 'I')
||(md3Header->fileID[1] != 'D')
||(md3Header->fileID[2] != 'P')
||(md3Header->fileID[3] != '3')))
{
cout<<"Bad Version or identifier"<<endl;
cout << md3Header->fileID[0] << md3Header->fileID[1] <<
md3Header->fileID[2] << md3Header->fileID[3] << endl;
cout << md3Header->version << endl;
cout << md3Header->ident << endl;
}
I think you might have some misconceptions about how pointers work.

The code you posted will read into random chunks of memory and obliterate whatever's there. If you're lucky it will crash like you describe; if you're unlucky very literally almost anything could happen to your program's behavior.

I posted code that should work. I really don't understand what you were hoping to accomplish by making that change.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This topic is closed to new replies.

Advertisement