T3DSModel.cpp es una librería cuyo objetivo es brindar una interfaz lo más sencilla posible para cargar
y dibujar archivos 3DS, de modo que con solo llamar las funciones Open3DS() y Draw() podremos estar
dibujando modelos complejos con alto nivel poligonal sin tener que preocuparnos en cargar texturas,
calcular normales, etc. Claro que a mayor abstracción menor control, no obstante es muy cómodo
exportar tus modelos previamente hechos en 3D Studio y luego cargarlos en tu aplicación como escenarios,
personajes, etc.
T3DSModel.cpp trabaja sobre la librería 3ds.cpp de DigiBen para crear una interface de fácil uso a la hora
de cargar y dibujar un 3DS.También me he tomando la libertad de hacerle algunos cambios a la librería de
DigiBen para agregar nuevas funcionalidades que quizás no sean básicas pero si importantes. Mis cambios
agregan: soporte para lightmaps, soporte para reflectionmaps, transparencia de materiales y CullMode establecido por el material.
T3DSModel.cpp
/*
*
* Nombre: T3DSModel
* Autor: h0aX
* Fecha: 10/febrero/2006
* Descripcion: Trabaja sobre la librería 3ds.cpp de
* DigiBen para crear una interface de fácil
* uso a la hora de cargar y dibujar un 3DS
*
*/
//---------------------------------------------------------------------------
#include <float.h>
#include <gl.h>
#include <glu.h>
#include <.\Libs3DS\multitexture.h>
#include "T3DSModel.h"
#pragma hdrstop
#pragma package(smart_init)
//---------------------------------------------------------------------------
T3DSModel::T3DSModel()
{
_control87(MCW_EM, MCW_EM);
CanDraw = TRUE;
}
//---------------------------------------------------------------------------
void T3DSModel::Open3DS(char *fichero)
{
BOOL bMultitexture;
bMultitexture = FALSE;
//importa estructura de datos del 3ds
g_Load3ds.Import3DS(&g_3DModel, fichero);
//inicia la carga de texturas
for(int i = 0; i < g_3DModel.numOfMaterials; i++)
{
if(strlen(g_3DModel.pMaterials[i].strFile) > 0)
{
//carga textura del material
CreateTexture(g_Texture, g_3DModel.pMaterials[i].strFile, i);
//si usa lightmap activa multitexturas y carga el lightmap
if (g_3DModel.pMaterials[i].bUseLightmap)
{
if (!bMultitexture)
{
InitMultiTexture();
bMultitexture = true;
}
CreateTexture(g_Lightmaps, g_3DModel.pMaterials[i].strLightmapFile, i);
}
//si usa reflexión activa multitexturas y carga la textura de reflexión
if (g_3DModel.pMaterials[i].bUseReflection)
{
if (!bMultitexture)
{
InitMultiTexture();
bMultitexture = true;
}
CreateTexture(g_Reflections, g_3DModel.pMaterials[i].strReflectionFile, i);
}
}
g_3DModel.pMaterials[i].texureId = i;
}
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
}
//---------------------------------------------------------------------------
int T3DSModel::GetPolygonsCount()
{
int result = 0;
for(int i = 0; i < g_3DModel.numOfObjects; i++)
{
if(g_3DModel.pObject.size() <= 0)
break;
t3DObject *pObject = &g_3DModel.pObject[i];
for(int j = 0; j < pObject->numOfFaces; j++)
{
result++;
}
}
result = result / 2;
return result;
}
//---------------------------------------------------------------------------
void T3DSModel::Draw()
{
float fTransp;
if (CanDraw)
{
for(int i = 0; i < g_3DModel.numOfObjects; i++)
{
if(g_3DModel.pObject.size() <= 0) break;
t3DObject *pObject = &g_3DModel.pObject[i];
/*
** Aqui comienza la carga del material
*/
//chequea si el material actual usa dos caras
if (g_3DModel.pMaterials[pObject->materialID].bTwoSides)
{
glDisable(GL_CULL_FACE);
}
else
{
glEnable(GL_CULL_FACE);
}
//chequea si el material usa texturas
if(pObject->bHasTexture)
{
glEnable(GL_TEXTURE_2D);
//carga la opacidad del material
fTransp = g_3DModel.pMaterials[pObject->materialID].fTransp;
//si la opacidad es menor de 1.0 activa la transparencia
if (fTransp < 1.0)
{
glEnable(GL_BLEND);
glColor4f(1.0,1.0,1.0,fTransp);
}
//Si el material actual usa lightmaps activa la textura actual
//junto con el lightmap usando multitexturas, sino solo activa
//la textura normal
if ( g_3DModel.pMaterials[pObject->materialID].bUseLightmap )
{
Bind2Textures(g_Texture[pObject->materialID],g_Lightmaps[pObject->materialID]);
}
else
{
glBindTexture(GL_TEXTURE_2D, g_Texture[pObject->materialID]);
}
//Si el material actual usa reflexión activa textura normal y la textura
//de reflexión usando multitexturas y luego le da reflexión esférica a la
//última
if ( g_3DModel.pMaterials[pObject->materialID].bUseReflection )
{
Bind2Textures(g_Texture[pObject->materialID],g_Reflections[pObject->materialID]);
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
//Caso que usen ambos, reflexión y lightmaps en un mismo material se activan las
//tres juntas con multitextura, Normal + Lightmap + Reflexión
if ( (g_3DModel.pMaterials[pObject->materialID].bUseLightmap) &&
(g_3DModel.pMaterials[pObject->materialID].bUseReflection) )
{
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Texture[pObject->materialID]);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Lightmaps[pObject->materialID]);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Reflections[pObject->materialID]);
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
}
else
{
//si el material no usa una textura se
//deshabilitan las texturas y se usa un
//color.
glDisable(GL_TEXTURE_2D);
glColor3b(g_3DModel.pMaterials[pObject->materialID].color[0], g_3DModel.pMaterials[pObject->materialID].color[1], g_3DModel.pMaterials[pObject->materialID].color[2]);
}
/*
** Aqui comienza el dibujado
*/
glBegin(GL_TRIANGLES);
//se recorren todas las caras
for(int j = 0; j < pObject->numOfFaces; j++)
{
//se recorre cada vértice de cada cara
for(int whichVertex = 0; whichVertex < 3; whichVertex++)
{
int index = pObject->pFaces[j].vertIndex[whichVertex];
//normales
glNormal3f(pObject->pNormals[ index ].x, pObject->pNormals[ index ].y, pObject->pNormals[ index ].z);
//si usa texturas se definen las coordenadas de mapeado
if(pObject->bHasTexture)
{
if(pObject->pTexVerts)
{
//coordenadas de mapeado para los lightmaps
if ( g_3DModel.pMaterials[pObject->materialID].bUseLightmap )
{
glMultiTexCoord2fARB(GL_TEXTURE0_ARB,pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y);
}
else
{
//coordenadas de mapeado de textura normal
glTexCoord2f(pObject->pTexVerts[index].x, pObject->pTexVerts[index ].y);
}
}
}
else
{
//si no usa textura se le asigna un color al vértice
if(g_3DModel.pMaterials.size() && pObject->materialID >= 0)
{
BYTE *pColor = g_3DModel.pMaterials[pObject->materialID].color;
glColor3ub(pColor[0], pColor[1], pColor[2]);
}
}
//dibuja el vértice
glVertex3f(pObject->pVerts[ index ].x, pObject->pVerts[ index ].y, pObject->pVerts[ index ].z);
}
}
glEnd();
//si la transparencia esta activada se desactiva
if (fTransp < 1.0)
{
glDisable(GL_BLEND);
}
//si se activaron las multitexturas se desactivan aqui
if ( (g_3DModel.pMaterials[pObject->materialID].bUseLightmap) ||
(g_3DModel.pMaterials[pObject->materialID].bUseReflection))
{
glActiveTextureARB(GL_TEXTURE2_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
}
}
}
}
//---------------------------------------------------------------------------
T3DSModel::~T3DSModel()
{
for(int i = 0; i < g_3DModel.numOfObjects; i++)
{
delete[] g_3DModel.pObject[i].pFaces;
delete[] g_3DModel.pObject[i].pNormals;
delete[] g_3DModel.pObject[i].pVerts;
delete[] g_3DModel.pObject[i].pTexVerts;
}
}
//---------------------------------------------------------------------------
void T3DSModel::Reset()
{
//esto falta
}
//---------------------------------------------------------------------------
Escrito por H0aX [hoax_ws@yahoo.es]
