PDA

View Full Version : Whats the deal with "byte"?



31337
12-08-2002, 10:39 AM
I've been reading tutorials on loading MD2's and they say things like "byte vertices[3]" They are visual c++ tutorials too (I'm using Visual C++). However, when I try to do byte vertices[3] in my code it whines and complains. I asked a friend and he said to just use unsigned chars instead. Will they act the same exact way? When I multiply em and stuff will they act the same as a "byte"? Thanks

GameMaker
12-08-2002, 11:20 AM
They should behave the same. A byte is always 8 bits so "unsigned char" should work the same since it is also 8 bits.

Syslock
12-08-2002, 12:31 PM
Learn assembly language and you will see why
people use typedefs like byte, word, and dword.

31337
12-08-2002, 02:21 PM
Or better than learning assembly language, how about you teach me assembly language? http://www.opengl.org/discussion_boards/ubb/smile.gif

Well ok I guess I'll keep trying with chars

josip
12-08-2002, 03:04 PM
Originally posted by 31337:
I asked a friend and he said to just use unsigned chars instead. Will they act the same exact way? When I multiply em and stuff will they act the same as a "byte"? Thanks

They 'should' act the same, but I'd recommend creating a header file w/ all the standard types (unsigned/signed char, unsigned/signed int, double, float, etc.) typedef'd. The reason being that an 'int' is not necessarily a 32-bit (4 byte) value. The same applies for the other types, so you need to account for that, assuming you're trying to be cross-platform.

This becomes an issue when you try loading a file and dump it directly into a structure. If the size is not what you expected, you're in trouble.

Sephiroth
12-08-2002, 04:20 PM
A "BYTE" is an unsigned char. Here is how it looks in the header.



//Some C/C++ header...

typedef unsigned char BYTE;

So using BYTE or usigned char will yield the result you need. By the way, aside from MD2 loading, you know anything about actually animating models? I can load and display/rotate/move them for hours, but I can't figure out animation.

31337
12-08-2002, 04:31 PM
No sorry I havn't done animation yet (gametutorials.com has some great tutorials on it though)

My question is this: I am fread()ing these "bytes" into unsigned chars, and then I need to multiply these unsigned chars by floats and I need to get floats. Is this going to work?

I asked another programmer and he said it wouldn't. He said I would need to convert the binary numbers or something and I don't know what he's talking about. Oh well I'll just use unsigned chars for now I guess.

Bob
12-08-2002, 04:59 PM
... and then I need to multiply these unsigned chars by floats and I need to get floats. Is this going to work?

Yes, it will work. The integer types will be converted to floats before multiplication, and the return type is, of course, a float.

31337
12-08-2002, 05:10 PM
Guys!!!! To use bytes you need to include windows.h, and seeing as how my game is for windows...

So I included windows.h and now I'm using bytes.

Sephiroth
12-08-2002, 05:21 PM
Not all compilers use "BYTE" typedefs. I have seen several that just give you the basic types with a few others, or just the basic types alone. I personally have all the types that I am aware of with Borland, but once again, each distro has it's own flavor, kind of like Linux.

31337
12-08-2002, 05:48 PM
Question - why does my program crash while doing this loop?




triVert = new triangleVertex [header.numVertices];
for(i = 0; i<header.numVertices; i++) {
triVert[i].vertex[0] = ((float)frames[0].vertices[i].vertex[0] * frames[0].scale[0]) + frames[0].translate[0];
triVert[i].vertex[1] = ((float)frames[0].vertices[i].vertex[1] * frames[0].scale[1]) + frames[0].translate[1];
triVert[i].vertex[2] = ((float)frames[0].vertices[i].vertex[2] * frames[0].scale[2]) + frames[0].translate[2];
}



I'm pretty sure that it isn't memory overflow because I cout << i << endl; and it never displays ANYTHING so I'm guessing its a problem with multiplying type byte with floats. Am I correct in my thinking?

Old GLman
12-08-2002, 07:08 PM
Ive never played around with md2's, so just out of curiosity can someone tell me why they are storing vertices as bytes? Or perhaps they are indices?

EDIT: Ah, nm, I figured it out.

[This message has been edited by Old GLman (edited 12-08-2002).]

31337
12-08-2002, 08:10 PM
So GL Man maybe you could help *me* out? http://www.opengl.org/discussion_boards/ubb/smile.gif

Old GLman
12-08-2002, 09:17 PM
Nah, its not a problem with multiplying floats and bytes, in fact you dont even have to cast it to float. Its hard to tell what could be going wrong without seeing your structures, or seeing how you are allocating memory for the frame, but the way they're doing it in the game tutorials tutorial is to:

1. Allocate a buffer of size MD2_MAX_FRAMESIZE. This buffer is of type byte.

2. Keep a pointer to buffer memory.

3. Read in the whole frame into the buffer.

4. Use the pointer to traverse the buffer.

Im sure you have seen this tut?? If so I would use it as a reference to make sure you are doing everything correctly. Chances its a memory problem.

Old GLman

31337
12-09-2002, 11:20 AM
Yah I've been reading that tutorial a lot however I'm not as fluent in C/C++ as you so its harder for me to see. What I've done is I've loaded the data into the same structures as that tutorial, but now I'm at the same point as their "modifyData" function I think it is. The one that comes after loading the data.

How do you think I should go about doing this? Thanks

Old GLman
12-09-2002, 01:27 PM
Well it looks like they are just moving the data from the md2 structures into there own structure. I think DigiBen did this because he wanted to eventually have it handle several different types of model formats. This way rendering models of different formats is the same for each model. I would put all the data into a vertex array, tex array, etc... so you can conviniently render it with one call to glDrawElements. I believe this would make it easier for animation to, because you have access to the data.

Old GLman

31337
12-09-2002, 02:15 PM
I agree with you and I have attempted to do that however to no avail. When I get home from school along with access to Visual C++ I'll work on it and see if I can get something happening.

31337
12-09-2002, 05:25 PM
Alright I'm trying to format the vertices and establish space for the normals however my program crashes. I have pinpointed the line and I don't have the faintest idea of why. I've done my best to debug my program however I'm not very experienced with it so I couldn't locate the problem. Here's the cpp file for my md2 loader:




#include "MD2.h"
#include <fstream.h>
#include <stdio.h>
#include <gl\glaux.h> // Header File For The GLaux Lib
#include <stdio.h> // Header File For Input/Output
#include <gl\gl.h> // Header File For The GL Library
#include <gl\glu.h> // Header File For The GLu Library
#include <iostream.h> // Header for C++ console input/output
#include <fstream.h> // Header for C++ file I/O
#include <string.h> // Header for working with strings
#include <gl\glut.h> // Header for GLUT
#include <math.h> // Header for sine and cosine
#include <gl\glfw.h> // Header for glfw
#include <stdarg.h>


// Here's the maximums and minimums for a valid MD2 file
// As specified by ID software
#define MAX_TRIANGLES 4096
#define MAX_VERTICES 2048
#define MAX_TEXTURE_COORDINATES 2048
#define MAX_FRAMES 512
#define MAX_SKINS 32

#define TOOLARGE 1
#define DONE 0
#define FAIL -1

MD2::MD2() {

}

MD2::~MD2() {
// Free all of the dynamic memory
delete []skin;
delete []triangles;
delete []frames;
delete []finaltexcords;
}

int MD2::loadMD2(const char *filename) {
FILE *inputfile = fopen(filename, "rb");
if(!inputfile) {
return FAIL;
}
// First step: READ the HEADER
fread(&amp;header, 1, sizeof(Header), inputfile);
if(MD2::verifyMD2()==FAIL) {
cout << "VERIFYING MD2 " << filename << " FAILED" << endl;
return FAIL;
}
// The header must be valid so far
// Establish the much needed memory for the job
skin = new skinName [header.numSkins];
triangles = new triangle_t [header.numTriangles];
frames = new frame_t [header.numTriangles];
for(int i = 0; i<header.numFrames; i++) {
frames[i].vertices = new triangleVertex_t [header.numVertices];
}
texcords = new textureCoordinate_t [header.numTexCoords];

fseek(inputfile, header.offsetSkins, SEEK_SET);
fread(skin, sizeof(skinName), header.numSkins, inputfile);

fseek(inputfile, header.offsetFrames, SEEK_SET);
fread(frames, sizeof(frames[0]), header.numFrames, inputfile);

fseek(inputfile, header.offsetTriangles, SEEK_SET);
fread(triangles, sizeof(triangle_t), header.numTriangles, inputfile);

fseek(inputfile, header.offsetTexCoords, SEEK_SET);
fread(texcords, sizeof(textureCoordinate_t), header.numTexCoords, inputfile);

fclose(inputfile);
formatMD2();
return DONE;
}

int MD2::formatMD2() {
// Our first task is to correctly scale the texture coordinates
finaltexcords = new finalTex [header.numTexCoords];
for(int i = 0; i<header.numTexCoords; i++) {
finaltexcords[i].x = (float)texcords[i].s / (float)header.skinWidth;
finaltexcords[i].y = (float)texcords[i].t / (float)header.skinHeight;
}
delete []texcords; // Free the older outdated texture coordinates
// Now our array of final texture coordinates is complete we go on
// on to format the triangles - lets start by
triVert = new triangle [header.numTriangles * 3];
for(i = 0; i<header.numTriangles; i+=3) {
triVert[i].vertex[0] = (frames[0].vertices[triangles[i].vertexIndices[0]].vertex[0]) * frames[0].scale[0] + frames[0].translate[0];
triVert[i].vertex[1] = frames[0].vertices[triangles[i].vertexIndices[0]].vertex[1] * frames[0].scale[1] + frames[0].translate[1];
triVert[i].vertex[2] = frames[0].vertices[triangles[i].vertexIndices[0]].vertex[2] * frames[0].scale[2] + frames[0].translate[2];

triVert[i+1].vertex[0] = frames[0].vertices[triangles[i+1].vertexIndices[1]].vertex[0] * frames[0].scale[0] + frames[0].translate[0];
triVert[i+1].vertex[1] = frames[0].vertices[triangles[i+1].vertexIndices[1]].vertex[1] * frames[0].scale[1] + frames[0].translate[1];
triVert[i+1].vertex[2] = frames[0].vertices[triangles[i+1].vertexIndices[1]].vertex[2] * frames[0].scale[2] + frames[0].translate[2];

triVert[i+2].vertex[0] = frames[0].vertices[triangles[i+2].vertexIndices[2]].vertex[0] * frames[0].scale[0] + frames[0].translate[0];
triVert[i+2].vertex[1] = frames[0].vertices[triangles[i+2].vertexIndices[2]].vertex[1] * frames[0].scale[1] + frames[0].translate[1];
triVert[i+2].vertex[2] = frames[0].vertices[triangles[i+2].vertexIndices[2]].vertex[2] * frames[0].scale[2] + frames[0].translate[2];
}

return DONE;
}

int MD2::verifyMD2() {
if(header.version!=8)
return FAIL;
if(header.magic!=844121161)
return FAIL;
if(header.numTriangles>MAX_TRIANGLES)
return TOOLARGE;
if(header.numVertices>MAX_VERTICES)
return TOOLARGE;
if(header.numTexCoords>MAX_TEXTURE_COORDINATES)
return TOOLARGE;
if(header.numFrames>MAX_FRAMES)
return TOOLARGE;
if(header.numSkins>MAX_SKINS)
return TOOLARGE;
return DONE;
}


and here's the header file:




#ifndef _MD2_H
#define _MD2_H

typedef struct // A place to store the header for an md2 file
{
int magic;
int version;
int skinWidth;
int skinHeight;
int frameSize;
int numSkins;
int numVertices;
int numTexCoords;
int numTriangles;
int numGlCommands;
int numFrames;
int offsetSkins;
int offsetTexCoords;
int offsetTriangles;
int offsetFrames;
int offsetGlCommands;
int offsetEnd;
} Header;

// For the triangles
typedef struct
{
short vertexIndices[3];
short textureIndices[3];
} triangle_t;

typedef struct
{
float vertex[3];
float normal[3];
} triangle;

// For the frames

typedef struct
{
unsigned char vertex[3];
unsigned char lightNormalIndex;
} triangleVertex_t;

typedef struct
{
float scale[3];
float translate[3];
char name[16];
triangleVertex_t *vertices;
} frame_t;

/* Done with structures storing frame info */

/* For the texture coordinates */
typedef struct
{
short s, t; // The x and the y for the texture coordinate
} textureCoordinate_t;

typedef struct
{
float x,y; // A finalized texture coordinate
} finalTex;

/* Done storing information for texture coordinates */

typedef struct
{
short s, t; // The x and y for a texture coordinate
} TexCord;

class MD2 {
public:
MD2();
~MD2();
int loadMD2(const char *filename); // load the MD2
int verifyMD2(); // Verify that its a valid MD2
int formatMD2(); // Format the MD2 memory for drawing
//int drawMD2(int mode); // Draw the MD2
private:
typedef char skinName[64];
Header header;
skinName *skin;
triangle_t *triangles;
triangle *triVert;
frame_t *frames;
textureCoordinate_t *texcords;
finalTex *finaltexcords; // Finalized texture coordinates
float *drawList;
};

#endif


The line it crashes on is in the cpp file in the formatMD2() function. In the for loop at the end of the function it crashes on the first attempt at executing the first command inside of it. Can anybody see why? Thanks

Old GLman
12-09-2002, 07:36 PM
frames = new frame_t [header.numTriangles];


should be:




frames = new frame_t[header.numFrames];


Right?? Makes more sense. And I think that:




fread(frames, sizeof(frames[0]), header.numFrames, inputfile);


is incorrect. Here you are supposed to read in the first frame right? So it should be:




fread(frames,1,header.frameSize,inputfile);


Hope this helps,

Old GLman

[This message has been edited by Old GLman (edited 12-09-2002).]

31337
12-10-2002, 06:21 AM
I made your changes but it still crashes http://www.opengl.org/discussion_boards/ubb/frown.gif
Thanks for your help GL Man you rock

Old GLman
12-10-2002, 08:40 AM
zip up just your source files and email me your code.

31337
12-10-2002, 04:43 PM
done

Old GLman
12-10-2002, 07:09 PM
Ok, it was a memory problem. You were trying to process the frame data without having read it in. I made some changes to the code, so you should be back on track.

First:



typedef struct
{
float scale[3];
float translate[3];
char name[16];
triangleVertex_t vertices[1];
} aliasframe_t;


This structure stores your scaling and translation. Each vert is stored as a byte in the file, presumably to save space. These aren't real coordinates, so thats why you have to scale and translate them back.

Next, I added this structure:



typedef struct
{
char strName[16];
triangle *pVertices;
} frame;


This is the structure that will contain your array of vertices. This frame structure is the one you declare in your MD2 class.

The alias frame structure is just for temporary storage as you will see.

Next, most of the modifications took place in the loadMD2 function. I will show you the changes I made:

After you open the file and such, allocate needed memory:




skin = new skinName[header.numSkins];
triangles = new triangle_t[header.numTriangles];
frames = new frame[header.numFrames];
texcords = new textureCoordinate_t[header.numTexCoords];


Then, read in the following info:




fseek(inputfile, header.offsetSkins, SEEK_SET);
fread(skin, sizeof(skinName), header.numSkins, inputfile);

fseek(inputfile, header.offsetTexCoords, SEEK_SET);
fread(texcords, sizeof(textureCoordinate_t), header.numTexCoords, inputfile);

fseek(inputfile, header.offsetTriangles, SEEK_SET);
fread(triangles, sizeof(triangle_t), header.numTriangles, inputfile);


The next part contains the changes I made.




/* this goes at the top of the file */
#define MD2_MAX_FRAMESIZE (MAX_VERTICES * 4 + 128)

/* this goes somewhere nice in your function */
unsigned char buffer[MD2_MAX_FRAMESIZE];

/* use aliasframe to point to the actual frame data in memory */
aliasframe_t *pframe = (aliasframe_t*)buffer;

/* read in the frame data */
fseek(inputfile, header.offsetFrames, SEEK_SET);
fread(pframe, 1, header.frameSize, inputfile);

/* copy the frame name */
strcpy(frames[0].strName,pframe->name);

/* close the file */
fclose(inputfile);

/* here is the scaling and translation part */
for( int i = 0; i < header.numVertices; i++ )
{
frames[0].pVertices[i].vertex[0] = pframe->vertices[i].vertex[0] * pframe->scale[0] + pframe->translate[0];
frames[0].pVertices[i].vertex[1] = pframe->vertices[i].vertex[2] * pframe->scale[2] + pframe->translate[2];
frames[0].pVertices[i].vertex[2] = -1 * (pframe->vertices[i].vertex[1] * pframe->scale[1] + pframe->translate[1]);
}


Make sure you see what is going on here. You are scaling and translating the vert data thats in memory (buffer) and copying it into your frame vertex array.

Now all the vertex data is in the vertex array, you can do whatever you want with it.
After I made these changes, the huge ugly chunk of for loop in the formatmd2 function started given me crap, so I just deleted it http://www.opengl.org/discussion_boards/ubb/biggrin.gif You should rewrite that anyway, now that everything is much cleaner to work with.

I emailed you back the source.

Old GLman