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.