Whats the deal with "byte"?

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

They should behave the same. A byte is always 8 bits so “unsigned char” should work the same since it is also 8 bits.

Learn assembly language and you will see why
people use typedefs like byte, word, and dword.

Or better than learning assembly language, how about you teach me assembly language?

Well ok I guess I’ll keep trying with chars

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.

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.

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.

… 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.

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.

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.

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?

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

So GL Man maybe you could help me out?

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

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

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

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.

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(&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

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

I made your changes but it still crashes
Thanks for your help GL Man you rock