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.

 

  Yet Another 3DS Loader
  Submitted by



This is a minimal C++ 3ds mesh geometry loader. I use it (and maintain it) for my 3d engine "DexVT", which can be found on my site.

If you like clean, minimal OOP code like I do, then this loader is for you. it manages to stay out of your code as much as possible.

Jerry Chen (Dextre)
http://onlyuser.cjb.net

Currently browsing [yet_another_3ds_loader.zip] (2,976 bytes) - [FileSys.cpp] - (3,716 bytes)

#include "FileSys.h"

void FileSys::load3ds(char *filename, int index, IScene *scene) { if (FILE *stream = fopen(filename, "rb")) { fseek(stream, 0, SEEK_END); long size = ftell(stream); rewind(stream); long mainEnd = enterChunk(stream, MAIN3DS, size); long editEnd = enterChunk(stream, EDIT3DS, mainEnd); int count = 0; while (ftell(stream) < editEnd) { long objEnd = enterChunk(stream, EDIT_OBJECT, editEnd); char buf[80]; readString(stream, buf); /* read object name */ int objType = readShort(stream); fseek(stream, -1 * sizeof(short), SEEK_CUR); /* rewind */ if (objType == OBJ_TRIMESH) { if (count == index || index == -1) { long meshEnd = enterChunk(stream, OBJ_TRIMESH, objEnd); if (meshEnd != 0) { long meshBase = ftell(stream); //========================================================= enterChunk(stream, TRI_VERTEXL, meshEnd); int vertCnt = readShort(stream); fseek(stream, meshBase, SEEK_SET); //========================================================= enterChunk(stream, TRI_FACEL, meshEnd); int faceCnt = readShort(stream); fseek(stream, meshBase, SEEK_SET); //========================================================= IMesh *mesh = scene->addMesh(buf, vertCnt, faceCnt); //========================================================= enterChunk(stream, TRI_VERTEXL, meshEnd); readVertList(stream, mesh); fseek(stream, meshBase, SEEK_SET); //========================================================= enterChunk(stream, TRI_FACEL, meshEnd); readFaceList(stream, mesh); fseek(stream, meshBase, SEEK_SET); //========================================================= } fseek(stream, meshEnd, SEEK_SET); } else break; count++; } fseek(stream, objEnd, SEEK_SET); } fclose(stream); } }

inline long FileSys::enterChunk(FILE *stream, long chunkID, long chunkEnd) { long offset = 0; while (ftell(stream) < chunkEnd) { long pChunkID = readShort(stream); long chunkSize = readLong(stream); if (pChunkID == chunkID) { offset = -1 * (sizeof(short) + sizeof(long)) + chunkSize; break; } else { fseek(stream, -1 * (sizeof(short) + sizeof(long)), SEEK_CUR); /* rewind */ fseek(stream, chunkSize, SEEK_CUR); /* skip this chunk */ } } return ftell(stream) + offset; }

inline void FileSys::readVertList(FILE *stream, IMesh *mesh) { float *vertex = new float[3]; fseek(stream, sizeof(short), SEEK_CUR); /* skip list size */ for (int i = 0; i < mesh->getVertCnt(); i++) { fread(vertex, sizeof(float), 3, stream); mesh->setVertex(i, vertex[0], vertex[2], vertex[1]); } delete []vertex; }

inline void FileSys::readFaceList(FILE *stream, IMesh *mesh) { short *pFace = new short[3]; fseek(stream, sizeof(short), SEEK_CUR); /* skip list size */ for (int i = 0; i < mesh->getFaceCnt(); i++) { fread(pFace, sizeof(short), 3, stream); mesh->setFace(i, pFace[0], pFace[2], pFace[1]); fseek(stream, sizeof(short), SEEK_CUR); /* skip face info */ } delete []pFace; }

inline short FileSys::readShort(FILE *stream) { BYTE loByte; BYTE hiByte; fread(&loByte, sizeof(BYTE), 1, stream); fread(&hiByte, sizeof(BYTE), 1, stream); return MAKEWORD(loByte, hiByte); }

inline long FileSys::readLong(FILE *stream) { short loWord = readShort(stream); short hiWord = readShort(stream); return MAKELONG(loWord, hiWord); }

inline void FileSys::readString(FILE *stream, char *buf) { int i = 0; while ((buf[i++] = fgetc(stream)) != 0); }

Currently browsing [yet_another_3ds_loader.zip] (2,976 bytes) - [IScene.h] - (202 bytes)

#ifndef H_ISCENE
#define H_ISCENE

#include "IMesh.h"

class IScene { public: virtual IMesh *addMesh(char *id, int vertCnt, int faceCnt) = 0; virtual void remMesh(char *id) = 0; };

#endif

Currently browsing [yet_another_3ds_loader.zip] (2,976 bytes) - [IMesh.h] - (265 bytes)

#ifndef H_IMESH
#define H_IMESH

class IMesh { public: virtual int getVertCnt() = 0; virtual int getFaceCnt() = 0; virtual void setVertex(int index, float x, float y, float z) = 0; virtual void setFace(int index, int a, int b, int c) = 0; };

#endif

Currently browsing [yet_another_3ds_loader.zip] (2,976 bytes) - [FileSys.h] - (778 bytes)

#ifndef H_FILESYS
#define H_FILESYS

#include <windows.h> // BYTE #include <stdio.h> // fopen(), fclose() #include "IScene.h" #include "IMesh.h"

#define MAIN3DS 0x4D4D #define EDIT3DS 0x3D3D #define EDIT_OBJECT 0x4000 #define OBJ_TRIMESH 0x4100 #define TRI_VERTEXL 0x4110 #define TRI_FACEL 0x4120

class FileSys { private: static inline long enterChunk(FILE *stream, long chunkID, long chunkEnd); static inline void readVertList(FILE *stream, IMesh *mesh); static inline void readFaceList(FILE *stream, IMesh *mesh); static inline short readShort(FILE *stream); static inline long readLong(FILE *stream); static inline void readString(FILE *stream, char *buf); public: static void load3ds(char *filename, int index, IScene *scene); };

#endif

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.