Página principal | Jerarquía de la clase | Lista alfabética | Lista de componentes | Lista de archivos | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

md2load.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= md2load.cc                                            Noviembre de 1999 =
00003 //=-------------------------------------------------------------------------=
00004 //= Modulo de importacion de datos de avatares QUAKE2 en formato MD2        =
00005 //=-------------------------------------------------------------------------=
00006 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00007 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00008 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00009 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00010 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00011 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00012 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00013 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00014 //=-------------------------------------------------------------------------=
00015 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00016 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00017 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00018 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00019 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
00020 //===========================================================================
00021 
00022 #include "jed_defs.h"
00023 #include "toolkits/util/md2load.h"
00024 #include "lista.cc"
00025 
00026 #include <string.h>
00027 
00028 static void
00029 leer_bytes(FILE *f, void *buffer, int count) { fread (buffer, 1, count, f); }
00030 
00031 #define MAX_TRIANGLES 4096
00032 #define MAX_VERTS 2048
00033 #define MAX_FRAMES 512
00034 #define MAX_SKINNAME 64
00035 
00036 //===========================================================================
00037 //= Estructuras privadas usadas en el proceso de importacion de datos       =
00038 //===========================================================================
00039 
00040 class COORDENADA_PIEL_MD2 {
00041   public:
00042     WORD s;
00043     WORD t;
00044 };
00045 
00046 class POLIGONO_MD2
00047 {
00048   public:
00049     WORD index_xyz[3];
00050     WORD index_st[3];
00051 };
00052 
00053 class N_MD2
00054 {
00055   public:
00056     BYTE v[3];
00057     BYTE lightnormalindex;
00058 };
00059 
00060 class FRAME_ALIAS
00061 {
00062   public:
00063     float scale[3];
00064     float translate[3];
00065     char name[16];
00066     N_MD2 verts[1];
00067 };
00068 
00069 class ENCABEZADO_MD2
00070 {
00071   public:
00072     DWORD id_md2;       // Identificadores del formato de archivo MD2
00073     DWORD version;
00074     DWORD piel_xtam;    // Inforacion de las configuraciones MESH
00075     DWORD piel_ytam;
00076     DWORD framesize;
00077     DWORD num_pieles;   //
00078     DWORD num_vertices;
00079     DWORD _num_st;
00080     DWORD num_triangulos;
00081     DWORD _num_glcmds;
00082     DWORD num_frames;
00083     DWORD ofs_skins;    //
00084     DWORD ofs_st;
00085     DWORD ofs_tris;
00086     DWORD ofs_frames;
00087     DWORD ofs_glcmds; 
00088     DWORD ofs_end;
00089 };
00090 
00091 //===========================================================================
00092 //= Clase
00093 //===========================================================================
00094 
00095 LECTOR_QUAKE_MD2::LECTOR_QUAKE_MD2()
00104 {
00105     triangulos_arr = NULL;
00106     frames_arr = NULL;
00107     _num_frames = 0;
00108     _num_vertices = 0;
00109     _num_triangulos = 0;
00110     _nombre_piel = NULL;
00111     Piel = NULL;
00112 }
00113 
00114 LECTOR_QUAKE_MD2::~LECTOR_QUAKE_MD2()
00115 {
00116     elim();
00117 }
00118 
00119 void
00120 LECTOR_QUAKE_MD2::elim(void)
00121 {
00122     DWORD i;
00123 
00124     if ( frames_arr ) {
00125         for ( i = 0; i < _num_frames; i++ ) delete frames_arr[i].arr_vertices;
00126         delete frames_arr;
00127         frames_arr = NULL;
00128     }
00129     if ( triangulos_arr ) {
00130         delete triangulos_arr;
00131         triangulos_arr = NULL;
00132     }
00133     if ( _nombre_piel ) {
00134         delete _nombre_piel;
00135         _nombre_piel = NULL;
00136     }
00137     // OJO: La textura no es de esta clase! Es de la MESH! No hacer delete Piel
00138 }
00139 
00140 BOOLEAN
00141 LECTOR_QUAKE_MD2::leer(char *archivo_md2, char *archivo_piel, 
00142                   double factor_gamma)
00150 {
00151     //- Cargue la textura para su piel --------------------------------------
00152     FILE *fd = fopen(archivo_piel, "rb");
00153     if ( !fd ) {
00154         fprintf(stderr,"<LECTOR_QUAKE_MD2> ERROR: no puedo abrir el archivo %s!\n",
00155             archivo_piel);
00156         fflush(stderr);
00157         return FALSE;
00158     }
00159     Piel = new IMAGEN_RGB();
00160     if ( !Piel || !Piel->importar_pcx(fd) ) {
00161         fprintf(stderr,"ERROR Abriendo la imagen.\n"); fflush(stderr);
00162         exit(1);
00163     }
00164 
00165     BYTE funcion_gamma[256];
00166 
00167     calcular_funcion_gamma(funcion_gamma, factor_gamma);
00168     Piel->aplicar_correccion_gamma(funcion_gamma);
00169 
00170     _nombre_piel = new char[strlen(archivo_piel)+1];
00171     strcpy(_nombre_piel, archivo_piel);
00172 
00173     //- Abra el archivo y lea el encabezado MD2 -----------------------------
00174     ENCABEZADO_MD2      encabezado;
00175 
00176     fd = fopen (archivo_md2, "rb");
00177     if ( !fd ) {
00178         fprintf(stderr,"<LECTOR_QUAKE_MD2> ERROR: No puedo abrir el archivo %s!\n",
00179             archivo_md2);
00180         fflush(stderr);
00181         return FALSE;
00182     }
00183 
00184     lea_DWORD_BE(&encabezado.id_md2, fd);
00185     lea_DWORD_BE(&encabezado.version, fd);
00186     lea_DWORD_BE(&encabezado.piel_xtam, fd);
00187     lea_DWORD_BE(&encabezado.piel_ytam, fd);
00188     lea_DWORD_BE(&encabezado.framesize, fd);
00189     lea_DWORD_BE(&encabezado.num_pieles, fd);
00190     lea_DWORD_BE(&encabezado.num_vertices, fd);
00191     lea_DWORD_BE(&encabezado._num_st, fd);
00192     lea_DWORD_BE(&encabezado.num_triangulos, fd);
00193     lea_DWORD_BE(&encabezado._num_glcmds, fd);
00194     lea_DWORD_BE(&encabezado.num_frames, fd);
00195     lea_DWORD_BE(&encabezado.ofs_skins, fd);
00196     lea_DWORD_BE(&encabezado.ofs_st, fd);
00197     lea_DWORD_BE(&encabezado.ofs_tris, fd);
00198     lea_DWORD_BE(&encabezado.ofs_frames, fd);
00199     lea_DWORD_BE(&encabezado.ofs_glcmds, fd) 
00200     lea_DWORD_BE(&encabezado.ofs_end, fd);
00201 
00202     //- Cree la estructura de representacion del MESH y sus configuraciones -
00203     DWORD i, j;
00204 
00205     _num_frames     = encabezado.num_frames;
00206     _num_vertices   = encabezado.num_vertices;
00207     _num_triangulos = encabezado.num_triangulos;
00208     triangulos_arr  = new TRIANGULO_QUAKE [_num_triangulos];
00209     frames_arr      = new CONFIGURACION_MESH [_num_frames];
00210 
00211     for ( i = 0; i < _num_frames; i++ ) {
00212         frames_arr[i].arr_vertices = new VERTICE_GL[_num_vertices];
00213     }
00214 
00215     //- Llene los datos del mesh --------------------------------------------
00216     char *nombres_pieles;
00217     COORDENADA_PIEL_MD2 *puntos_uv =
00218         new COORDENADA_PIEL_MD2[encabezado._num_st];
00219     POLIGONO_MD2 tri;
00220 
00221     nombres_pieles = new char [encabezado.num_pieles * MAX_SKINNAME];
00222     leer_bytes(fd, nombres_pieles, encabezado.num_pieles * MAX_SKINNAME);
00223     for ( i = 0; i < encabezado._num_st; i++ ) {
00224         lea_WORD_BE(&puntos_uv[i].s, fd);
00225         lea_WORD_BE(&puntos_uv[i].t, fd);
00226     }
00227 
00228     for ( i = 0; i < _num_triangulos; i++ ) {
00229         lea_WORD_BE(&tri.index_xyz[0], fd);
00230         lea_WORD_BE(&tri.index_xyz[1], fd);
00231         lea_WORD_BE(&tri.index_xyz[2], fd);
00232         lea_WORD_BE(&tri.index_st[0], fd);
00233         lea_WORD_BE(&tri.index_st[1], fd);
00234         lea_WORD_BE(&tri.index_st[2], fd);
00235         triangulos_arr[i].p0 = tri.index_xyz[2];
00236         triangulos_arr[i].p1 = tri.index_xyz[1];
00237         triangulos_arr[i].p2 = tri.index_xyz[0];
00238         triangulos_arr[i].a_s = puntos_uv[tri.index_st[2]].s;
00239         triangulos_arr[i].a_t = puntos_uv[tri.index_st[2]].t;
00240         triangulos_arr[i].b_s = puntos_uv[tri.index_st[1]].s;
00241         triangulos_arr[i].b_t = puntos_uv[tri.index_st[1]].t;
00242         triangulos_arr[i].c_s = puntos_uv[tri.index_st[0]].s;
00243         triangulos_arr[i].c_t = puntos_uv[tri.index_st[0]].t;
00244     }
00245     delete puntos_uv;
00246     delete nombres_pieles;
00247 
00248     //-----------------------------------------------------------------------
00249     BYTE        buffer[MAX_VERTS*4+128];
00250     FRAME_ALIAS *out;
00251 
00252     for ( i = 0; i < _num_frames; i++ ) {
00253         out = (FRAME_ALIAS *)buffer;
00254         leer_bytes(fd, out, encabezado.framesize);
00255         for ( j = 0; j < _num_vertices; j++ ) {
00256             frames_arr[i].arr_vertices[j].x =
00257                 out->verts[j].v[0] * out->scale[0] + out->translate[0];
00258             frames_arr[i].arr_vertices[j].y =
00259                 out->verts[j].v[1] * out->scale[1] + out->translate[1];
00260             frames_arr[i].arr_vertices[j].z =
00261                 out->verts[j].v[2] * out->scale[2] + out->translate[2];
00262             frames_arr[i].arr_vertices[j].u = -INFINITO;
00263             frames_arr[i].arr_vertices[j].v = -INFINITO;
00264         }
00265     }
00266     fclose (fd);
00267 
00268     return TRUE;
00269 }
00270 
00271 void
00272 LECTOR_QUAKE_MD2::init(BOOLEAN suavizar_normales)
00278 {
00279     DWORD i, j;
00280     VERTICE_GL *Geometria_nueva, *Consulta;
00281     long int tam_consulta;
00282 
00283     printf("<LECTOR_QUAKE_MD2> Preprocesando %ld cuadros:\n[", _num_frames);
00284     fflush(stdout);
00285     for ( i = 0; i < _num_frames; i++ ) {
00286         printf("."); fflush(stdout);
00287         MESH *Tmp = exportar_MESH(i);
00288         // Calcule las normales para el i-esimo frame usando el MESH Tmp.
00289         Tmp->get_vertices(&Consulta, &tam_consulta);
00290         actualizar_vertices(Consulta, tam_consulta, i);
00291         Tmp->init();
00292         if ( suavizar_normales ) Tmp->promediar_normales_vertice();
00293 
00294         // Almacene las normales en mi i-esima geometria preprocesada
00295         Geometria_nueva = new VERTICE_GL[_num_triangulos * 3];
00296         for ( j = 0;
00297               j < (DWORD)tam_consulta && j < _num_triangulos * 3; j++ ) {
00298             Geometria_nueva[j] = Consulta[j];
00299         }
00300         geometrias_preprocesadas.anx(Geometria_nueva);
00301         delete Tmp;
00302     }
00303     printf("]\nOk!\n"); fflush(stdout);
00304     //delete Tmp; // OJO: Saca segmentation fault!
00305 }
00306 
00307 DWORD LECTOR_QUAKE_MD2::num_frames(void) {return _num_frames;}
00308 DWORD LECTOR_QUAKE_MD2::num_vertices(void) {return _num_vertices;}
00309 DWORD LECTOR_QUAKE_MD2::num_triangulos(void){return _num_triangulos;}
00310 
00311 #ifdef NONONO
00312 void
00313 LECTOR_QUAKE_MD2::pintar_gl(DWORD frame)
00318 {
00319     if ( frame >= _num_frames || frame < 0 ) return;
00320 
00321     //--- Configuracion de la textura que conforma la piel -------------------
00322     static float modo_repetir[] = {GL_CLAMP};
00323     static GLfloat f_combinar[] = {GL_MODULATE};
00324     static GLfloat f_interpolar[] = {GL_LINEAR};
00325 
00326     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, modo_repetir);
00327     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, modo_repetir);
00328     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, f_combinar);
00329     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f_interpolar);
00330     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f_interpolar);
00331     Piel->activar_gl();
00332     glEnable(GL_TEXTURE_2D);
00333 
00334     //---
00335     glScaled(0.05, 0.05, 0.05); // OJO!
00336     glDisable(GL_LIGHTING);     // OJO!
00337     glColor3d(1, 1, 1);         // OJO!
00338 
00339     //- Generacion de una MESH ----------------------------------------------
00340     DWORD i;
00341 
00342     for ( i = 0; i < _num_triangulos; i++ ) {
00343       glBegin(GL_TRIANGLES);
00344         glTexCoord2f((triangulos_arr[i].a_s)/(float)Piel->xtam(),
00345                      (triangulos_arr[i].a_t)/(float)Piel->ytam());
00346         glVertex3f(frames_arr[frame].arr_vertices[triangulos_arr[i].p0].x,
00347                    frames_arr[frame].arr_vertices[triangulos_arr[i].p0].y,
00348                    frames_arr[frame].arr_vertices[triangulos_arr[i].p0].z);
00349         glTexCoord2f((triangulos_arr[i].b_s)/(float)Piel->xtam(), 
00350                      (triangulos_arr[i].b_t)/(float)Piel->ytam());
00351         glVertex3f(frames_arr[frame].arr_vertices[triangulos_arr[i].p1].x,
00352                    frames_arr[frame].arr_vertices[triangulos_arr[i].p1].y,
00353                    frames_arr[frame].arr_vertices[triangulos_arr[i].p1].z);
00354         glTexCoord2f((triangulos_arr[i].c_s)/(float)Piel->xtam(), 
00355                      (triangulos_arr[i].c_t)/(float)Piel->ytam());
00356         glVertex3f(frames_arr[frame].arr_vertices[triangulos_arr[i].p2].x,
00357                    frames_arr[frame].arr_vertices[triangulos_arr[i].p2].y,
00358                    frames_arr[frame].arr_vertices[triangulos_arr[i].p2].z);
00359       glEnd();
00360     }
00361 
00362     glDisable(GL_TEXTURE_2D); // OJO!
00363 }
00364 #endif
00365 
00366 //===========================================================================
00367 
00368 void
00369 LECTOR_QUAKE_MD2::actualizar_vertices(VERTICE_GL *V,
00370                                       long int /*t*/, int cuadro)
00386 {
00387     WORD i;
00388     int j;
00389 
00390     for ( i = 0, j = 0; i < (WORD)_num_triangulos; i++ ) {
00391         V[j] = 
00392             frames_arr[cuadro].arr_vertices[triangulos_arr[i].p0];
00393         V[j].u = triangulos_arr[i].a_s / (float)Piel->xtam();
00394         V[j].v = triangulos_arr[i].a_t / (float)Piel->ytam();
00395         j++;
00396 
00397         V[j] =
00398             frames_arr[cuadro].arr_vertices[triangulos_arr[i].p1];
00399         V[j].u = triangulos_arr[i].b_s / (float)Piel->xtam();
00400         V[j].v = triangulos_arr[i].b_t / (float)Piel->ytam();
00401         j++;
00402 
00403         V[j] =
00404             frames_arr[cuadro].arr_vertices[triangulos_arr[i].p2];
00405         V[j].u = triangulos_arr[i].c_s / (float)Piel->xtam();
00406         V[j].v = triangulos_arr[i].c_t / (float)Piel->ytam();
00407         j++;
00408     }
00409 }
00410 
00411 void
00412 LECTOR_QUAKE_MD2::actualizar_vertices_rapido(VERTICE_GL *V,
00413                                              long int /*t*/, int cuadro)
00423 {
00424     WORD i;
00425 
00426     if ( !geometrias_preprocesadas.tam() ) {
00427         fprintf(stderr, "<LECTOR_QUAKE_MD2> ERROR: Debe llamarse init() "
00428             "antes de usar actualizar_vertices_rapido.\n");
00429         fflush(stderr);
00430         return;
00431     }
00432 
00433     VERTICE_GL *O = geometrias_preprocesadas[cuadro];
00434 
00435     for ( i = 0; i < (WORD)_num_triangulos * 3; i++ ) {
00436         V[i] = O[i];
00437     }
00438 }
00439 
00440 #define INTERPOLAR_VARIABLE(v, vi, vf, f, t) \
00441 ( v = (float)(vi + ((double)f) * ( (vf - vi) / ((double)t) )) )
00442 
00443 void
00444 interpolar_vertice(VERTICE_GL *D, VERTICE_GL *Oi,
00445                    VERTICE_GL *Of, int f, int t)
00453 {
00454     INTERPOLAR_VARIABLE(D->x, Oi->x, Of->x, f, t);
00455     INTERPOLAR_VARIABLE(D->y, Oi->y, Of->y, f, t);
00456     INTERPOLAR_VARIABLE(D->z, Oi->z, Of->z, f, t);
00457     INTERPOLAR_VARIABLE(D->nx, Oi->nx, Of->nx, f, t);
00458     INTERPOLAR_VARIABLE(D->ny, Oi->ny, Of->ny, f, t);
00459     INTERPOLAR_VARIABLE(D->nz, Oi->nz, Of->nz, f, t);
00460     D->u = Oi->u;
00461     D->v = Oi->v;
00462 }
00463 
00464 void
00465 LECTOR_QUAKE_MD2::actualizar_vertices_rapido_i(VERTICE_GL *V,
00466                                              long int /*t*/, int cuadro,
00467                                              int cuadroi, int cuadrof,  
00468                                              int frame, int tam)
00473 {
00474     WORD i;
00475 
00476     if ( !geometrias_preprocesadas.tam() ) {
00477         fprintf(stderr, "<LECTOR_QUAKE_MD2> ERROR: Debe llamarse init() "
00478             "antes de usar actualizar_vertices_rapido.\n");
00479         fflush(stderr);
00480         return;
00481     }
00482 
00483     VERTICE_GL O, *Oi, *Of;
00484     int elcuadro = cuadro+1;
00485 
00486     if ( elcuadro > cuadrof ) {
00487         elcuadro = cuadroi;
00488     }
00489 
00490     Oi = geometrias_preprocesadas[cuadro];
00491     Of = geometrias_preprocesadas[elcuadro];
00492 
00493     for ( i = 0; i < (WORD)_num_triangulos * 3; i++ ) {
00494         interpolar_vertice(&O, &Oi[i], &Of[i], frame, tam);
00495         V[i] = O;
00496     }
00497 }
00498 
00499 MESH *
00500 LECTOR_QUAKE_MD2::exportar_MESH(int cuadro)
00525 {
00526     WORD i;
00527 
00528     //- Creo una copia... (version ingenua, ineficiente en espacio) ---------
00529     // OJO: Esto funciona pero es muy ineficiente en espacio... ocupa 
00530     //      muchos mas vertices (i.e. de 300 pasa a 1800)
00531     VERTICE_GL *Copia_vertices = new VERTICE_GL[_num_triangulos * 3];
00532     TRIANGULO_GL *Copia_triangulos = new TRIANGULO_GL[_num_triangulos];
00533 
00534     int j;
00535     // Defino la topologia
00536     for ( i = 0, j = 0; i < (WORD)_num_triangulos; i++ ) {
00537         Copia_triangulos[i].p0 = j;        j++;
00538         Copia_triangulos[i].p1 = j;        j++;
00539         Copia_triangulos[i].p2 = j;        j++;
00540     }
00541 
00542     // Defino la geometria
00543     actualizar_vertices(Copia_vertices, _num_triangulos*3, cuadro);
00544 
00545     //-----------------------------------------------------------------------
00546     MESH *G = new MESH(181 /*umbral*/, FALSE/*strip*/, TRUE/*centrar*/, 0.05);
00547 
00548     //- Exporte materiales --------------------------------------------------
00549     COLOR ambient, diffuse, specular;
00550 
00551     ambient.r = ambient.g = ambient.b = 0.2f;  // ORO
00552     diffuse.r = 0.85f;    diffuse.g = 0.85f;    diffuse.b = 0.1f;
00553     specular.r = specular.g = specular.b = 1.0;
00554     ambient.alpha = diffuse.alpha = specular.alpha = 1.0;
00555     G->anx_material(ambient, diffuse, specular, "WG_DEFAULT", "", 1);
00556 
00557     //- Exporte la geometria y la topologia de la malla ----------------------
00558     VERTICE_GL v;
00559 
00560     for ( i = 0; i < (WORD)_num_triangulos*3; i++ ) {
00561         v.x = Copia_vertices[i].x;
00562         v.y = Copia_vertices[i].y;
00563         v.z = Copia_vertices[i].z;
00564         v.u = Copia_vertices[i].u;
00565         v.v = Copia_vertices[i].v;
00566         G->anx_vertex(v);
00567     }
00568 
00569     for ( i = 0; i < (WORD)_num_triangulos; i++ ) {
00570         G->anx_triangle(Copia_triangulos[i], "WG_DEFAULT");
00571     }
00572 
00573     //- Asocie la imagen ----------------------------------------------------
00574     G->anexar_textura(Piel);
00575 
00576     //-----------------------------------------------------------------------
00577     delete Copia_vertices;
00578     Copia_vertices = NULL;
00579     delete Copia_triangulos;
00580     Copia_triangulos = NULL;
00581     G->set_material_global(TRUE);
00582     return G;
00583 }
00584 
00585 
00586 //===========================================================================
00587 //= EOF                                                                     =
00588 //===========================================================================
00589 

Este archivo HTML ha sido generado automáticamente a partir del código fuente AQUYNZA. NO LO EDITE. Para mayor información contacte al autor.