MD2 Loader Woes

Post your questions, suggestions and experiences regarding game design, integration of external libraries here. For irrEdit, irrXML and irrKlang, see the
ambiera forums
Post Reply
RustyNail
Posts: 168
Joined: Fri Jun 02, 2006 1:49 pm
Contact:

MD2 Loader Woes

Post by RustyNail »

Well, I finally decided that static worlds in a custom text-based format are not good enough for me, and so I decided to create an MD2 Loader for my engine... The results:
Image

Any ideas on what is happening to the model? (It's the sydney model from Irrlicht's media folder...)
I'm rendering it with the MD2 GL Commands, but I get the same result if I use the Triangle data :-/ ...
I have recently discovered that both the Flu and my Algebra teacher have exact the same effect on my health: it quickly degrades.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

I've worked with some model loaders in my time and it's a rite of passage to see these sorts of things on your screen before it actually works properly :lol:

Did you copy the irrlicht MD2 laoder or was it another one you found online?

It could be that you're passing the wrong things to the draw commands, posting some of your code might help :)
Image Image Image
RustyNail
Posts: 168
Joined: Fri Jun 02, 2006 1:49 pm
Contact:

Post by RustyNail »

Heh. I was waiting for the code question :)
Now as for where I got the loader... I wrote it myself looking at the MD2 Format Specifications... Here's the loader:

Code: Select all

    std::ifstream file(fileName.c_str(), std::ios::binary);
    int magicNum;
    int version;
    //
    int texW, texH;
    //
    file.read((char*)(&magicNum), 4);
    file.read((char*)(&version), 4);
    (rust::cLogfileManager::getInstance())->writeToLog("Opening MD2 File...");

    if ((magicNum == MD2_MAGICNUM) && (version == 8)) {
        (rust::cLogfileManager::getInstance())->writeToLog("Opened MD2 File...");
        file.read((char*)(&texW), 4);
        file.read((char*)(&texH), 4);

        file.seekg(24); //Go to number of vertices in frame...
        file.read((char*)(&this->vertPerFrame), 4); // read verticies in frame...

        file.read((char*)(&this->numTexCoords), 4); //read number of tex coordinates in model
        file.read((char*)(&this->numTriangles), 4);

        file.seekg(36); //Go to number of GLCommands
        file.read((char*)(&this->numGLCommands), 4); // read number of GLCommands

        file.read((char*)(&this->numFrames), 4); //readnumber of frames

        int texCoordOffset, frameOffset, glCmdOffset;

        file.seekg(48); //Go to offset for tex coords;
        file.read((char*)(&texCoordOffset), 4); // read offset to tex coords

        file.seekg(56);
        file.read((char*)(&frameOffset), 4); //read offset to verts, frames

        file.read((char*)(&glCmdOffset), 4); //read offset to glCommands

        /////////////////////////
        ///////Read DATA/////////
        /////////////////////////

        //1. Tex Coords
        file.seekg(texCoordOffset);
        this->texCoords = new rust::cVector2f[this->numTexCoords];
        for(int i = 0; i < this->numTexCoords; i++){
            short U;
            short V;
            file.read((char*)(&U), 2);
            file.read((char*)(&V), 2);
            this->texCoords[i].fX = U/texW;
            this->texCoords[i].fY = V/texH;
        }
        //2. Verticies (automatically un-compressing them)
        file.seekg(frameOffset);
        this->verts = new rust::cVector3f[this->vertPerFrame * this->numFrames];
        char frameNames[this->numFrames][16];
        for(int frame = 0; frame < this->numFrames; frame++) {
            rust::cVector3f scale;
            rust::cVector3f translate;
            //Read Scale Vector
            file.read((char*)(&scale.fX), 4);
            file.read((char*)(&scale.fY), 4);
            file.read((char*)(&scale.fZ), 4);
            //Read Translation Vector
            file.read((char*)(&translate.fX), 4);
            file.read((char*)(&translate.fY), 4);
            file.read((char*)(&translate.fZ), 4);
            //read Frame Name
            file.read(&(frameNames[frame][0]), 16);
            for(int vert = 0; vert < this->vertPerFrame; vert++){
                char X, Y, Z;
                file.read(&X, 1);
                file.read(&Y, 1);
                file.read(&Z, 1);

                char lNorm;
                file.read(&lNorm, 1);
                //this->verts[(frame + 1) * (vert + 1) - 1].fX = scale.fX * X + translate.fX;
                //this->verts[(frame + 1) * (vert + 1) - 1].fY = scale.fY * Y + translate.fY;
                //this->verts[(frame + 1) * (vert + 1) - 1].fZ = scale.fZ * Z + translate.fZ;
                this->verts[vert + frame * this->vertPerFrame].fX = scale.fX * X + translate.fX;
                this->verts[vert + frame * this->vertPerFrame].fY = scale.fY * Y + translate.fY;
                this->verts[vert + frame * this->vertPerFrame].fZ = scale.fZ * Z + translate.fZ;
            }
        }
        //3. GL Commands
        this->glCommands = new int[this->numGLCommands];
        file.seekg(glCmdOffset);
        for(int i = 0; i < this->numGLCommands; i++){
            file.read((char*)&(this->glCommands[i]), 4);
        }

        this->oneFrame = new rust::cVector3f[this->vertPerFrame];
        setFrame(45);
    }
    file.close();
And the display code:

Code: Select all

    int i = 0;
    for(; i < this->numGLCommands;) {
        if (this->glCommands[i] != 0) {
            int numVert;
            if (this->glCommands[i] > 0) {
                glBegin(GL_TRIANGLE_STRIP);
                numVert = this->glCommands[i];
            }else{
                glBegin(GL_TRIANGLE_FAN);
                numVert = -this->glCommands[i];
            }
            //i++;
            for(int vert = 0; vert < numVert; vert++){
                glTexCoord2f(*((float*)(&this->glCommands[++i])), *((float*)(&this->glCommands[++i])));
                i++;
                glVertex3f(this->oneFrame[this->glCommands[i]].fX,
                            this->oneFrame[this->glCommands[i]].fY,
                            this->oneFrame[this->glCommands[i]].fZ);
            }
            glEnd();
        }
        i++;
    }
I have recently discovered that both the Flu and my Algebra teacher have exact the same effect on my health: it quickly degrades.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Well in that case i would compare it against a working MD2 loader, such as the irrlicht one or google for one as then you can see where you might have gone wrong.

And also, make sure you get rid of all those individual file reads, that will be seriously slow. You're much better off reading the entire file into memory at the start and then reading through the memory to get the data out. One big file read is a helluva lot quicker than thousands of individual file reads, which is what you're doing there.

It can be tricky to convert it but it will speed up the file load massively so is definitely worth it!
Image Image Image
RustyNail
Posts: 168
Joined: Fri Jun 02, 2006 1:49 pm
Contact:

Post by RustyNail »

Slow? meh. :D
I'd be happy if it worked... I can make it work faster later...
Why have a lightning-fast loader that loads garbage? :lol:
But I see your point.
A/w, it's strange, if I do some close-ups of the loaded model, I do see some elements of the model loaded CORRECTLY, but badly texture-mapped...
Like the left arm is loaded correctly on some frames...
And the worst bit is - I have no idea on where I screwed up!
If it crashed, I could track it down... But if it doesn't... ><
I have recently discovered that both the Flu and my Algebra teacher have exact the same effect on my health: it quickly degrades.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Yeah this is the difficulty with model loaders that i've had, you get something on screen but it's definetly not right. And sometimes you even get the proper outline of the model but then there's some really weird stretched polygons and missing polygons and it's just mind boggling!

But i guess if you've got the right shapes then it's probably loaded the data properly but is being drawn wrongly. I've never used the GL commands in MD2 models so i can't really advise anything there or think what might be wrong...

As you say, it's better to get the model loader loading and rendering properly before optimising the load time so it's something you can consider later.
Image Image Image
RustyNail
Posts: 168
Joined: Fri Jun 02, 2006 1:49 pm
Contact:

Post by RustyNail »

Do you know if they fixed the MD2 Exporter for Blender? :roll:
Then i'd just make a cube, export it, and see what it looks like...
And work from there...
I have recently discovered that both the Flu and my Algebra teacher have exact the same effect on my health: it quickly degrades.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

No idea, try exporting a cube into irrlicht and see if that works ;)
Image Image Image
RustyNail
Posts: 168
Joined: Fri Jun 02, 2006 1:49 pm
Contact:

Post by RustyNail »

Hmmm... I tried displaying the MD2 Model using the triangle data, and got the sam results... I'm starting to think that I'm uncompressing the verts wrongly... :roll:
I have recently discovered that both the Flu and my Algebra teacher have exact the same effect on my health: it quickly degrades.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

read takes a void*, so casting is not necessary at all. However, this will only work on the same endianess, otherwise neither floats nor ints will work. And yes, the bits are directly copied into the memory location
RustyNail
Posts: 168
Joined: Fri Jun 02, 2006 1:49 pm
Contact:

Post by RustyNail »

After exporting the standard Blender cube & loading it & printing all the vertices & finding it in some obscure point of the world,
it became obvious that the cube was being displayed properly (except the fact, that all the verts were winding counter-clockwise, but that's not related to my problem) but it was not a cube, it was.... squished on the Z axis -> I am loading the vertices incorrectly. but I cannot figure out WHAT I am doing wrong... ><

EDIT: Nevermind, fixed it.
I am an Idiot. I was loading the compressed coordinates into SIGNED CHARS,
while they should have been UNSIGNED CHARS. I edited 4 lines. And VOILA! The geometry is getting loaded properly. Only need to fix some UV Coord loading heresy, probably also related to signed/unsigned chars, i think.... And then implement linear interpolation & animation... and i'm off making my own version of SWKotOR! :lol:
I have recently discovered that both the Flu and my Algebra teacher have exact the same effect on my health: it quickly degrades.
Post Reply