This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| 3DS Loader Submitted by

This bit of code is a bare bones .3ds model loader. It only reads in vertices and polygon indices for one object right now. In the beginning stages of an engine, it's nice to get models in quickly to test with. Later on, once things are working well, you can just toss this code out in favor of a loader for custom file format. Just grab the .3ds spec from www.wotsit.org and change the code in the switch statement to reflect the innards of your engine.
Chris Thompson aka "Lightman"

Download Associated File: 3dsloader.cpp (3,273 bytes)

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

    struct CPolygon
    {
        int verts[3];
    };

    struct CModel
    {
        CVertex* verts;
        int numverts;
        CPolygon* polys;
        int numpolys;
    };

    CModel g_model;

    // Load3DS
    //
    // Load a .3ds file into memory for parsing
    //
    int Load3DS(char* filename)
    {
        ifstream    file;
        bool        doneloading = false;
        int         filelength;
        char*       memfile;        // file loaded into memory

        // load entire file into memory (easier to deal with)
        file.open(filename, ios::binary);
        file.seekg(0, ios::end);
        filelength = file.tellg();
        memfile = new char[filelength];
        file.seekg(0, ios::beg);
        file.read(memfile, filelength);
        // parse it
        EatChunk(memfile);
        delete memfile;
        return 0;
    }

    // EatChunk
    //
    //  This function recursively handles chunks
    // in a .3ds file.  When the function exits,
    // the return value (i) should be the length
    // of the current chunk.  Right now we only
    // create one model (the first one listed in
    // the file) and read in verts and polys only.
    // To grab other info from the file, create
    // a new case label in the switch statement
    // for the chunk type you want to react to.
    //
    long EatChunk(char* buffer)
    {
        short   chunkid;
        long    chunklength;
        int     i = 0;  // index into current chunk
        int     j;

        chunkid = *(short*)(buffer);
        chunklength = *(long*)(buffer+2);
        i = 6;
        switch (chunkid)
        {
        case 0x4D4D:    // main file
            while ((*(short*)(buffer+i) != 0x3D3D) &&
                (*(short*)(buffer+i) != 0xB000))
                i += 2;
            break;
        case 0x3D3D:    // editor data
            break;
        case 0x4000:    // object description
            while (*(buffer+(i++)) != 0);   // get past string description
            break;
        case 0x4100:    // triangular polygon list
            break;
        case 0x4110:    // vertex list
            if (g_model.numverts == NULL)
            {
                g_model.numverts = *(short*)(buffer+i);
                i+=2;
                g_model.verts = new CVertex[g_model.numverts];
                for (j=0;j<g_modelnumverts;j++)
                {
                    g_model.verts[j].x = *(float*)(buffer+i);
                    i+=4;
                    g_model.verts[j].y = *(float*)(buffer+i);
                    i+=4;
                    g_model.verts[j].z = *(float*)(buffer+i);
                    i+=4;
                }
            }
            else
                i = chunklength;
            break;
        case 0x4120:
            if (g_model.numpolys == NULL)
            {
                g_model.numpolys = *(short*)(buffer+i);
                i+=2;
                g_model.polys = new CPolygon[g_model.numpolys];
                for (j=0;j<numpolys;j++)
                {
                    g_model.polys[j].verts[0] = *(short*)(buffer+i);
                    i+=2;
                    g_model.polys[j].verts[1] = *(short*)(buffer+i);
                    i+=2;
                    g_model.polys[j].verts[2] = *(short*)(buffer+i);
                    i+=2;
                    i+=2;   // skip face info
                }
            }
            else
                i = chunklength;
            break;
        default:
            i = chunklength;    // skips over rest of chunk (ignores it)
            break;
        }

        // eat child chunks
        while (i < chunklength)
            i += EatChunk(buffer+i);
        return chunklength;
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.