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

mesh.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= mesh.cc                 Septiembre de 1998, revisado en octubre de 1999 =
00003 //=-------------------------------------------------------------------------=
00004 //= Modulo de representacion y despliegue de geometrias 3D en mallas de     =
00005 //= triangulos. Este modulo contiene la implementacion de la clase MESH y   =
00006 //= esta dividido en las siguientes secciones:                              =
00007 //=   - Inicio                                                              =
00008 //=       Macros, descructora y constructora                                =
00009 //=   - Servicios de construccion de TAD's internos                         =
00010 //=       angulo_de_vertice, calcule_normales_vertice,                      =
00011 //=       cree_lista_de_referencias & init                                  =
00012 //=   - Operaciones que precalculan datos                                   =
00013 //=       crear_trozos_gl & crear_tiras                                     =
00014 //=   - Operaciones que permiten importar datos desde otras clases          =
00015 //=       encontrar_material, calcule_normal_triangulo, anx_vertex,         =
00016 //=       anx_triangle & anx_material                                       =
00017 //= Notese que las siguientes operaciones han sido aisladas en el modulo    =
00018 //= `mesh_gl`:                                                              =
00019 //=   - Operaciones de visualizacion                                        =
00020 //=       crear_trozos_gl, crear_tiras, pintar_*_gl, nucleo_pintar_gl y     =
00021 //=       compilar_lista_gl                                                 =
00022 //=-------------------------------------------------------------------------=
00023 //= Comentarios del autor original de quien se basa este codigo:            =
00024 //= The data structures used in this module are probably hard for anyone    =
00025 //= else to understand, so let me explain my code. There are three main     =
00026 //= data structures in use: arr_vertices, poligonos_arr, and                =
00027 //= listas_de_referencias.                                                =
00028 //=                                                                         =
00029 //= arr_vertices is the list of vertices and normals that polygons index in =
00030 //=  to. OpenGL accepts this array as a vertex array. The normals stored    =
00031 //=  in this array are normals *for each vertex*, not the polygon normals.  =
00032 //=                                                                         =
00033 //= poligonos_arr is an array of materials. A material is a group of        =
00034 //=  attributes such as diffuse color, shininess, a texture map, etc. It    =
00035 //=  contains an array of triangles stored as 3-tuples of integers. These   =
00036 //=  are indexes into the arr_vertices array. An example:                   =
00037 //=       arr_vertices[poligonos_arr[2].arr_triangulos[3].p0]               =
00038 //=       arr_vertices[poligonos_arr[2].arr_triangulos[3].p1]               =
00039 //=       arr_vertices[poligonos_arr[2].arr_triangulos[3].p2]               =
00040 //=  are the three points of the fourth triangle of the third material. Of  =
00041 //=  course, *each* of these points (p0, p1, and p2) have three GLfloats    =
00042 //=  associated with them as X,Y,Z data.                                    =
00043 //=                                                                         =
00044 //= listas_de_referencias is an array the same size as arr_vertices.      =
00045 //= Each of it's positions is a linked list of pointers into the            =
00046 //= poligonos_arr[].arr_triangulos of  every triangle that touches that     =
00047 //= vertex. Another example:                                                =
00048 //=       for(ptr = listas_de_referencias[5]; ptr; ptr=ptr->sig)          =
00049 //=           printf("%d %d %d\n",                                          =
00050 //=               ptr->triangle->p0, ptr->triangle->p1, ptr->triangle->p2); =
00051 //=  This will traverse a linked list, producing the integer indexes of the =
00052 //=  three points of all the triangles that touch vertex 5. This is the     =
00053 //=  same vertex 5 as arr_vertices[5]. This is used for building the        =
00054 //=  normals for each vertex where we may have to produce two vertexes with =
00055 //=  the same X,Y,Z but different normals due to sharp edges.               =
00056 //=-------------------------------------------------------------------------=
00057 //= Basado en el proyecto "3D Studio to OpenGL File Converter" de David     =
00058 //= Farrell, fdavid@cyberramp.net                                           =
00059 //= Modificado y extendido por Oscar Chavarro      oscarchavarro@hotmail.co =
00060 //===========================================================================
00061 
00062 #include <math.h>
00063 #include <stdio.h>
00064 #include <stdlib.h>
00065 #include <string.h>
00066 
00067 #include "toolkits/geom/mesh.h"
00068 #include "matriz4.h"
00069 #include "lista.cc"
00070 #include "arreglo.cc"
00071 
00072 #ifdef GL_VERSION_1_1  // OJO: Toca revisar si esta vaina funciona bien!
00073     #define GL_COMPLETO
00074 #endif
00075 
00076 #if PLATAFORMA == SGI
00077     #undef GL_COMPLETO  // OJO: Esto es un machete!
00078 #endif
00079 
00080 //#define DEBUG_MESH
00081 
00082 //===========================================================================
00083 //= Macros locales                                                          =
00084 //===========================================================================
00085 
00086 #define VERIFICAR(m) \
00087     if ( !m ) { \
00088         fprintf(stderr, "<MESH> ERROR: Falla de memoria dinamica.\n"); \
00089         fflush(stderr); \
00090         exit(-1); \
00091     }
00092 
00093 #define VERIFICAR1(m) \
00094     if ( !m ) { \
00095         fprintf(stderr, "<MESH> ERROR: Falla de memoria dinamica (STRIP).\n");\
00096         fflush(stderr); \
00097         exit(-1); \
00098     }
00099 
00100 /*  Returns the cosine of the angle between two normals.
00101  * Since the normals are already normalized, we don't need to
00102  * divide by the product of their magnitudes. We only need
00103  * to return the dot product since the denominator will always
00104  * be 1. */
00105 #define cos_angle(a, b) \
00106     ((a)->nx * (b)->nx) + ((a)->ny * (b)->ny) + ((a)->nz * (b)->nz)
00107 
00108 #define COMPARAR_MM()                           \
00109         if ( p.x < _min.x ) _min.x = p.x;       \
00110         if ( p.y < _min.y ) _min.y = p.y;       \
00111         if ( p.z < _min.z ) _min.z = p.z;       \
00112         if ( p.x > _max.x ) _max.x = p.x;       \
00113         if ( p.y > _max.y ) _max.y = p.y;       \
00114         if ( p.z > _max.z ) _max.z = p.z;
00115 
00116 //===========================================================================
00117 //= CLASE MESH                                                              =
00118 //===========================================================================
00119 
00120 MESH::MESH(int threshold, BOOLEAN strips, BOOLEAN center_model, double scale)
00121     : arr_vertices(VERTEXBLOCKSIZE), arr_trozos_gl(1), 
00122       arr_colores(VERTEXBLOCKSIZE), listas_de_referencias(VERTEXBLOCKSIZE) 
00141 {
00142     //- Empiece como un objeto vacio ---------------------------------------
00143     vertice_promedio.x = vertice_promedio.y = vertice_promedio.z = 0;
00144 
00145     //- Flags por defecto --------------------------------------------------
00146     material_global = FALSE;
00147     calcular_normales = TRUE;
00148     preprocesada = FALSE;
00149 #ifdef GL_ENABLED
00150     preprocesada_gl = FALSE;
00151 #endif
00152     modo_tiras_de_triangulos = FALSE;
00153     centrar_modelo = FALSE;
00154     preservar_bordes = FALSE;
00155     Arr_control = NULL;
00156     pintar_normales = FALSE;
00157     pintar_debug_vertices = FALSE;
00158     pintar_debug_triangulos = FALSE;
00159     index_debug_vertice = 0;
00160     index_debug_triangulo = 0;
00161     mostrar_tiras = FALSE;
00162     con_minmax = FALSE;
00163     ultima_tira = 0;
00164     _invertir_orden = FALSE;
00165 
00166   #if PLATAFORMA == i386_WIN32_VC  // OJO: Esto es un machete, debido a falta de 
00167     con_lista_gl = FALSE;     // informacion a la hora de integrar OpenGL
00168   #else                       // con el SDK de Windows.
00169     con_lista_gl = FALSE;  // OJO!
00170   #endif
00171 
00172     normales_de_triangulo = FALSE;
00173 
00174     //- Flags configurables por el usuario mediante los atributos ----------
00175     _nombre_de_archivo = NULL;
00176     if ( strips ) modo_tiras_de_triangulos = TRUE;
00177     if ( center_model ) centrar_modelo = TRUE;
00178     if ( threshold ) {
00179         cos_threshold = (GLfloat)cos(threshold*PI/180.0);
00180         preservar_bordes = TRUE;
00181         if ( threshold > 180 ) normales_de_triangulo = TRUE;
00182       }
00183       else {
00184         preservar_bordes = FALSE;
00185         normales_de_triangulo = TRUE;
00186     }
00187     escala = scale;
00188 
00189     imagen = NULL;
00190 }
00191 
00192 MESH::~MESH(void)
00197 {
00198     int i;
00199     //TRIANGLENODE *LList;
00200     //TRIANGLENODE *TempPtr;
00201 
00202     arr_vertices.elim();
00203     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {
00204         arr_trozos_gl[i].arr_triangulos.elim();
00205         delete arr_trozos_gl[i].triangulos_gl;
00206     }
00207     /*
00208     for ( i = 0; i < arr_vertices.tam(); i++ ) {
00209         LList = listas_de_referencias[i];
00210         while (LList) {
00211             TempPtr = LList;
00212             LList = LList->sig;
00213             delete TempPtr;
00214         }
00215     }
00216     */
00217     if ( _nombre_de_archivo ) {
00218         delete _nombre_de_archivo;
00219     }
00220     listas_de_referencias.elim();
00221     arr_trozos_gl.elim();
00222 }
00223 
00224 //= SERVICIOS DE CONSTRUCCION DE TAD'S INTERNOS =============================
00225 
00226 void
00227 MESH::get_vertices(VERTICE_GL **V, long int *n)
00238 {
00239     (*V) = arr_vertices.data();
00240     (*n) = arr_vertices.tam();
00241 
00242     //preprocesada = FALSE;     // OJO: El usuario debera dar init!
00243     //preprocesada_gl = FALSE;
00244 
00245     if ( con_lista_gl ) {
00246         //glDeleteLists(id_lista_opengl, 1); // Y esto no funciona a veces!
00247         // OJO: Esto es machete!
00248         con_lista_gl = FALSE;
00249     }
00250 }
00251 
00252 void
00253 MESH::set_invertir_orden(BOOLEAN o)
00254 {
00255     _invertir_orden = o;
00256 }
00257 
00258 void
00259 MESH::set_nombre_de_archivo(char *c)
00260 {
00261     _nombre_de_archivo = c;
00262 }
00263 
00264 void
00265 MESH::set_escala(double e)
00266 {
00267     escala = e;
00268 }
00269 
00270 inline GLfloat
00271 MESH::angulo_de_vertice(TRIANGULITO *triangle, GLuint vertex)
00281 {
00282     double a,b,c;
00283 
00284     if ( triangle->p0 == vertex ) {
00285         a = DISTANCIA_VGL(&arr_vertices[triangle->p0],
00286                           &arr_vertices[triangle->p1]);
00287         b = DISTANCIA_VGL(&arr_vertices[triangle->p0],
00288                           &arr_vertices[triangle->p2]);
00289         c = DISTANCIA_VGL(&arr_vertices[triangle->p1],
00290                           &arr_vertices[triangle->p2]);
00291       }
00292       else if ( triangle->p1 == vertex ) {
00293         a = DISTANCIA_VGL(&arr_vertices[triangle->p1],
00294                           &arr_vertices[triangle->p0]);
00295         b = DISTANCIA_VGL(&arr_vertices[triangle->p1],
00296                           &arr_vertices[triangle->p2]);
00297         c = DISTANCIA_VGL(&arr_vertices[triangle->p2],
00298                           &arr_vertices[triangle->p0]);
00299       }
00300       else if (triangle->p2 == vertex) {
00301         a = DISTANCIA_VGL(&arr_vertices[triangle->p2],
00302                           &arr_vertices[triangle->p0]);
00303         b = DISTANCIA_VGL(&arr_vertices[triangle->p2],
00304                           &arr_vertices[triangle->p1]);
00305         c = DISTANCIA_VGL(&arr_vertices[triangle->p0],
00306                           &arr_vertices[triangle->p1]);
00307       }
00308       else {
00309         // ERROR: Algo alda mal!
00310         fprintf(stderr, "!");
00311         return 60;
00312       }
00313     ;
00314     
00315     return (GLfloat)acos( (c*c - a*a - b*b) / (2*a*b) );
00316 }
00317 
00318 void
00319 MESH::calcule_normales_vertice(void)
00326 {
00327     int orig_arr_vertices_tam;
00328     int i;
00329     long int error_vertice_suelto = 0;
00330 
00331     orig_arr_vertices_tam = arr_vertices.tam();
00332 
00333     //- 1a. CALCULA TODAS LAS NORMALES SI HAY UN SOLO TRIANGULO POR VERTICE -
00334     int j;
00335     TRIANGULITO *pptr;
00336 
00337     if ( normales_de_triangulo ) {
00338         for ( j = 0; j < arr_trozos_gl.tam(); j++ ) {
00339             for ( i = 0; i < arr_trozos_gl[j].arr_triangulos.tam(); i++ ) {
00340                 pptr=&(arr_trozos_gl[j].arr_triangulos[i]);
00341                 arr_vertices[pptr->p0].nx = pptr->nx;
00342                 arr_vertices[pptr->p0].ny = pptr->ny;
00343                 arr_vertices[pptr->p0].nz = pptr->nz;
00344                 arr_vertices[pptr->p1].nx = pptr->nx;
00345                 arr_vertices[pptr->p1].ny = pptr->ny;
00346                 arr_vertices[pptr->p1].nz = pptr->nz;
00347                 arr_vertices[pptr->p2].nx = pptr->nx;
00348                 arr_vertices[pptr->p2].ny = pptr->ny;
00349                 arr_vertices[pptr->p2].nz = pptr->nz;
00350             }
00351         }
00352     }
00353 
00354     //- 1b. CALCULE LAS NORMALES PARA TODOS LOS VERTICES --------------------
00355     BOOLEAN ya_hice_vertice_nuevo;
00356     TRIANGLENODE *ptr;
00357     TRIANGLENODE *qtr;
00358     GLfloat TotalAngles;
00359     GLfloat VertexAngle;
00360     GLfloat magnitude;
00361 
00362     for ( i = 0; !normales_de_triangulo && i < arr_vertices.tam(); i++ ) {
00363         //- Preparese para el calculo de la normal --------------------------
00364         // OJO: La normal es <0, 0, 0> porque se va a ir acumulando
00365         arr_vertices[i].nx = arr_vertices[i].ny = arr_vertices[i].nz = 0;
00366         ya_hice_vertice_nuevo = FALSE;
00367         TotalAngles = 0;
00368 
00369         //- Recorra la lista de triangulos que tocan este vertice... --------
00370         ptr = listas_de_referencias[i]; // O sea ptr = cab;
00371         while ( ptr ) {
00372             if ( preservar_bordes && 
00373                  cos_angle(listas_de_referencias[i]->triangle,
00374                            ptr->triangle) <= cos_threshold) {
00375                 /* Put this triangle at another vertex */
00376                 if ( !ya_hice_vertice_nuevo ) {
00377                     /* Make a copy of this vertex at the end of the vertex 
00378                        list */
00379                     ya_hice_vertice_nuevo = TRUE;
00380                     // Notese que la copia de este vertice no contribuye al
00381                     // calculo del centro...
00382                     anx_vertex(arr_vertices[i]);
00383                     vertice_promedio.x -= arr_vertices[i].x;
00384                     vertice_promedio.y -= arr_vertices[i].y;
00385                     vertice_promedio.z -= arr_vertices[i].z;
00386                 }
00387                 /* Attach this surface to the last vertex's list of adjacent 
00388                  * triangles must be in this order or our ->sig's won't link
00389                  * correctly  */
00390                 qtr = ptr;
00391                 ptr = ptr->sig;
00392                 qtr->sig = listas_de_referencias[arr_vertices.tam()-1];
00393                 listas_de_referencias[arr_vertices.tam()-1] = qtr;
00394                 /* Change the vertex indices so that we point to the new vertex
00395                  * instead of the one we were originally pointing to. */
00396                 if ( qtr->triangle->p0 == (GLuint)i ) {
00397                     qtr->triangle->p0 = arr_vertices.tam()-1;
00398                 }
00399                 if ( qtr->triangle->p1 == (GLuint)i ) {
00400                     qtr->triangle->p1 = arr_vertices.tam()-1;
00401                 }
00402                 if ( qtr->triangle->p2 == (GLuint)i ) {
00403                     qtr->triangle->p2 = arr_vertices.tam()-1;
00404                 }
00405               } 
00406               else {
00407                 /* Since it's less then the threshold angle, calculate the 
00408                  * angle that this polygon shares with the vertex  */
00409                 VertexAngle = angulo_de_vertice(ptr->triangle, i);
00410                 arr_vertices[i].nx += ptr->triangle->nx * VertexAngle;
00411                 arr_vertices[i].ny += ptr->triangle->ny * VertexAngle;
00412                 arr_vertices[i].nz += ptr->triangle->nz * VertexAngle;
00413                 TotalAngles += VertexAngle;
00414                 ptr = ptr->sig;
00415             }  // if-else
00416         } // while
00417 
00418         //- Calcule la normal (unitaria) para este vertice ------------------
00419         if ( IGUAL(0.0, TotalAngles) ) {
00420             // Este es un vertice suelto (no participa en ningun poligono!)
00421             error_vertice_suelto++;
00422             arr_vertices[i].nz = 1;
00423             continue;
00424         }
00425         arr_vertices[i].nx /= TotalAngles;
00426         arr_vertices[i].ny /= TotalAngles;
00427         arr_vertices[i].nz /= TotalAngles;
00428         // Normalizacion del vector
00429         magnitude = (GLfloat)sqrt(
00430                                ((arr_vertices[i].nx * arr_vertices[i].nx) +
00431                                (arr_vertices[i].ny * arr_vertices[i].ny) +
00432                                (arr_vertices[i].nz * arr_vertices[i].nz))   );
00433         arr_vertices[i].nx /= magnitude;
00434         arr_vertices[i].ny /= magnitude;
00435         arr_vertices[i].nz /= magnitude;
00436     } // for ( i = 0; i < arr_vertices.tam(); i++ )...
00437 
00438     //- 2. OJO: Esto ayuda a que el objeto sea mas manejable! ---------------
00439     if ( centrar_modelo ) {
00440         vertice_promedio.x /= orig_arr_vertices_tam;
00441         vertice_promedio.y /= orig_arr_vertices_tam;
00442         vertice_promedio.z /= orig_arr_vertices_tam;
00443         
00444         for ( i = 0; i < arr_vertices.tam(); i++ ) {
00445             arr_vertices[i].x -= vertice_promedio.x;
00446             arr_vertices[i].y -= vertice_promedio.y;
00447             arr_vertices[i].z -= vertice_promedio.z;
00448 
00449             // Invertir la normal
00450             //arr_vertices[i].nx *= -1;
00451             //arr_vertices[i].ny *= -1;
00452             //arr_vertices[i].nz *= -1;
00453         }
00454     }
00455 
00456     if ( error_vertice_suelto ) {
00457         fprintf(stderr, "<MESH> - Warning: %ld vertices sueltos, de los "
00458                 "%ld vertices del modelo\n", 
00459                 error_vertice_suelto, arr_vertices.tam());
00460         fflush(stderr);
00461     }
00462 }
00463 
00464 void
00465 MESH::cree_lista_de_referencias(void)
00477 {
00478     TRIANGULITO *Triangulo;
00479     TRIANGLENODE *qtr;
00480     int i, j;
00481 
00482     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {
00483         for ( j = 0; j < arr_trozos_gl[i].arr_triangulos.tam(); j++ ) {
00484             /* For each triangle, insert a pointer to the triangle */
00485             /* into a linked list hanging off of each of the three */
00486             /* vertices it touches.                                */
00487             Triangulo = &arr_trozos_gl[i].arr_triangulos[j];
00488 
00489             /* Point One */
00490             qtr = new TRIANGLENODE;
00491             qtr->triangle = Triangulo;
00492             // Inserta el nodo en la cabeza de la lista del vertice T->p0
00493             qtr->sig = listas_de_referencias[Triangulo->p0];
00494             listas_de_referencias[Triangulo->p0] = qtr;
00495             
00496             /* Point Two */
00497             qtr = new TRIANGLENODE;
00498             qtr->triangle = Triangulo;
00499             // Inserta el nodo en la cabeza de la lista del vertice T->p1
00500             qtr->sig = listas_de_referencias[Triangulo->p1];
00501             listas_de_referencias[Triangulo->p1] = qtr;
00502             
00503             /* Point Three */
00504             qtr = new TRIANGLENODE;
00505             qtr->triangle = Triangulo;
00506             // Inserta el nodo en la cabeza de la lista del vertice T->p2
00507             qtr->sig = listas_de_referencias[Triangulo->p2];
00508             listas_de_referencias[Triangulo->p2] = qtr;
00509         }
00510     }
00511 }
00512 
00513 void
00514 MESH::init(void)
00539 {
00540   #ifdef DEBUG_MESH
00541     int vertices_originales = arr_vertices.tam();
00542   #endif
00543     int i, acum_triangulos = 0;
00544 
00545   #ifdef DEBUG_MESH
00546     printf("<MESH>: Recibo un modelo con %ld vertices\n", arr_vertices.tam());
00547     printf("<MESH>: precalculando normales para los vertices... ");
00548     fflush(stdout);
00549   #endif
00550 
00551     if ( calcular_normales ) {
00552         cree_lista_de_referencias();
00553         calcule_normales_vertice();
00554     }
00555 
00556 
00557   #ifdef DEBUG_MESH
00558     printf("Ok!\n"); fflush(stdout);
00559   #endif
00560 
00561     if ( modo_tiras_de_triangulos && ultima_tira == 0 ) crear_tiras();
00562     else if ( ultima_tira == 0 ) crear_trozos_gl();
00563 
00564   #ifdef DEBUG_MESH
00565     if ( preservar_bordes ) {
00566         printf("<MESH>: Se han generado %ld vertices nuevos con normales para "
00567                "preservar\n        la apariencia de los bordes en la geometria"
00568                " del modelo.\n", arr_vertices.tam() - vertices_originales);
00569     }
00570   #endif
00571 
00572     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {
00573         acum_triangulos += arr_trozos_gl[i].arr_triangulos.tam();
00574     }
00575   #ifdef DEBUG_MESH
00576     printf("<MESH>: El modelo quedo con %ld vertices y %d triangulos\n",
00577         arr_vertices.tam(), acum_triangulos);
00578   #endif
00579 
00580     preprocesada = TRUE;
00581 }
00582 
00583 void
00584 MESH::promediar_normales_vertice(void)
00598 {
00599     long i, j;
00600     ARREGLO <BOOLEAN> arr_banderas(arr_vertices.tam());
00601 
00602     //- Desmarcar todos los vertices ----------------------------------------
00603     for ( i = 0; i < arr_vertices.tam(); i++ ) {
00604         arr_banderas.anx(FALSE);
00605     }
00606 
00607     //-----------------------------------------------------------------------
00608     for ( i = 0; i < arr_vertices.tam(); i++ ) {
00609         // El vertice ya habia sido procesado, me lo salto
00610         if ( arr_banderas[i] ) continue;
00611         arr_banderas[i] = TRUE;
00612         // Armo el grupo de todos los vertices cercanos
00613         ARREGLO <int> arr_vecinos(100);
00614         arr_vecinos.anx(i);
00615         for ( j = i+1; j < arr_vertices.tam(); j++ ) {
00616             if ( !arr_banderas[j] &&
00617                 DISTANCIA_VGL(&arr_vertices[i], &arr_vertices[j]) < 30*EPSILON 
00618                ) {
00619                 arr_banderas[j] = TRUE;
00620                 arr_vecinos.anx(j);
00621             }
00622         }
00623         // Promedio la normal y la asigno en todos los vecinos
00624         VECTOR n(0, 0, 0);
00625 
00626         for ( j = 0; j < arr_vecinos.tam(); j++ ) {
00627             n.x += arr_vertices[arr_vecinos[j]].nx;
00628             n.y += arr_vertices[arr_vecinos[j]].ny;
00629             n.z += arr_vertices[arr_vecinos[j]].nz;
00630         }
00631         n.normalizar();
00632         for ( j = 0; j < arr_vecinos.tam(); j++ ) {
00633             arr_vertices[arr_vecinos[j]].nx = (float)n.x;
00634             arr_vertices[arr_vecinos[j]].ny = (float)n.y;
00635             arr_vertices[arr_vecinos[j]].nz = (float)n.z;
00636         }
00637     }
00638 }
00639 
00640 //= OPERACIONES QUE PRECALCULAN DATOS =======================================
00641 
00642 void
00643 MESH::crear_trozos_gl(void)
00651 {
00652     int i, j;
00653 
00654     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {
00655         arr_trozos_gl[i].triangulos_gl = 
00656                 new TRIANGULO_GL[arr_trozos_gl[i].arr_triangulos.tam()+1];
00657         for ( j = 0; j < arr_trozos_gl[i].arr_triangulos.tam(); j++ ) {
00658             arr_trozos_gl[i].triangulos_gl[j].p0 =
00659                 arr_trozos_gl[i].arr_triangulos[j].p0;
00660             arr_trozos_gl[i].triangulos_gl[j].p1 =
00661                 arr_trozos_gl[i].arr_triangulos[j].p1;
00662             arr_trozos_gl[i].triangulos_gl[j].p2 =
00663                 arr_trozos_gl[i].arr_triangulos[j].p2;
00664         }
00665     }
00666 
00667 #ifdef NO_FUNCIONA
00668     //- Dele la vuelta a los triangulos para que queden bien orientados -----
00669     double x1, y1, z1, nx1, ny1, nz1;
00670     double x2, y2, z2, nx2, ny2, nz2;
00671     double x3, y3, z3, nx3, ny3, nz3;
00672     VECTOR l1, l2, normal, anti_normal;
00673     int a, b, c;
00674     GLuint tmp;
00675 
00676     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {                             
00677         for ( j = 0; j < arr_trozos_gl[i].arr_triangulos.tam(); j++ ) {       
00678            a = arr_trozos_gl[i].triangulos_gl[j].p0;
00679            b = arr_trozos_gl[i].triangulos_gl[j].p1;
00680            c = arr_trozos_gl[i].triangulos_gl[j].p2;
00681            nx1 = arr_vertices[a].nx;
00682            ny1 = arr_vertices[a].ny;
00683            nz1 = arr_vertices[a].nz;
00684            x1 = arr_vertices[a].x;
00685            y1 = arr_vertices[a].y;
00686            z1 = arr_vertices[a].z;
00687            nx2 = arr_vertices[b].nx;
00688            ny2 = arr_vertices[b].ny;
00689            nz2 = arr_vertices[b].nz;
00690            x2 = arr_vertices[b].x;
00691            y2 = arr_vertices[b].y;
00692            z2 = arr_vertices[b].z;
00693            nx3 = arr_vertices[c].nx;
00694            ny3 = arr_vertices[c].ny;
00695            nz3 = arr_vertices[c].nz;
00696            x3 = arr_vertices[c].x;
00697            y3 = arr_vertices[c].y;
00698            z3 = arr_vertices[c].z;
00699            normal.x = nx3;
00700            normal.y = ny3;
00701            normal.z = nz3;
00702            l1.x = x1 - x3;    l1.y = y1 - y3;    l1.z = z1 - z3;
00703            l2.x = x2 - x3;    l2.y = y2 - y3;    l2.z = z2 - z3;
00704            anti_normal = l1.producto_cruz(l2);
00705 
00706            if ( anti_normal.producto_punto(normal) < 0 ) {
00707                printf("~"); fflush(stdout);
00708                tmp = arr_trozos_gl[i].triangulos_gl[j].p1;
00709                arr_trozos_gl[i].triangulos_gl[j].p1 = 
00710                    arr_trozos_gl[i].triangulos_gl[j].p0;
00711                arr_trozos_gl[i].triangulos_gl[j].p0 = tmp;
00712            }
00713         }                                                               
00714     }                             
00715     printf("Voy...\n");
00716     fflush(stdout);
00717 #endif // NO_FUNCIONA
00718 
00719 }
00720 
00721 void
00722 MESH::crear_tiras(void)
00730 {
00731     //- Variables -----------------------------------------------------------
00732     int i,j;
00733     FILE *fd_in, *fd_out;
00734     char line[256];
00735     char filename[256];
00736     char command[256];
00737     
00738     printf("<MESH> Generando tiras de triangulos para %ld trozos: [ ",
00739            arr_trozos_gl.tam()); 
00740     fflush(stdout);
00741 
00742     //- Ciclo: Se repite el proceso para cada uno de los trozos_gl ----------
00743     int longitudes_actual;
00744     int inicios_actual;
00745     BOOLEAN primera_tira;
00746 
00747     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {
00748         longitudes_actual = 0;
00749         inicios_actual = 0;
00750         primera_tira = TRUE;
00751         // Generacion de un archivo wavefront (obj) para que lo lea stripe
00752         sprintf(filename, "temp%d.obj", i);
00753         fd_out = fopen(filename, "w");
00754         exportar_obj(fd_out, i);
00755         fclose(fd_out);
00756 
00757         // Ejecucion de la utilidada externa STRIPE
00758       #if PLATAFORMA == i386_WIN32_VC
00759         sprintf(command, "stripe -p %s > shudup", filename); system(command);
00760         sprintf(command, "erase shudup");                    system(command);
00761         sprintf(command, "erase %s", filename);              system(command);
00762       #endif
00763       #if PLATAFORMA != i386_WIN32_VC
00764         sprintf(command, "stripe %s > /dev/null", filename); system(command);
00765         sprintf(command, "rm %s", filename);                 system(command);
00766       #endif
00767 
00768         // Recapture los resultados
00769         strcat(filename, "f");
00770         fd_in = fopen(filename,"r");
00771 
00772         // Count the number of strip points and initialize arr_trozos_gl
00773         while ( fscanf(fd_in, "%s", line) != EOF ) {
00774             switch( line[0] ) {
00775               case '#': // # is a comment, v is a vertex, we ignore both
00776               case 'v':
00777                 while (fgetc(fd_in) != '\n');
00778                 break;
00779               case 't': // t is the start of a new triangle strip
00780                 if ( primera_tira ) {
00781                     primera_tira = FALSE;
00782                   }
00783                   else {
00784                     arr_trozos_gl[i].inicios_tiras.anx(inicios_actual);
00785                     arr_trozos_gl[i].longitudes_tiras.anx(longitudes_actual);
00786                     longitudes_actual = 0;
00787                 }
00788                 break;
00789               case 'q': // q is another entry in the current strip
00790               case '%': // % is a STRIPE type
00791                 break;
00792               default: //Anything else is a point in the current triangle strip
00793                 arr_trozos_gl[i].indices_vertices_tiras.anx((GLuint)(atoi(line)-1));
00794                 inicios_actual++;
00795                 longitudes_actual++;
00796                 break;
00797             }
00798         }
00799         arr_trozos_gl[i].inicios_tiras.anx(inicios_actual);
00800         arr_trozos_gl[i].longitudes_tiras.anx(longitudes_actual);
00801         fclose(fd_in);
00802 
00803         //------------------------------------------------------------------
00804       #if PLATAFORMA == i386_WIN32_VC
00805         sprintf(command, "erase %s", filename);        system(command);
00806       #endif
00807       #if PLATAFORMA != i386_WIN32_VC
00808         sprintf(command, "rm %s", filename);           system(command);
00809       #endif
00810 
00811         for ( j = 0; j < arr_trozos_gl[i].indices_vertices_tiras.tam(); j++ ) {
00812             if ( 
00813                  /* OJO: Notese que la 1ra condicion siempre es TRUE */
00814                  /* arr_trozos_gl[i].indices_vertices_tiras[j] < (GLuint)0 || */
00815                  arr_trozos_gl[i].indices_vertices_tiras[j] > (GLuint)(arr_vertices.tam()-1)
00816                 ) {
00817                 exit(-1);
00818             }
00819         }
00820         printf("."); fflush(stdout);
00821     }
00822     printf(" ] Ok.\n");  fflush(stdout);
00823     con_minmax = FALSE;
00824 }
00825 
00826 //= OPERACIONES QUE PERMITEN IMPORTAR DATOS DESDE OTRAS CLASES ==============
00827 
00828 int
00829 MESH::encontrar_material(char *name)
00830 /* Finds the index of the material in question */
00831 {
00832     int n;
00833 
00834     for ( n = 0; n < arr_trozos_gl.tam(); n++ ) {
00835         if ( strcmp(name, arr_trozos_gl[n].material.nombre()) == 0 ) {
00836             return n;
00837         }
00838     }
00839 
00840     if ( n >= arr_trozos_gl.tam() ) {
00841         if ( arr_trozos_gl.tam() ) {
00842             fprintf(stderr, "!");
00843             fflush(stderr);
00844             return 0;
00845         }
00846         fprintf(stderr, "<MESH> - ERROR: No se encuentra el material \"%s\"\n",
00847             name);
00848         fprintf(stderr, "<MESH> No hay materiales, abortando"); fflush(stderr);
00849         exit(-1); 
00850     }
00851     return 0;
00852 }
00853 
00854 BOOLEAN
00855 MESH::calcule_normal_triangulo(TRIANGULITO *Triangulo)
00861 {
00862     VECTOR normal, p0, p1, p2, a, b;
00863 
00864     p0.x = arr_vertices[Triangulo->p0].x;
00865     p0.y = arr_vertices[Triangulo->p0].y;
00866     p0.z = arr_vertices[Triangulo->p0].z;
00867     p1.x = arr_vertices[Triangulo->p1].x;
00868     p1.y = arr_vertices[Triangulo->p1].y;
00869     p1.z = arr_vertices[Triangulo->p1].z;
00870     p2.x = arr_vertices[Triangulo->p2].x;
00871     p2.y = arr_vertices[Triangulo->p2].y;
00872     p2.z = arr_vertices[Triangulo->p2].z;
00873 
00874     a = p1 - p0; //a.normalizar();
00875     b = p2 - p0; //b.normalizar();
00876     normal = a.producto_cruz(b);
00877 
00878     if ( normal.norma() == 0 ) {
00879         // OJO: Triangulo invalido, normal indeterminada!
00880         fprintf(stderr, "-"); fflush(stdout);
00881         return FALSE;
00882     }
00883 
00884     normal.normalizar();
00885 
00886     Triangulo->nx = (float)normal.x;
00887     Triangulo->ny = (float)normal.y;
00888     Triangulo->nz = (float)normal.z;
00889 
00890     return TRUE;
00891 }
00892 
00893 void
00894 MESH::anx_indice_tira(long int i)
00898 {
00899     arr_trozos_gl[0].indices_vertices_tiras.anx(i);
00900 }
00901 
00902 void
00903 MESH::anx_tira(void)
00908 {
00909     long int a = arr_trozos_gl[0].indices_vertices_tiras.tam();
00910     arr_trozos_gl[0].inicios_tiras.anx(ultima_tira);
00911     arr_trozos_gl[0].longitudes_tiras.anx(a-ultima_tira);
00912     modo_tiras_de_triangulos = TRUE;
00913     ultima_tira = a;
00914 }
00915 
00916 void
00917 MESH::anx_vertex(VERTICE_GL v)
00918 /* Adds a vertex to the vertex list */
00919 {
00920     //-----------------------------------------------------------------------
00921     arr_vertices.anx(v);
00922 
00923     //-----------------------------------------------------------------------
00924     vertice_promedio.x += v.x;
00925     vertice_promedio.y += v.y;
00926     vertice_promedio.z += v.z;
00927 
00928     //-----------------------------------------------------------------------
00929     /*  Add a slot into the array we're building to keep track of which     
00930      * triangles are part of which vertices, which will be used to build 
00931      * vertex normals.  */
00932     listas_de_referencias.anx(NULL);
00933 }
00934 
00935 void
00936 MESH::anx_color(GLubyte r, GLubyte g, GLubyte b)
00937 {
00938     arr_colores.anx(r);
00939     arr_colores.anx(g);
00940     arr_colores.anx(b);
00941 }
00942 
00943 void
00944 MESH::anx_triangle(TRIANGULO_GL tri, char *nombre_material)
00949 {
00950     // Verifique que es un triangulo valido
00951     unsigned long int ta;
00952 
00953     ta = arr_vertices.tam();
00954     if ( tri.p0 >= ta || tri.p1 >= ta || tri.p2 >= ta ) return;
00955     // Mmm... si son unsigned int's tiene sentido comparar contra < 0?
00956     //if ( tri.p0 < 0 || tri.p1 < 0 || tri.p2 < 0 ) return;
00957 
00958     // Determine el grupo en base al material del triangulo
00959     int MatNum;
00960     TROZO_GL *list;
00961 
00962     MatNum = encontrar_material(nombre_material);
00963     list = &arr_trozos_gl[MatNum];
00964 
00965     // Si el orden es inverso... 
00966     TRIANGULITO t;
00967 
00968     if ( _invertir_orden ) {
00969         t.p0 = tri.p0;
00970         t.p1 = tri.p2;
00971         t.p2 = tri.p1;
00972       }
00973       else {
00974         t.p0 = tri.p0;
00975         t.p1 = tri.p1;
00976         t.p2 = tri.p2;
00977     }
00978 
00979     // Si el triangulo no es colineal, insertelo
00980     if ( !calcule_normal_triangulo(&t) ) return;
00981     list->arr_triangulos.anx(t);
00982 }
00983 
00984 void
00985 MESH::anx_material(COLOR ambient, COLOR diffuse, COLOR specular,
00986              char *name, char *texname, int caras_dobles)
00987 /* Add a material to the model */
00988 {
00989     //-----------------------------------------------------------------------
00990     COLOR e(0, 0, 0);
00991     TROZO_GL t;
00992 
00993     t.material.set_nombre(name);
00994     strcpy(t.texturename, texname);
00995     t.material.set_ambiente(ambient);
00996     t.material.set_difusa(diffuse);
00997     t.material.set_especular(specular);
00998     t.material.set_emision(e);
00999     t.material.set_transparencia(1);
01000     if ( caras_dobles ) {
01001        t.material.set_doble_cara(TRUE);
01002     }
01003 
01004     //-----------------------------------------------------------------------
01005     arr_trozos_gl.anx(t);
01006 }
01007 
01008 //= OPERACIONES STANDARD DE GEOMETRIA AQUYNZA ===============================
01009 
01010 void
01011 MESH::anexar_textura(IMAGEN *img)
01012 { 
01013     if ( imagen ) delete imagen;
01014     imagen = img;
01015 }
01016 
01017 int
01018 MESH::clasificar_punto(VECTOR /*p*/)
01019 {
01020     return 0;
01021 }
01022 
01023 void
01024 MESH::minmax(VECTOR *min, VECTOR *max)
01025 {
01026     int i, j, k;
01027     VECTOR p;
01028 
01029     if ( !preprocesada ) {
01030         init();
01031     }    
01032 
01033     if ( !con_minmax ) {
01034         _min.x = INFINITO;
01035         _min.y = INFINITO;
01036         _min.z = INFINITO;
01037         _max.x = -INFINITO;
01038         _max.y = -INFINITO;
01039         _max.z = -INFINITO;
01040     
01041         for ( i = 0; !modo_tiras_de_triangulos && i < arr_trozos_gl.tam(); i++ ) {
01042             for ( j = 0; j < arr_trozos_gl[i].arr_triangulos.tam(); j++ ) {
01043                 p.x = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].x;
01044                 p.y = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].y;
01045                 p.z = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].z;
01046                 COMPARAR_MM();
01047                 p.x = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].x;
01048                 p.y = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].y;
01049                 p.z = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].z;
01050                 COMPARAR_MM();
01051                 p.x = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].x;
01052                 p.y = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].y;
01053                 p.z = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].z;
01054                 COMPARAR_MM();
01055             }
01056         }
01057     
01058         for ( i = 0; modo_tiras_de_triangulos && i < arr_trozos_gl.tam(); i++ ) {
01059             for ( j = 0; j < arr_trozos_gl[i].indices_vertices_tiras.tam(); j++ ) {
01060                 k = arr_trozos_gl[i].indices_vertices_tiras[j];
01061                 p.x = arr_vertices[k].x;
01062                 p.y = arr_vertices[k].y;
01063                 p.z = arr_vertices[k].z;
01064                 COMPARAR_MM();
01065                 p.x = arr_vertices[k].x;
01066                 p.y = arr_vertices[k].y;
01067                 p.z = arr_vertices[k].z;
01068                 COMPARAR_MM();
01069                 p.x = arr_vertices[k].x;
01070                 p.y = arr_vertices[k].y;
01071                 p.z = arr_vertices[k].z;
01072                 COMPARAR_MM();
01073             }
01074         }
01075     
01076         _min.x *= escala;
01077         _min.y *= escala;
01078         _min.z *= escala;
01079         _max.x *= escala;
01080         _max.y *= escala;
01081         _max.z *= escala;
01082         con_minmax = TRUE;
01083     }
01084     (*min) = _min;
01085     (*max) = _max;
01086 }
01087 
01088 void
01089 MESH::pintar_aqz(FILE *fd)
01090 {
01091     fprintf(fd, "    // Pilas: No hay pintar_aqz... \n");
01092     fprintf(fd, "    geometria ESFERA 1 \"\"\n");
01093 }
01094 
01095 void
01096 MESH::pintar_povray(FILE *fd)
01097 {
01098     float x1, y1, z1;
01099     float x2, y2, z2;
01100     float x3, y3, z3;
01101     //float nx1, ny1, nz1;
01102     //float nx2, ny2, nz2;
01103     //float nx3, ny3, nz3;
01104     int i, j;
01105 
01106     if ( !preprocesada ) init();
01107 
01108     fprintf(fd, "merge {\n");
01109     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {                             
01110         fprintf(fd, "mesh {\n");
01111         for ( j = 0; j < arr_trozos_gl[i].arr_triangulos.tam(); j++ ) {       
01112            //nx1 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].nx;
01113            //ny1 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].ny;
01114            //nz1 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].nz;
01115            x1 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].x;
01116            y1 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].y;
01117            z1 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p0].z;
01118            //nx2 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].nx;
01119            //ny2 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].ny;
01120            //nz2 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].nz;
01121            x2 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].x;
01122            y2 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].y;
01123            z2 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p1].z;
01124            //nx3 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].nx;
01125            //ny3 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].ny;
01126            //nz3 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].nz;
01127            x3 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].x;
01128            y3 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].y;
01129            z3 = arr_vertices[arr_trozos_gl[i].triangulos_gl[j].p2].z;
01130 
01131            fprintf(fd, "    triangle {<%f,%f,%f>,<%f,%f,%f>,<%f,%f,%f>}\n",
01132                x1*escala, y1*escala, z1*escala, x2*escala, y2*escala,
01133                z2*escala, x3*escala, y3*escala, z3*escala);
01134 
01135 #ifdef NO_FUNCIONA_ESTO_EN_POV
01136            fprintf(fd, "    smooth_triangle {");
01137            fprintf(fd, "<%.4f,%.4f,%.4f>,<%.4f,%.4f,%.4f>,",
01138                x1*escala, nx1, y1*escala, ny1, z1*escala, nz1);
01139            fprintf(fd, "<%.4f,%.4f,%.4f>,<%.4f,%.4f,%.4f>,",
01140                x2*escala, nx2, y2*escala, ny2, z2*escala, nz2);
01141            fprintf(fd, "<%.4f,%.4f,%.4f>,<%.4f,%.4f,%.4f>}\n",
01142                x3*escala, nx3, y3*escala, ny3, z3*escala, nz3);
01143 #endif
01144         }
01145         arr_trozos_gl[i].material.activar_povray(fd);
01146         fprintf(fd, "}");
01147     }
01148 
01149 
01150 }
01151 
01152 //===========================================================================
01153 
01154 int
01155 MESH::num_grupos(void)
01160 {
01161     return arr_trozos_gl.tam();
01162 }
01163 
01164 long int
01165 MESH::num_vertices(void)
01166 {
01167     return arr_vertices.tam();
01168 }
01169 
01170 long int
01171 MESH::num_triangulos(void)
01172 {
01173     int i;
01174     long int accum = 0;
01175 
01176     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {
01177         accum += arr_trozos_gl[i].arr_triangulos.tam();
01178     }
01179     return accum;
01180 }
01181 
01182 void
01183 MESH::controlar(BOOLEAN *arr_control)
01189 {
01190     Arr_control = arr_control;
01191   #ifdef GL_ENABLED
01192     preprocesada_gl = FALSE;
01193   #endif 
01194 }
01195 
01196 void
01197 MESH::set_pintado_normales(BOOLEAN c)
01198 {
01199     pintar_normales = c;
01200   #ifdef GL_ENABLED
01201     preprocesada_gl = FALSE;
01202   #endif
01203 }
01204 
01205 void
01206 MESH::set_debug_vertices(BOOLEAN c)
01207 {
01208     pintar_debug_vertices = c;
01209   #ifdef GL_ENABLED
01210     preprocesada_gl = FALSE;
01211   #endif
01212 }
01213 
01214 void
01215 MESH::set_debug_triangulos(BOOLEAN c)
01216 {
01217     pintar_debug_triangulos = c;
01218   #ifdef GL_ENABLED
01219     preprocesada_gl = FALSE;
01220   #endif
01221 }
01222 
01223 void
01224 MESH::set_debug_vertices_index(long int i)
01225 {
01226     index_debug_vertice = i;
01227 }
01228 
01229 void
01230 MESH::set_debug_triangulos_index(long int i)
01231 {
01232     index_debug_triangulo = i;
01233 }
01234 
01235 void
01236 MESH::set_material_global(BOOLEAN m)
01237 {
01238     material_global = m;
01239   #ifdef GL_ENABLED
01240     preprocesada_gl = FALSE;
01241   #endif
01242 }
01243 
01244 void
01245 MESH::set_debug_tiras(BOOLEAN t)
01246 {
01247     mostrar_tiras = t;
01248   #ifdef GL_ENABLED
01249     preprocesada_gl = FALSE;
01250   #endif
01251 }
01252 
01253 void
01254 MESH::imprimir(BOOLEAN full_report)
01255 {
01256     int i, j, num_tri;
01257     long int ttt = 0;
01258     long int tttiras = 0;
01259     long int num_con_textura = 0;
01260 
01261     if ( !preprocesada ) init();
01262 
01263     //-----------------------------------------------------------------------
01264     for ( i = 0; i < arr_trozos_gl.tam(); i++ ) {
01265         if ( arr_trozos_gl[i].texturename && 
01266              strlen(arr_trozos_gl[i].texturename) ) {
01267             num_con_textura++;
01268         }
01269     }
01270     
01271     //-----------------------------------------------------------------------
01272     if ( full_report ) {
01273         printf(
01274 "= MESH ====================================================================\n"
01275         );
01276 
01277         if ( _nombre_de_archivo ) {
01278             printf("  - Geometria importada del archivo \"%s\".\n", 
01279                    _nombre_de_archivo);
01280         }
01281 
01282         printf("  - Modo: %s %s uso de listas precompiladas OpenGL\n",
01283                modo_tiras_de_triangulos?"tiras de triangulos":
01284                "triangulos sueltos",
01285                con_lista_gl?"con":"sin");
01286       #ifdef GL_COMPLETO
01287         printf("  - Usando primitivas de OpenGL 1.1 (arreglos de datos)\n");
01288       #endif
01289       #ifndef GL_COMPLETO
01290         printf(
01291             "  - Usando primitivas de OpenGL 1.0 (SIN arreglos de datos)\n");
01292       #endif
01293     }
01294 
01295     if ( full_report ) {
01296         printf("  - %ld vertices en la estructura\n", num_vertices()); 
01297         fflush(stdout);
01298     }
01299     char cc;
01300 
01301     if ( arr_trozos_gl.tam() < 1 ) {
01302         printf("  - ESTRUCTURA VACIA!\n");
01303     }
01304     else {
01305         if ( full_report ) {
01306             if ( arr_trozos_gl.tam() == 1 ) {
01307                 printf("  - La estructura consiste de un solo grupo\n");
01308             }
01309             else{
01310                 printf("  - La estructura contiene %ld grupos:\n",
01311                     arr_trozos_gl.tam());
01312             }
01313         }
01314         for ( i = 0; !modo_tiras_de_triangulos && i < arr_trozos_gl.tam(); i++ ) {
01315             if ( full_report ) {
01316                 if ( !Arr_control ) {
01317                     cc = '=';
01318                   }
01319                   else if ( Arr_control[i] ) {
01320                     cc = '*';
01321                   }
01322                   else {
01323                       cc = '.';
01324                   }
01325                 ;
01326                 printf("    [%c] Grupo %d: %ld triangulos.\n", cc, i+1,
01327                        arr_trozos_gl[i].arr_triangulos.tam());
01328             }
01329             ttt += arr_trozos_gl[i].arr_triangulos.tam();
01330         }
01331         for ( i = 0; modo_tiras_de_triangulos && i < arr_trozos_gl.tam(); i++ ) {
01332             if ( full_report ) {
01333                 if ( !Arr_control ) {
01334                     cc = '=';
01335                   }
01336                   else if ( Arr_control[i] ) {
01337                     cc = '*';
01338                   }
01339                   else {
01340                     cc = '.';
01341                   }
01342                 ;
01343                 printf("    [%c] Grupo %2d: %3ld tiras, ", cc, i+1,
01344                        arr_trozos_gl[i].longitudes_tiras.tam());
01345             }
01346             num_tri = 0;
01347             for ( j = 0; j < arr_trozos_gl[i].longitudes_tiras.tam(); j++ ) {
01348                     //printf("%d ", arr_trozos_gl[i].longitudes_tiras[j]);
01349                 num_tri += arr_trozos_gl[i].longitudes_tiras[j];
01350                 tttiras++;
01351             }
01352             if ( full_report ) {
01353                 printf("%d triangulos (%.2f triangulos por tira)\n", num_tri,
01354                        (double)num_tri/(double)arr_trozos_gl[i].longitudes_tiras.tam());
01355             }
01356             ttt += num_tri;
01357         }
01358     }
01359 
01360     if ( full_report ) {
01361         printf("  - %ld triangulos en total.\n", ttt);
01362         printf("  - %ld nombres de textura definidos.\n", num_con_textura);
01363         printf(
01364 "===========================================================================\n"
01365         );
01366         printf("\n");
01367     }
01368     else {
01369         printf("%ld triangulos, ", ttt);
01370         if ( arr_trozos_gl.tam() != 1 ) {
01371             printf("%ld trozos, %ld referencias a textura.", 
01372                    arr_trozos_gl.tam(), num_con_textura);
01373           }
01374           else {
01375             printf("1 trozo.");
01376         }
01377         if ( modo_tiras_de_triangulos ) {
01378             printf(" %ld tiras, %.2f triangulos por tira, %ld referencias a textura.", tttiras,
01379                 (double)ttt/(double)tttiras, num_con_textura);
01380         }
01381         if ( _nombre_de_archivo ) {
01382             printf("\t%s", _nombre_de_archivo);
01383         }
01384         printf("\n");
01385     }
01386 
01387     fflush(stdout);
01388 }
01389 
01390 BOOLEAN
01391 MESH::exportar_obj(FILE *fd, int i)
01396 {
01397     int j;
01398 
01399     fprintf(fd, "# Archivo .obj generado por AQUYNZA\n");
01400     for ( j = 0; j < arr_vertices.tam(); j++ ) {
01401         fprintf(fd, "v %f %f %f\n",
01402             arr_vertices[j].x, arr_vertices[j].y, arr_vertices[j].z);
01403     }
01404     fprintf(fd, "\n");
01405     for ( j = 0; j < arr_trozos_gl[i].arr_triangulos.tam(); j++ ) {
01406         // Notese que en el formato Wavefront - OBJ los indices se numeran
01407         // desde 1 y NO desde 0.
01408         fprintf(fd, 
01409                 "f %d %d %d\n", 
01410                 arr_trozos_gl[i].arr_triangulos[j].p0+1,
01411                 arr_trozos_gl[i].arr_triangulos[j].p1+1,
01412                 arr_trozos_gl[i].arr_triangulos[j].p2+1);
01413     }
01414     return TRUE;
01415 }
01416 
01417 void
01418 MESH::anexar_trozo_obj(char *linea)
01432 {
01433     TRIANGULO_GL t, t2, t3, t4, t5, t6, t7;
01434     
01435     //- ATENCION: Recuerde que CRAY no soporta inicializaciones aqui! -------
01436     t.p0  = 0;    t.p1  = 0;    t.p2  = 0;
01437     t2.p0 = 0;    t2.p1 = 0;    t2.p2 = 0;
01438     t3.p0 = 0;    t3.p1 = 0;    t3.p2 = 0;
01439     t4.p0 = 0;    t4.p1 = 0;    t4.p2 = 0;
01440     t5.p0 = 0;    t5.p1 = 0;    t5.p2 = 0;
01441     t6.p0 = 0;    t6.p1 = 0;    t6.p2 = 0;
01442     t7.p0 = 0;    t7.p1 = 0;    t7.p2 = 0;
01443 
01444     //-----------------------------------------------------------------------
01445     char *ptr;
01446     LISTA <char*> tokens;
01447     int i;
01448 
01449     //-----------------------------------------------------------------------
01450     for ( ptr = strtok(linea, " \t\n"); ptr; ptr = strtok(NULL, " \t\n") ) {
01451         tokens.anx(ptr);
01452     }
01453     for ( i = 0; i < (int)strlen(linea); i++ ) {
01454         if ( linea[i] == '/' ) linea[i] = ' ';
01455     }
01456 
01457     for ( i = 0; i < tokens.tam(); i++ ) {
01458         switch ( i ) {
01459           case 0: break;
01460           case 1: t.p0 = atoi(tokens[i]) - 1; break;
01461           case 2: t.p1 = atoi(tokens[i]) - 1; break;
01462           case 3: t.p2 = atoi(tokens[i]) - 1; break;
01463           case 4:
01464             t2.p0 = t.p0;
01465             t2.p1 = t.p2;
01466             t2.p2 = atoi(tokens[i]) - 1;
01467             anx_triangle(t2, "WG_DEFAULT");
01468             break;
01469           case 5:
01470             t3.p0 = t2.p0;
01471             t3.p1 = t2.p2;
01472             t3.p2 = atoi(tokens[i]) - 1;
01473             anx_triangle(t3, "WG_DEFAULT");
01474             break;
01475           case 6:
01476             t4.p0 = t3.p0;
01477             t4.p1 = t3.p2;
01478             t4.p2 = atoi(tokens[i]) - 1;
01479             anx_triangle(t4, "WG_DEFAULT");
01480             break;
01481           case 7:
01482             t5.p0 = t4.p0;
01483             t5.p1 = t4.p2;
01484             t5.p2 = atoi(tokens[i]) - 1;
01485             anx_triangle(t5, "WG_DEFAULT");
01486             break;
01487           case 8:
01488             t6.p0 = t5.p0;
01489             t6.p1 = t5.p2;
01490             t6.p2 = atoi(tokens[i]) - 1;
01491             anx_triangle(t6, "WG_DEFAULT");
01492             break;
01493           case 9:
01494             t7.p0 = t6.p0;
01495             t7.p1 = t6.p2;
01496             t7.p2 = atoi(tokens[i]) - 1;
01497             anx_triangle(t7, "WG_DEFAULT");
01498             break;
01499           default: break;
01500         }
01501     }
01502     anx_triangle(t, "WG_DEFAULT");
01503     tokens.elim();
01504 }
01505 
01506 BOOLEAN
01507 MESH::importar_obj(char *archivo, double *Escala_optima)
01508 {
01509     FILE *fd;
01510     char linea[1024];
01511 
01512     //- Abra el archivo -----------------------------------------------------
01513     fd = fopen(archivo, "rt");
01514     if ( !fd ) {
01515         fprintf(stderr, "ERROR: No se puede abrir el archivo!\n");
01516         fflush(stderr);
01517         return FALSE;
01518     }
01519     set_nombre_de_archivo(archivo);
01520 
01521     // Esto es para calcular el factor de escala optima
01522     VECTOR min, max, factor;
01523     VECTOR accum(0, 0, 0);
01524 
01525     min.x = INFINITO;
01526     min.y = INFINITO;
01527     min.z = INFINITO;
01528     max.x = -INFINITO;
01529     max.y = -INFINITO;
01530     max.z = -INFINITO;
01531 
01532     //printf("Importando OBJ...\n"); fflush(stdout);
01533 
01534     //-----------------------------------------------------------------------
01535     COLOR ambient, diffuse, specular;
01536 
01537     //- Felizmente es barato tener oro en la realidad virtual :-)
01538     ambient.r = ambient.g = ambient.b = 0.2f;
01539     diffuse.r = 0.85f;
01540     diffuse.g = 0.85f;
01541     diffuse.b = 0.1f;
01542     specular.r = specular.g = specular.b = 1.0;
01543     ambient.alpha = diffuse.alpha = specular.alpha = 1.0;
01544     anx_material(ambient, diffuse, specular, "WG_DEFAULT", "", 0);
01545 
01546     //- Cree la estructura --------------------------------------------------
01547     VECTOR e;
01548     MATRIZ_4x4 R;
01549     VERTICE_GL v;
01550     char *ptr;
01551 
01552     // OJO: Wavefront, respecto a AQUYNZA, suele ver sus coordenadas 90
01553     //      grados volteada...
01554     R.rotacion_angulos_euler(DEG2RAD(-90), 0, DEG2RAD(90)); 
01555 
01556     while ( fgets(linea, 1023, fd) ) {
01557         if ( linea[0] == 'v' && linea[1] == ' ' ) {
01558             // Leo e
01559             ptr = strtok(linea, " \t\n");
01560             ptr = strtok(NULL, " \t\n");
01561             e.x = atof(ptr);
01562             ptr = strtok(NULL, " \t\n");
01563             e.y = atof(ptr);
01564             ptr = strtok(NULL, " \t\n");
01565             e.z = atof(ptr);
01566             e = R * e;
01567             accum = accum + e;
01568 
01569             // Calculo el vertice
01570             v.x = (float)e.x;
01571             v.y = (float)e.y;
01572             v.z = (float)e.z;
01573 
01574             //e.normalizar();  // OJO!
01575             //v.nx = e.x;
01576             //v.ny = e.y;
01577             //v.nz = e.z;
01578 
01579             // Llevo los extremos
01580             if ( v.x < min.x ) min.x = v.x;
01581             if ( v.y < min.y ) min.y = v.y;
01582             if ( v.z < min.z ) min.z = v.z;
01583             if ( v.x > max.x ) max.x = v.x;
01584             if ( v.y > max.y ) max.y = v.y;
01585             if ( v.z > max.z ) max.z = v.z;
01586 
01587             anx_vertex(v);
01588         }       
01589         if ( linea[0] == 'f' && linea[1] == ' ' ) {
01590             anexar_trozo_obj(linea);
01591         }
01592     }
01593 
01594     //-----------------------------------------------------------------------
01595     VECTOR p;
01596     VECTOR o(0, 0, 0);
01597     int i;
01598     double theta, phi;
01599 
01600     factor = max - min;
01601     *(Escala_optima) = 5/factor.norma();
01602     //o = accum/arr_vertices.tam();
01603     //o = (max + min) / 2;
01604 
01605     // Estimo las coordenadas de la textura!
01606     for ( i = 0; i < arr_vertices.tam(); i++ ) {
01607         // Se calcula u
01608         p.x = arr_vertices[i].x;
01609         p.y = arr_vertices[i].y;
01610         p.z = arr_vertices[i].z;
01611         p = p - o;
01612         p.normalizar();
01613 
01614         phi = acos(p.z);
01615         if ( fabs(sin(phi)) < EPSILON ) theta = 0;
01616         if ( p.y > -EPSILON ) theta = acos(p.x/sin(phi));
01617         else theta = 2*PI - acos(p.x/sin(phi));
01618 
01619         theta /= 2*PI;
01620         phi /= -PI;
01621         while( phi < 0 ) phi += 1;
01622         while( theta < 0 ) theta += 1;
01623         while( phi > 1 ) phi -= 1;
01624         while( theta > 1 ) theta -= 1;
01625         //
01626 
01627         //arr_vertices[i].u = (float)(p.y - o.y) / (max.y - min.y) + 0.5;
01628         arr_vertices[i].u = (float)(theta);
01629 
01630         // Se calcula v
01631         //arr_vertices[i].v = (float)(p.z - o.z)/(max.z - min.z) + 0.5;
01632         arr_vertices[i].v = (float)(phi);
01633     }
01634     //calcular_normales = FALSE; // OJO: Solo si quiero enviromental map!
01635 
01636     calcular_normales = TRUE;
01637 
01638     return TRUE;
01639 }
01640 
01641 //===========================================================================
01642 //= EOF                                                                     =
01643 //===========================================================================
01644 

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.