//////////////////////////////////////////////////////////////////////
//
// 3D Studio Model Class
// by: Matthew Fairfax
//
// Model_3DS.cpp: implementation of the Model_3DS class.
// This is a simple class for loading and viewing
// 3D Studio model files (.3ds). It supports models
// with multiple objects. It also supports multiple
// textures per object. It does not support the animation
// for 3D Studio models b/c there are simply too many
// ways for an artist to animate a 3D Studio model and
// I didn't want to impose huge limitations on the artists.
// However, I have imposed a limitation on how the models are
// textured:
// 1) Every faces must be assigned a material
// 2) If you want the face to be textured assign the
// texture to the Diffuse Color map
// 3) The texture must be supported by the GLTexture class
// which only supports bitmap and targa right now
// 4) The texture must be located in the same directory as
// the model
//
// Support for non-textured faces is done by reading the color
// from the material's diffuse color.
//
// Some models have problems loading even if you follow all of
// the restrictions I have stated and I don't know why. If you
// can import the 3D Studio file into Milkshape 3D
// (http://www.swissquake.ch/chumbalum-soft) and then export it
// to a new 3D Studio file. This seems to fix many of the problems
// but there is a limit on the number of faces and vertices Milkshape 3D
// can read.
//
// Usage:
// Model_3DS m;
//
// m.Load("model.3ds"); // Load the model
// m.Draw(); // Renders the model to the screen
//
// // If you want to show the model's normals
// m.shownormals = true;
//
// // If the model is not going to be lit then set the lit
// // variable to false. It defaults to true.
// m.lit = false;
//
// // You can disable the rendering of the model
// m.visible = false;
//
// // You can move and rotate the model like this:
// m.rot.x = 90.0f;
// m.rot.y = 30.0f;
// m.rot.z = 0.0f;
//
// m.pos.x = 10.0f;
// m.pos.y = 0.0f;
// m.pos.z = 0.0f;
//
// // If you want to move or rotate individual objects
// m.Objects[0].rot.x = 90.0f;
// m.Objects[0].rot.y = 30.0f;
// m.Objects[0].rot.z = 0.0f;
//
// m.Objects[0].pos.x = 10.0f;
// m.Objects[0].pos.y = 0.0f;
// m.Objects[0].pos.z = 0.0f;
//
//////////////////////////////////////////////////////////////////////
// This is used to generate a warning from the compiler
#define _QUOTE(x) # x
#define QUOTE(x) _QUOTE(x)
#define __FILE__LINE__ __FILE__ "(" QUOTE(__LINE__) ") : "
#define warn( x ) message( __FILE__LINE__ #x "\n" )
// You need to uncomment this if you are using MFC
#pragma warn( You need to uncomment this if you are using MFC )
//#include "stdafx.h"
#include "Model_3DS.h"
#include <math.h> // Header file for the math library
#include <gl\gl.h> // Header file for the OpenGL32 library
// The chunk's id numbers
#define MAIN3DS 0x4D4D
#define MAIN_VERS 0x0002
#define EDIT3DS 0x3D3D
#define MESH_VERS 0x3D3E
#define OBJECT 0x4000
#define TRIG_MESH 0x4100
#define VERT_LIST 0x4110
#define FACE_DESC 0x4120
#define FACE_MAT 0x4130
#define TEX_VERTS 0x4140
#define SMOOTH_GROUP 0x4150
#define LOCAL_COORDS 0x4160
#define MATERIAL 0xAFFF
#define MAT_NAME 0xA000
#define MAT_AMBIENT 0xA010
#define MAT_DIFFUSE 0xA020
#define MAT_SPECULAR 0xA030
#define SHINY_PERC 0xA040
#define SHINY_STR_PERC 0xA041
#define TRANS_PERC 0xA050
#define TRANS_FOFF_PERC 0xA052
#define REF_BLUR_PERC 0xA053
#define RENDER_TYPE 0xA100
#define SELF_ILLUM 0xA084
#define MAT_SELF_ILPCT 0xA08A
#define WIRE_THICKNESS 0xA087
#define MAT_TEXMAP 0xA200
#define MAT_MAPNAME 0xA300
#define ONE_UNIT 0x0100
#define KEYF3DS 0xB000
#define FRAMES 0xB008
#define MESH_INFO 0xB002
#define HIER_POS 0xB030
#define HIER_FATHER 0xB010
#define PIVOT_PT 0xB013
#define TRACK00 0xB020
#define TRACK01 0xB021
#define TRACK02 0xB022
#define COLOR_RGB 0x0010
#define COLOR_TRU 0x0011
#define COLOR_TRUG 0x0012
#define COLOR_RGBG 0x0013
#define PERC_INT 0x0030
#define PERC_FLOAT 0x0031
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Model_3DS::Model_3DS()
{
// Initialization
// Don't show the normals by default
shownormals = false;
// The model is lit by default
lit = true;
// The model is visible by default
visible = true;
// Set up the default position
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = 0.0f;
// Set up the default rotation
rot.x = 0.0f;
rot.y = 0.0f;
rot.z = 0.0f;
// Set up the path
path = new char[80];
sprintf(path, "");
// Zero out our counters for MFC
numObjects = 0;
numMaterials = 0;
// Set the scale to one
scale = 1.0f;
}
Model_3DS::~Model_3DS()
{
}
void Model_3DS::Load(char *name)
{
// holds the main chunk header
ChunkHeader main;
// strip "'s
if (strstr(name, "\""))
name = strtok(name, "\"");
// Find the path
if (strstr(name, "/") || strstr(name, "\\"))
{
// Holds the name of the model minus the path
char *temp;
// Find the name without the path
if (strstr(name, "/"))
temp = strrchr(name, '/');
else
temp = strrchr(name, '\\');
// Allocate space for the path
path = new char[strlen(name)-strlen(temp)+1];
// Get a pointer to the end of the path and name
char *src = name + strlen(name) - 1;
// Back up until a \ or the start
while (src != path && !((*(src-1)) == '\\' || (*(src-1)) == '/'))
src--;
// Copy the path into path
memcpy (path, name, src-name);
path[src-name] = 0;
}
// Load the file
bin3ds = fopen(name,"rb");
// Make sure we are at the beginning
fseek(bin3ds, 0, SEEK_SET);
// Load the Main Chunk's header
fread(&main.id,sizeof(main.id),1,bin3ds);
fread(&main.len,sizeof(main.len),1,bin3ds);
// Start Processing
MainChunkProcessor(main.len, ftell(bin3ds));
// Don't need the file anymore so close it
fclose(bin3ds);
// Calculate the vertex normals
CalculateNormals();
// For future reference
modelname = name;
// Find the total number of faces and vertices
totalFaces = 0;
totalVerts = 0;
for (int i = 0; i < numObjects; i ++)
{
totalFaces += Objects[i].numFaces/3;
totalVerts += Objects[i].numVerts;
}
// If the object doesn't have any texcoords generate some
for (int k = 0; k < numObjects; k++)
{
if (Objects[k].numTexCoords == 0)
{
// Set the number of texture coords
Objects[k].numTexCoords = Objects[k].numVerts;
// Allocate an array to hold the texture coordinates
Objects[k].TexCoords = new GLfloat[Objects[k].numTexCoords * 2];
// Make some texture coords
for (int m = 0; m < Objects[k].numTexCoords; m++)
{
Objects[k].TexCoords[2*m] = Objects[k].Vertexes[3*m];
Objects[k].TexCoords[2*m+1] = Objects[k].Vertexes[3*m+1];
}
}
}
// Let's build simple colored textures for the materials w/o a texture
for (int j = 0; j < numMaterials; j++)
{
if (Materials[j].textured == false)
{
unsigned char r = Materials[j].color.r;
unsigned char g = Materials[j].color.g;
unsigned char b = Materials[j].color.b;
Materials[j].tex.BuildColorTexture(r, g, b);
Materials[j].textured = true;
}
}
}
void Model_3DS::Draw()
{
if (visible)
{
glPushMatrix();
// Move the model
glTranslatef(pos.x, pos.y, pos.z);
// Rotate the model
glRotatef(rot.x, 1.0f, 0.0f, 0.0f);
glRotatef(rot.y, 0.0f, 1.0f, 0.0f);
glRotatef(rot.z, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, scale);
// Loop through the objects
for (int i = 0; i < numObjects; i++)
{
// E
评论12
最新资源