Endian-independent float loading (MD2)

Started by
5 comments, last by Ravuya 18 years, 5 months ago
Hey, I'm loading md2 files from binary on my Mac, based on this tutorial: Clicky. I am, of course, not dumb enough to load entire structures with fread, so I read the individual integers into the header with a little endian-independence wrapper and SDL's little endian flipper. The problem is that when I jump to the triangle offset and start reading, the first 256 or so triangles are (0,0,0) and then they go to insane exponent problems (including NaN for some vertices). I've tried it with some md2s from PolyCount as well. AFAIK this swapping should be fine! I think there's something screwing up somewhere else (link to the rest of my source at the bottom).

inline Uint32 AEndian(const Uint32 x)
{return (x>>24)|(x>>8)&0x0000ff00|(x<<8)&0x00ff0000|(x<<24);}
// SDL_SwapLE32 does the same thing as AEndian, this is just here to test

inline float floatSwap(const float x) 
{
    Uint32 retval = AEndian(*((Uint32*)&x));
    return *((float*)&retval);
}

inline float loadFloat(float src) {
	return floatSwap(src);
}

inline int getInteger(FILE* fp, int &result, bool swap = true) {
	int dummy = 0;
	fread(&dummy, 1, sizeof(int), fp);
	//printf("Got %i\n", dummy);
	if(swap) {
		result = loadInteger(dummy);
	}
	else {
		result = dummy;
	}
	return 1;
}

inline void getFloat(FILE* fp, float &result) {
	float dummy = 0;
	fread(&dummy, 1, sizeof(float), fp);
	if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
		result = loadFloat(dummy);
	}
	else {
		result = dummy;
	}
}






I call getFloat on the members of the 'triangle' array, like this:
for(int i = 0; i < header.numTriangles; i++) {
		for(int j = 0; j < 3; j++) {
			getFloat(fp, tris.vertex[j]);
		}







It ONLY seems to do this for floats -- the magic number and version integers are all OK, and the other integer values in the header seem to be within the realm of sanity:
Header
Skins: 256 x 256
Frame Size: 936
Num Skins: 0
Num Vertices: 224
Num Tex Coords 374
Num Triangles 416
Num GL Commands: 2089
Num Frames 198
Offset Skins: 68
Offset Tex Coords 68
Offset Triangles 1564
Offset Frames 6556
Offset GL commands 191884
Offset End 200240






I'm kind of curious about the two 68's but it makes sense if there's no skin. My wager is that I've got the wrong offset for triangles in the provided file somehow. You can get the whole (temporary) file at this directory for what I've written. I was missing some reads into the headers before but I think I have all of them that were outlined in the tutorial now. I know this is a lot of crap to read, so thanks if you can help [grin] I also have a log of my loading attempt here, which raises further questions: are texture coordinates supposed to be negative? And huge? [Edited by - Ravuya on November 23, 2005 10:11:01 AM]
Advertisement
This doesnt exactly solve your problem, but perhaps will help locate it.

How about you create a to-text exporter, and as you load the model, you export the various parts to a text-based file format?

This way you could do a side-by-side comparison, and pin-point the location where it all goes wrong.

Hope it helps...
OK, now I'm confused -- This page says that the guts of triangle structures are unsigned shorts, and that the vertices aren't coordinates but indices into the array of vertices we have...

If I change it so it loads unsigned shorts instead, it makes a little bit of sense, but then I only have 224 vertices and get something like this:
	Triangle 134: vertex (24064,20992,21248)				normal: (28672,29696,28928)


So now I'm really confused -- which is it, floats or shorts?
Gobshite. I forgot that shorts are multi byte. After flipping them, my values make more sense:

	HeaderSkins: 256 x 256Frame Size: 936Num Skins: 0Num Vertices: 224Num Tex Coords 374Num Triangles 416Num GL Commands: 2089Num Frames 198Offset Skins: 68Offset Tex Coords 68Offset Triangles 1564Offset Frames 6556Offset GL commands 191884Offset End 200240...Triangle 405: vertex (222,127,126)				normal: (359,368,367)	Triangle 406: vertex (222,128,127)				normal: (359,369,368)	Triangle 407: vertex (222,129,128)				normal: (359,370,369)	Triangle 408: vertex (222,130,129)				normal: (359,371,370)	Triangle 409: vertex (222,131,130)				normal: (359,363,371)	Triangle 410: vertex (123,119,223)				normal: (170,166,372)	Triangle 411: vertex (223,119,121)				normal: (372,166,167)	Triangle 412: vertex (119,103,121)				normal: (166,152,167)	Triangle 413: vertex (123,105,119)				normal: (170,151,166)	Triangle 414: vertex (222,223,121)				normal: (359,373,360)	Triangle 415: vertex (222,123,223)				normal: (359,365,373)	Done


But there are still some out of range of my 224 vertices. I'll go back and take another look, I think.
floats... i think...

See if my code helps...
Please notice that the second triple of shorts isn't an index into the normal table (the normals are stored interleaved w/ the vertices, so their indices are a-priori identical w/ those of the vertex) but are texture indices! So the indices you write down in your post are not those of vertices!

typedef struct{    unsigned short vertex[3];   /* vertex indices of the triangle */    unsigned short st[3];       /* tex. coord. indices */} md2_triangle_t;

You are reading this structs, correct (or else you would not have indices at all, I think)?
Quote:Original post by haegarr
Please notice that the second triple of shorts isn't an index into the normal table (the normals are stored interleaved w/ the vertices, so their indices are a-priori identical w/ those of the vertex) but are texture indices! So the indices you write down in your post are not those of vertices!

*** Source Snippet Removed ***
You are reading this structs, correct (or else you would not have indices at all, I think)?


Well, that makes a lot more sense! Thanks a lot, now it seems to work [grin] It looks like the original tutorial I read was full of shit.

Now I can continue. Ratings for all!

This topic is closed to new replies.

Advertisement