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.