Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


C++ BinaryReader?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
18 replies to this topic

#1 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 25 April 2012 - 03:54 PM

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

Sponsor:

#2 ApochPiQ   Moderators   -  Reputation: 15979

Like
0Likes
Like

Posted 25 April 2012 - 03:59 PM

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

#3 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 25 April 2012 - 04:28 PM

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]....???

#4 mhagain   Crossbones+   -  Reputation: 8134

Like
1Likes
Like

Posted 25 April 2012 - 04:42 PM

Your specific problem is here: "(char *) &md3Header" - that should be "(char *) md3Header" instead as md3Header is already a pointer.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#5 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 25 April 2012 - 05:03 PM

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

#6 fastcall22   Crossbones+   -  Reputation: 4373

Like
0Likes
Like

Posted 25 April 2012 - 05:07 PM

Is your md3_header struct packed as tightly as possible?
c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#7 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 25 April 2012 - 05:12 PM

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?

#8 ApochPiQ   Moderators   -  Reputation: 15979

Like
0Likes
Like

Posted 25 April 2012 - 05:15 PM

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


#9 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 25 April 2012 - 05:20 PM

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


#10 ApochPiQ   Moderators   -  Reputation: 15979

Like
0Likes
Like

Posted 25 April 2012 - 05:41 PM

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.

#11 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 25 April 2012 - 05:56 PM

Ok ive just used your code, the result is different but still not correct, also it froze my laptop :D, here is the output i get with your code implemented


Bad Version or identifier

157955018
0

which still isnt correct :(

#12 ApochPiQ   Moderators   -  Reputation: 15979

Like
0Likes
Like

Posted 25 April 2012 - 06:14 PM

If you open the file in a hex editor, does it actually show the bytes you expect to see?

#13 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 25 April 2012 - 06:34 PM

k the first line in the lara_head.MD3 in hex is this
49 44 50 33 0F 00 00 00 00 00 00 00 00 00 00 00 00 = IDP3 which is correct
but in my program it comes up with nothing :D,

still just doesnt seem to read the file correctly, or my header isnt correct, but it matchs many other peoples headers out there,

#14 ApochPiQ   Moderators   -  Reputation: 15979

Like
0Likes
Like

Posted 25 April 2012 - 06:59 PM

Can you post your complete code as it stands now?

#15 Trienco   Crossbones+   -  Reputation: 2207

Like
0Likes
Like

Posted 25 April 2012 - 09:58 PM

Before spending an endless amount of time debugging the read call:

Did you check your stream after opening it? If it fails to find/open the file in the first place, everything after that can't work.

Did you use gcount after read to see how much data you REALLY read into your struct?

Did you at any point consider to initialize your struct to all 0 to tell the difference between "reading wrong data" and "reading no data and having random uninitialized garbage in your struct"?
f@dzhttp://festini.device-zero.de

#16 Washu   Senior Moderators   -  Reputation: 5357

Like
2Likes
Like

Posted 26 April 2012 - 03:00 AM

You should really learn some basic C++ before you continue. The mistakes you're making are all quite trivial ones, and demonstrate a notable lack of understanding of pointers and basic C++ good practices.

Below is a snippet of working code that should get you started. Do try and read up on the bits and pieces you don't understand, instead of just copying and pasting and hoping it works.


#include <iostream>
#include <fstream>
#include <vector>
#include <cstdint>
#include <iterator>

struct MD3Vec3 {
	float x, y, z;
};

struct MD3Header {
	int32_t ident;
	int32_t version;
	char name[64];
	int32_t flags;
	int32_t num_frames;
	int32_t num_tags;
	int32_t num_surfaces;
	int32_t num_skins;
	int32_t ofs_frames;
	int32_t ofs_tags;
	int32_t ofs_surfaces;
	int32_t ofs_eof;
};

struct MD3Frame
{
	MD3Vec3 min_bounds;
	MD3Vec3 max_bounds;
	MD3Vec3 local_origin;
	float radius;
	char name[16];
};

struct MD3Tag {
	char name[64];
	MD3Vec3 origin;
	MD3Vec3 axis[3];
};

int main() {
	std::ifstream fin("../test.md3", std::ios::binary | std::ios::in);
	auto data = std::vector<char>(std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>());

	MD3Header* header = reinterpret_cast<MD3Header*>(&data.front());

	std::cout<<std::hex<<header->ident<<std::endl;

	for(int32_t i = 0; i < header->num_frames; ++i) {
		MD3Frame* frame = reinterpret_cast<MD3Frame*>(&data.front() + header->ofs_frames) + i;
		std::cout<<frame->name<<std::endl;
	}
}

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX


#17 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 26 April 2012 - 03:09 AM

Cheers Washu, I have a lesson soon so i wont be able to check your code until 1english time Posted Image, Sorry about the lack of knowledge, it does come in time tho Posted Image

Also here is my header and cpp file before i edit it with washu's code

Md3Asset.cpp
#include "Md3Asset.h"
Md3Asset::Md3Asset(const string &filename) {
	    import_md3_asset(filename);
// make the objects to display
if(0 == make_resources()) {
   cout << "Can't make the required OpenGL resources for Md2Asset." << endl;
   // TODO: exit nicely here
}
}
Md3Asset::~Md3Asset() {
  // TODO: clean up
}
void Md3Asset::update() {
}
void Md3Asset::import_md3_asset(const string &filename) {
/*ifstream md3file(filename, ios::in|ios::binary);
//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.*/
//ifstream is input stream, ofstream is output stream
//fstream is input&output
fstream md3file;
//ios::in = open for input mode
//ios::binary = opens the file in binary mode
md3file.open(filename.c_str(), ios::in | ios::binary | ios::ate);
md3_header md3Header;
md3file.read(reinterpret_cast<char *>(&md3Header), sizeof(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;
   }
md3file.close();
}

Md3Asset.h
#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

Thats my code at the moment which will change soonish

#18 Canvas   Members   -  Reputation: 243

Like
0Likes
Like

Posted 26 April 2012 - 08:48 AM

Ok Washu i have added your code and im getting a error

Here is my Md3Asset.cpp file
#include "Md3Asset.h"
Md3Asset::Md3Asset(const string &filename) {
import_md3_asset(filename);
// make the objects to display
if(0 == make_resources()) {
  cout << "Can't make the required OpenGL resources for Md3Asset." << endl;
  // TODO: exit nicely here
}
}
Md3Asset::Md3Asset(){}
Md3Asset::~Md3Asset() {
// TODO: clean up
}
void Md3Asset::update() {
}
void Md3Asset::import_md3_asset(const string &filename) {
	std::ifstream fin("../lara_head.MD3", std::ios::binary | std::ios::in);
	auto data = std::vector<char>(std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>());
	md3_header* header = reinterpret_cast<MD3Header*>(&data.front()); //LINE WONT COMPILE
	std::cout<<std::hex<<header->ident<<std::endl;
	for(int32_t i = 0; i < header->num_frames; ++i) {
			md3_frame* frame = reinterpret_cast<md3_frame*>(&data.front() + header->ofs_frames) + i;
			std::cout<<frame->name<<std::endl;
	}

};

and this is my header
Md3Asset.h
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdint>
#include <iterator>
#include "GameAsset.h"
using namespace std;
#ifndef MD3ASSET_H_
#define MD3ASSET_H_
class Md3Asset : public GameAsset {
public :
Md3Asset();
Md3Asset(const string &filename);
virtual ~Md3Asset();
virtual void update();
private:
void import_md3_asset(const string &filename);
struct Vec3 {
  float x, y, z;
};
struct md3_header {
  int32_t ident;
  int32_t version;
  char name[64];
  int32_t flags;
  int32_t num_frames;
  int32_t num_tags;
  int32_t num_surfaces;
  int32_t num_skins;
  int32_t ofs_frames;
  int32_t ofs_tags;
  int32_t ofs_surfaces;
  int32_t ofs_eof;
};
struct md3_frame
{
  Vec3 min_bounds;
  Vec3 max_bounds;
  Vec3 local_origin;
  float radius;
  char name[16];
};
struct md3_tag {
  char name[64];
  Vec3 origin;
  Vec3 axis[3][3];
};
struct md3_surface
{
  int32_t ident; //Stores the identity
  char name[64]; //Stores the surface name
  int32_t flags; //Stores the flags
  int32_t num_frames; //Stores the number of frames
  int32_t num_shaders; //Stores the number of shaders
  int32_t num_verts; //Stores the number of vertices
  int32_t num_triangles; //Stores the number of triangles
  int32_t ofs_triangles; //Stores the offset triangles
  int32_t ofs_shaders; //Stores the offset shaders
  int32_t ofs_ST; //Stores the offset starts
  int32_t ofs_xyzNormal; //Stores the offset starting positions
  int32_t ofs_end; //Stores the offset surface ends
};
struct md3_shader
  {
   char name[64]; //Stores the file name
   int32_t shader_index; //Stores the shader index number
  };
  struct md3_triangle
  {
   int32_t 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
  };
};
#endif

Its ok i have changed the line and the code is compiling BUT, when i click build, it builds it then displays a box for a split second and then just dissappears... I now put the load line as this
std::ifstream fin("data/lara/lara_head.MD3", std::ios::binary | std::ios::in);
and i now get this but still closes
33504449
(from 3DSMax)

#19 Ectara   Crossbones+   -  Reputation: 3015

Like
1Likes
Like

Posted 30 April 2012 - 11:24 AM

Just a quick check before we go further, the endianness of the file does match that of your machine, right?




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS