well.. ive finally finished my loader.. after many irritating hours...
if anyone needs a 3ds loader.. feel free to use my code.. however ull need a vector and a texture class to get it working..
comments and suggestions are welcome...
it supports multiple objects, materials, bumpmaps, diffusemaps and opicaty maps... more maps can easily be added.. just look at the code..
ive got no comments since its pretty much self explaining... ive tried to make it as simple as possible..
thx to all those thats been helping me out...
header
/****************************************************************/
/*********** 3DS LOADER BY DRAGON_STRIKE, ROBERT NAGY ***********/
/****************************************************************/
#ifndef MODEL_3DS_H
#define MODEL_3DS_H
#include "BaseCode/Image.h"
#include "BaseCode/Math/math.h"
#include <cstdio>
#include <cstdlib>
#include <io.h>
#include <vector>
#include <string>
class Model_3DS;
class Object_3DS{
friend Model_3DS;
private:
struct Face{
unsigned short a,b,c;
};
struct MaterialFace {
Face* subFaces;
int numSubFaces;
int MatIndex;
};
std::string Name;
int faces_amount;
int vertices_amount;
Face* Faces;
vec3* Vertices;
vec3* Normals;
vec3* Tangents;
vec2* TexCoords;
std::vector<MaterialFace> MatFaces;
public:
MaterialFace GetMaterialFace(int i) const
{ return MatFaces.at(i);}
int GetNumMatFaces()
{ return MatFaces.size();}
const vec3* GetVertices() const
{ return Vertices; }
const vec3* GetNormals() const
{ return Normals; }
const vec3* GetTangents() const
{ return Tangents; }
const vec2* GetTexCoords() const
{ return TexCoords; }
vec3 GetVertex(int i)
{ return Vertices; }
vec3 GetNormal(int i)
{ return Normals; }
vec3 GetTangent(int i)
{ return Tangents; }
vec2 GetTexCoord(int i)
{ return TexCoords; }
};
class Material_3DS{
friend Model_3DS;
private:
std::string Name;
public:
CIMAGE TextureMap;
CIMAGE BumpMap;
CIMAGE OpicatyMap;
float Ambient[4];
float Diffuse[4];
float Specular[4];
float Shining;
float Transparancy;
float SpecularMat;
float OpacityMat;
float ReflectionMat;
float BumpMat;
};
class Model_3DS
{
private:
void NormalizeVertices();
FILE *file;
std::vector<Object_3DS> m_Object_3DS;
std::vector<Material_3DS> m_Material_3DS;
void F_MATERIAL_BLOCK();
void F_MATERIAL_NAME();
void F_AMBIENT_COLOR();
void F_DIFFUSE_COLOR();
void F_SPECULAR_COLOR();
void F_SHININESS();
void F_TRANSPARACY();
void F_TEXFILE();
void F_OBJECT_BLOCK();
void F_VERTICES_LIST();
void F_FACES_DESCRIPTION();
void F_FACES_MATERIAL();
void F_MAPPING_COORDINATES_LIST();
unsigned int chunk_length;
unsigned short chunk_id;
CIMAGE* CurMap;
public:
Object_3DS GetObject_3DS(int i) const
{ return m_Object_3DS.at(i);}
Material_3DS GetMaterial_3DS(int i) const
{ return m_Material_3DS.at(i);}
int GetNumObjects()
{ return m_Object_3DS.size();}
int GetNumMaterials()
{ return m_Material_3DS.size();}
Model_3DS();
~Model_3DS();
int Load(char* filename);
};
#endif MODEL_3DS_H
body
#define MAIN_CHUNK 0x4D4D
#define EDITOR_CHUNK 0x3D3D
#define OBJECT_BLOCK 0x4000
#define TRIANGULAR_MESH 0x4100
#define VERTICES_LIST 0x4110
#define FACES_DESCRIPTION 0x4120
#define FACES_MATERIAL 0x4130
#define MAPPING_COORDINATES_LIST 0x4140
#define SMOOTHING_GROUP_LIST 0x4150
#define LOCAL_COORDINATES_SYSTEM 0x4160
#define MATERIAL_BLOCK 0xAFFF
#define MATERIAL_NAME 0xA000
#define AMBIENT_COLOR 0xA010
#define DIFFUSE_COLOR 0xA020
#define SPECULAR_COLOR 0xA030
#define SHININESS 0xA040
#define TRANSPARACY 0xA050
#define TEXTURE 0xA200
#define SPECULARMAT 0xA204
#define OPACITYMAT 0xA210
#define REFLECTIONMAT 0xA220
#define BUMPMAT 0xA230
#define TEXFILE 0xA300
#define MAPPING_FILENAME 0xA300
#define MAPPING_PARAMETERS 0xA351
#include "Model_3DS.h"
Model_3DS::Model_3DS()
{
}
Model_3DS::~Model_3DS()
{
}
void Model_3DS::NormalizeVertices()
{
for (int i = 0; i < (int)m_Object_3DS.size(); i++)
{
for (int k = 0; k < m_Object_3DS.at(i).vertices_amount; k++)
{
m_Object_3DS.at(i).Normals[k] = normalize(m_Object_3DS.at(i).Normals[k]);
m_Object_3DS.at(i).Tangents[k] = normalize(m_Object_3DS.at(i).Tangents[k]);
}
}
}
int Model_3DS::Load(char* filename)
{
if (!(file=fopen (filename, "rb")))
return 0;
while (ftell (file) < filelength(fileno (file))) //Loop to scan the whole file
{
fread (&chunk_id, 2, 1, file); //Read the chunk header
fread (&chunk_length, 4, 1, file); //Read the lenght of the chunk
switch (chunk_id)
{
case MAIN_CHUNK:
break;
case EDITOR_CHUNK:
break;
case MATERIAL_BLOCK:
F_MATERIAL_BLOCK();
break;
case MATERIAL_NAME:
F_MATERIAL_NAME();
break;
case AMBIENT_COLOR:
F_AMBIENT_COLOR();
break;
case DIFFUSE_COLOR:
F_DIFFUSE_COLOR();
break;
case SPECULAR_COLOR:
F_SPECULAR_COLOR();
break;
case SHININESS:
F_SHININESS();
break;
case TRANSPARACY:
F_TRANSPARACY();
break;
case OPACITYMAT:
CurMap = &m_Material_3DS.back().OpicatyMap;
break;
case BUMPMAT:
CurMap = &m_Material_3DS.back().BumpMap;
break;
case TEXTURE:
CurMap = &m_Material_3DS.back().TextureMap;
break;
case TEXFILE:
F_TEXFILE();
break;
case OBJECT_BLOCK:
F_OBJECT_BLOCK();
break;
case TRIANGULAR_MESH:
break;
case VERTICES_LIST:
F_VERTICES_LIST();
break;
case FACES_DESCRIPTION:
F_FACES_DESCRIPTION();
break;
case FACES_MATERIAL:
F_FACES_MATERIAL();
break;
case MAPPING_COORDINATES_LIST:
F_MAPPING_COORDINATES_LIST();
break;
default:
fseek(file, chunk_length-6, SEEK_CUR);
}
}
fclose (file);
NormalizeVertices();
return 1;
}
void Model_3DS::F_MATERIAL_BLOCK()
{
Material_3DS tempMaterial_3DS;
tempMaterial_3DS.Name = "";
for (int n = 0; n < 4; n++)
{
tempMaterial_3DS.Ambient[n] = 0.0f;
tempMaterial_3DS.Diffuse[n] = 0.0f;
tempMaterial_3DS.Specular[n] = 0.0f;
}
tempMaterial_3DS.Shining = 0.0f;
tempMaterial_3DS.SpecularMat = 0.0f;
tempMaterial_3DS.OpacityMat = 0.0f;
tempMaterial_3DS.ReflectionMat = 0.0f;
tempMaterial_3DS.BumpMat = 0.0f;
m_Material_3DS.push_back(tempMaterial_3DS);
}
void Model_3DS::F_MATERIAL_NAME()
{
char nchar;
m_Material_3DS.back().Name = "";
int i = 0;
do {
fread (&nchar, 1, 1, file);
m_Material_3DS.back().Name+=nchar;
i++;
} while(nchar != '\0');
}
void Model_3DS::F_AMBIENT_COLOR()
{
fread (&m_Material_3DS.back().Ambient[0], sizeof(int), 3, file);
for (int x = 0; x < 3; x++)
{
m_Material_3DS.back().Ambient [x]= (255.0f - m_Material_3DS.back().Ambient [x]) / 255.0f;
}
m_Material_3DS.back().Ambient [3]=1.0f;
chunk_length = chunk_length-4*3;
fseek(file, chunk_length-6, SEEK_CUR);
}
void Model_3DS::F_DIFFUSE_COLOR()
{
fread (&m_Material_3DS.back().Diffuse[0], sizeof(int), 3, file);
for (int x = 0; x < 3; x++)
{
m_Material_3DS.back().Diffuse[x]= (255.0f - m_Material_3DS.back().Diffuse[x]) / 255.0f;
}
m_Material_3DS.back().Diffuse[3]=1.0f;
chunk_length=chunk_length-4*3;
fseek(file, chunk_length-6, SEEK_CUR);
}
void Model_3DS::F_SPECULAR_COLOR()
{
fread (&m_Material_3DS.back().Specular[0], sizeof(int), 3, file);
for (int x = 0; x < 3; x++)
{
m_Material_3DS.back().Specular[x]= (255.0f - m_Material_3DS.back().Specular[x]) / 255.0f;
}
m_Material_3DS.back().Specular[3]=1.0f;
chunk_length=chunk_length-4*3;
fseek(file, chunk_length-6, SEEK_CUR);
}
void Model_3DS::F_SHININESS()
{
fread (&m_Material_3DS.back().Shining, sizeof(unsigned short), 1, file);
m_Material_3DS.back().Shining/= 100.0f;
chunk_length-=2;
fseek(file, chunk_length-6, SEEK_CUR);
}
void Model_3DS::F_TRANSPARACY()
{
fread (&m_Material_3DS.back().Transparancy, sizeof(unsigned short), 1, file);
m_Material_3DS.back().Transparancy/= 100.0f;
chunk_length-=2;
fseek(file, chunk_length-6, SEEK_CUR);
}
void Model_3DS::F_TEXFILE()
{
char name[20];
char nchar;
int i = 0;
do {
fread (&nchar, 1, 1, file);
name=nchar;
i++;
} while(nchar != '\0' && i < 20);
CurMap->Load(name);
}
void Model_3DS::F_OBJECT_BLOCK()
{
Object_3DS tempObject_3DS;
tempObject_3DS.Name = "";
tempObject_3DS.vertices_amount = 0;
tempObject_3DS.faces_amount = 0;
tempObject_3DS.Vertices = 0;
tempObject_3DS.Normals = 0;
tempObject_3DS.Tangents = 0;
tempObject_3DS.Faces = 0;
tempObject_3DS.TexCoords = 0;
char nchar;
int i=0;
do {
fread (&nchar, 1, 1, file);
tempObject_3DS.Name+=nchar;
i++;
} while(nchar != '\0');
m_Object_3DS.push_back(tempObject_3DS);
}
void Model_3DS::F_VERTICES_LIST()
{
unsigned short amount = 0;
fread (&amount, sizeof (unsigned short), 1, file);
m_Object_3DS.back().vertices_amount = amount;
m_Object_3DS.back().Vertices = new vec3[amount];
m_Object_3DS.back().Normals = new vec3[amount];
m_Object_3DS.back().Tangents = new vec3[amount];
for (int i=0; i<amount; i++)
{
fread (&m_Object_3DS.back().Vertices, sizeof(float), 3, file);
float temp = m_Object_3DS.back().Vertices.y;
m_Object_3DS.back().Vertices.y = m_Object_3DS.back().Vertices.z;
m_Object_3DS.back().Vertices.z = -temp;
m_Object_3DS.back().Normals = 0.0f;
m_Object_3DS.back().Tangents = 0.0f;
}
}
void Model_3DS::F_FACES_DESCRIPTION()
{
unsigned short amount = 0;
unsigned short face_flags = 0;
fread (&amount, sizeof (unsigned short), 1, file);
m_Object_3DS.back().faces_amount = amount;
m_Object_3DS.back().Faces = new Object_3DS::Face[amount];
for (int i=0; i<amount; i++)
{
fread (&m_Object_3DS.back().Faces, sizeof (unsigned short), 3, file);
fread (&face_flags, sizeof (unsigned short), 1, file);
vec3 N = CalculateNormal(m_Object_3DS.back().Vertices[m_Object_3DS.back().Faces.a],
m_Object_3DS.back().Vertices[m_Object_3DS.back().Faces.b],
m_Object_3DS.back().Vertices[m_Object_3DS.back().Faces.c]);
m_Object_3DS.back().Normals[m_Object_3DS.back().Faces.a] += N;
m_Object_3DS.back().Normals[m_Object_3DS.back().Faces.b] += N;
m_Object_3DS.back().Normals[m_Object_3DS.back().Faces.c] += N;
vec3 T = CalculateTangent(m_Object_3DS.back().Vertices[m_Object_3DS.back().Faces.a],
m_Object_3DS.back().Vertices[m_Object_3DS.back().Faces.b],
m_Object_3DS.back().Vertices[m_Object_3DS.back().Faces.c],
m_Object_3DS.back().TexCoords[m_Object_3DS.back().Faces.a],
m_Object_3DS.back().TexCoords[m_Object_3DS.back().Faces.b],
m_Object_3DS.back().TexCoords[m_Object_3DS.back().Faces.c]);
m_Object_3DS.back().Tangents[m_Object_3DS.back().Faces.a] += T;
m_Object_3DS.back().Tangents[m_Object_3DS.back().Faces.b] += T;
m_Object_3DS.back().Tangents[m_Object_3DS.back().Faces.c] += T;
}
}
void Model_3DS::F_FACES_MATERIAL()
{
char nchar;
std::string texname="";
do {
fread (&nchar, 1, 1, file);
texname+=nchar;
} while(nchar != '\0');
int index=0;
for(int j = 0; j < (int)m_Material_3DS.size(); j++) {
if (texname==m_Material_3DS.at(j).Name)
index=j;
}
Object_3DS::MaterialFace tempMaterialFace;
tempMaterialFace.MatIndex = index;
unsigned short amount = 0;
unsigned short face_flags = 0;
fread (&amount, sizeof (unsigned short), 1, file);
tempMaterialFace.subFaces = new Object_3DS::Face[amount];
tempMaterialFace.numSubFaces = amount;
for (int j = 0; j < amount; j++)
{
fread(&face_flags,sizeof(face_flags),1,file);
tempMaterialFace.subFaces[j] = m_Object_3DS.back().Faces[face_flags];
}
m_Object_3DS.back().MatFaces.push_back(tempMaterialFace);
}
void Model_3DS::F_MAPPING_COORDINATES_LIST()
{
unsigned short amount = 0;
fread (&amount, sizeof (unsigned short), 1, file);
m_Object_3DS.back().TexCoords = new vec2[amount];
for (int i=0; i<amount; i++)
{
fread (&m_Object_3DS.back().TexCoords, sizeof (float), 2, file);
}
}
[Edited by - Dragon_Strike on May 18, 2007 11:53:50 AM]