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

bsp_2d.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= bsp_2d.cc                       Noviembre/diciembre 1997, Junio de 1999 =
00003 //=-------------------------------------------------------------------------=
00004 //= Clases de representacion de interiores de solidos rigidos modelados por =
00005 //= la frontera, con enfasis en espacios arquitectonicos sencillos.         =
00006 //= Esquema de representacion compatible con los niveles de juego DOOM-WAD  =
00007 //= de idSoftware.                                                          =
00008 //= Notese que este modulo esta organizado en 3 grandes secciones:          =
00009 //=   - Definicion de una representacion geometrica tipo BREP               =
00010 //=   - Definicion de una particion espacial binaria (BSP) sobre dicha      =
00011 //=     estructura geometrica                                               =
00012 //=   - Definicion de la estructura publica que encapsula y exporta los     =
00013 //=     servicios de la representacion a los demas modulos AQUYNZA.         =
00014 //= Cabe la posibilidad de que este modulo este sobrepasando los limites de =
00015 //= manejabilidad, por ser tan grande y complejo.  En caso de decidir sub-  =
00016 //= dividirlo en mas modulos, se propone que se subdivida en tres, uno para =
00017 //= cada una de las actuales secciones.                                     =
00018 //=-------------------------------------------------------------------------=
00019 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00020 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00021 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00022 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00023 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00024 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00025 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00026 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00027 //=-------------------------------------------------------------------------=
00028 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00029 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00030 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00031 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00032 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
00033 //===========================================================================
00034 
00035 #include <ctype.h>
00036 #include <limits.h>
00037 #include <stdio.h>
00038 #include <string.h>
00039 
00040 #include "jed_gl.h"
00041 #include "toolkits/geom/bsp_2d.h"
00042 #include "matriz4.h"
00043 #include "triangulate.h"
00044 #include "lista.cc"
00045 
00046 //===========================================================================
00047 //= Variables globales                                                      =
00048 //===========================================================================
00049 
00050 #ifdef GL_ENABLED
00051 static GLenum PRIMITIVA_triangulos = GL_TRIANGLES;
00052 static GLenum PRIMITIVA_cuadros = GL_QUADS;
00053 static int NUM_poligonos;  // Esto esta aqui para hacer pruebas para medir
00054                            // el funcionamiento de la estructura BSP.
00055 #endif
00056 
00057 //===========================================================================
00058 //= Constantes y macros                                                     =
00059 //===========================================================================
00060 
00061 #define BIT_15  (1 << 15)
00062 #define FX 0.95
00063 #define ESCALA_ALTURA 1.28
00064 
00065 #define A_METROS(recuadro) (  ((double)(recuadro) - 32768.0)/50.0  )
00066 #define A_RECUADROS(metros) ( (WORD)(50 * metros + 32768.0)  )
00067 
00068 #define PINTAR_VERTICE(v, altura) \
00069      glVertex3d( A_METROS((v).x), A_METROS((v).y), ESCALA_ALTURA*A_METROS((altura+32768)) );
00070 
00071 #define CORREGIR(v) \
00072     if ( (v)  > 32768 ) (v) -= 32768; else (v) += 32768;
00073 
00074 #define VERIFIQUE(var, mensaje, cantidad) \
00075     if ( !var ) { \
00076         fprintf(stderr, mensaje, cantidad); \
00077         fflush(stdout); \
00078         return FALSE; \
00079     }
00080 
00081 #define CHEQUEO_WAD(pointer, mensaje)                                     \
00082     if ( !(pointer) ) {                                                   \
00083         fprintf(stderr, "<BSP_2D> - ERROR FATAL: \n    %s\n", (mensaje)); \
00084         return FALSE;                                                     \
00085     }
00086 
00087 #define PINTAR_RECTA(q, v)                                              \
00088     glBegin(GL_LINES);                                                  \
00089         glVertex3d((q).x, (q).y, (q).z+0.01);                           \
00090         glVertex3d((q).x + (v).x, (q).y + (v).y, (q).z + (v).z+0.01);   \
00091     glEnd();
00092 
00093 #define ACTIVAR_TEXTURA_PARED(textura_id)               \
00094     if ( (textura_id) >= 0 &&                           \
00095          Calidad->con_textura && Calidad->con_caras ) { \
00096         Padre->sprites[(textura_id)]->activar_gl();     \
00097     }
00098 
00099 //===========================================================================
00100 //= Servicios varios locales a este modulo                                  =
00101 //===========================================================================
00102 
00103 static inline BOOLEAN
00104 se_intersectan(VECTOR q1, VECTOR v1,
00105                VECTOR q2, VECTOR v2)
00111 {
00112     double numerador, denominador, t;
00113     denominador = v1.x*v2.y - v1.y*v2.x;
00114     if ( fabs(denominador) < EPSILON ) return FALSE;
00115     numerador = (v2.x*(q1.y-q2.y)) + (v2.y*(q2.x - q1.x));
00116     t = numerador/denominador;
00117     if ( t < 0 ) return FALSE;
00118     return TRUE;
00119 }
00120 
00121 //===========================================================================
00122 //= INFORMACION GENERAL RESPECTO A LAS CLASES                               =
00123 //=-------------------------------------------------------------------------=
00124 //= Debe notarse que la mayoria de clases tienen dos metodos en comun:      =
00125 //=     void importe_wad(WAD_LEVEL *Nivel_wad, WORD pos);    y              =
00126 //=     void pintar_gl(const _BSP2D_VERTICEi min, const _BSP2D_VERTICEi max);        =
00127 //= El metodo importe_wad lee a partir de un archivo WAD de IdSoftware los  =
00128 //= datos necesarios para el pos-esimo objeto, verificando el rango de pos  =
00129 //= y la existencia real de datos.  Obtenga mayor informacion en la         =
00130 //= documentacion de DOOM y en las clases del modulo jedi_wad.              =
00131 //= El metodo pintar_gl ejecuta primitivas del Api OpenGL.                   =
00132 //===========================================================================
00133 
00134 
00135 //=*************************************************************************=
00136 //= PRIMERA SECCION: CLASES DE LA REPRESENTACION GEOMETRICA BREP            =
00137 //=-------------------------------------------------------------------------=
00138 //= Aqui se encuentran, en este orden, las siguientes clases:               =
00139 //=   - _BSP2D_ARCO                                                         =
00140 //=   - _BSP2D_PARED                                                        =
00141 //=   - _BSP2D_SEGMENTOi                                                     =
00142 //=   - _BSP2D_SECTOR                                                       =
00143 //=*************************************************************************=
00144 
00145 //===========================================================================
00146 //= Clase _BSP2D_ARCO                                                       =
00147 //===========================================================================
00148 
00149 _BSP2D_ARCO::_BSP2D_ARCO()
00150 {
00151     Padre = NULL;
00152     Izq = NULL;
00153     Der = NULL;
00154 }
00155 
00156 void
00157 _BSP2D_ARCO::importe_wad(BSP_2D *p, WAD_LEVEL *Nivel_wad, long int pos)
00158 {
00159     Padre = p;
00160 
00161     if ( !Nivel_wad->Linedefs ) {
00162         fprintf(stderr, "ERROR FATAL: No se tienen arcos (LINEDEFS)!\n");
00163         fflush(stderr);
00164         return;
00165     }
00166 
00167     if ( pos > (Nivel_wad->Linedefs->size)/14 ) {
00168         fprintf(stderr, 
00169                 "Warning: El arco (LINEDEF) %ld esta fuera de rango!\n", pos);
00170         fflush(stderr);
00171         return;
00172     }
00173 
00174     BYTE dummy[14];
00175     WORD temp;
00176 
00177     fseek(Nivel_wad->wad_fd, Nivel_wad->Linedefs->offset + pos*14, SEEK_SET);
00178     lea_WORD_BE(&v_origen, Nivel_wad->wad_fd);
00179     lea_WORD_BE(&v_destino, Nivel_wad->wad_fd);
00180     lea_WORD_BE(&flags, Nivel_wad->wad_fd);
00181 
00182     fread(dummy, sizeof(BYTE), 2, Nivel_wad->wad_fd);
00183 
00184     lea_WORD_BE(&sector_id, Nivel_wad->wad_fd);
00185 
00186     lea_WORD_BE(&temp, Nivel_wad->wad_fd);
00187     //if ( temp != 0xFFFF ) {
00188         if ( (long int)temp > (long int)Padre->num_paredes ) {
00189             fprintf(stderr, "Warning: Referencia a pared %d fuera de rango.\n",
00190                     temp);
00191             fflush(stderr);
00192         }
00193         else {
00194             Der = &(Padre->Paredes[temp]);
00195             Der->Arco_padre = this;
00196             Der->Del_otro_lado = NULL;
00197         }
00198     //}
00199 
00200     lea_WORD_BE(&temp, Nivel_wad->wad_fd);
00201     //if ( temp != 0xFFFF ) {
00202         if ( temp > Padre->num_paredes ) {
00203             fprintf(stderr, "Warning: Referencia a pared %d fuera de rango.\n",
00204                     temp);
00205             fflush(stderr);
00206         }
00207         else {
00208             Izq = &(Padre->Paredes[temp]);
00209             Izq->Arco_padre = this;
00210             Izq->Del_otro_lado = Der;
00211             Der->Del_otro_lado = Izq;
00212         }
00213     //}
00214     //else {
00215     //    Izq = NULL;
00216     //}
00217 }
00218 
00219 #ifdef GL_ENABLED
00220 void
00221 _BSP2D_ARCO::pintar_gl_3D(void)
00225 {
00226     _BSP2D_VERTICEi v;
00227     WORD altura = 0;
00228     float r, g, b;
00229 
00230     if ( ARCO_IMPASABLE(*this) ) {
00231         r = 1;  g = 0; b = 0;
00232     }
00233     else {
00234         r = 0.5; g = 0.5; b = 0;
00235     }
00236 
00237     if ( ARCO_SECRETO(*this) ) {
00238         r /= 2; g /= 2; b /= 2;
00239     }
00240 
00241     glColor3f(r, g, b);
00242 
00243     v = Padre->Vertices[v_origen];
00244     PINTAR_VERTICE(v, altura);
00245     v = Padre->Vertices[v_destino];
00246     PINTAR_VERTICE(v, altura);
00247 }
00248 #endif
00249 
00250 //===========================================================================
00251 //= Clase _BSP2D_PARED                                                      =
00252 //===========================================================================
00253 
00254 _BSP2D_PARED::_BSP2D_PARED()
00255 {
00256     Arco_padre = NULL;
00257     Del_otro_lado = NULL;
00258 }
00259 
00260 void
00261 _BSP2D_PARED::importe_wad(BSP_2D *Padre, WAD_LEVEL *Nivel_wad, long int pos)
00262 {
00263     if ( !Nivel_wad->Sidedefs ) {
00264         fprintf(stderr, "ERROR FATAL: No se tienen paredes (SIDEDEFS)!\n");
00265         fflush(stderr);
00266         return;
00267     }
00268 
00269     if ( pos > (Nivel_wad->Sidedefs->size)/30 ) {
00270         // OJO: Este test esta fallando mucho! Revisar.
00271         fprintf(stderr, 
00272        "<_BSP2D_PARED/BSP_2D> Warning: La pared (SIDEDEF) %ld esta fuera de rango!\n",
00273         pos);
00274         fflush(stderr);
00275         return;
00276     }
00277 
00278     fseek(Nivel_wad->wad_fd, Nivel_wad->Sidedefs->offset + pos*30, SEEK_SET);
00279 
00280     lea_WORD_BE(&dx, Nivel_wad->wad_fd);
00281     lea_WORD_BE(&dy, Nivel_wad->wad_fd);
00282     fread(textura_superior, sizeof(BYTE), 8, Nivel_wad->wad_fd);
00283     fread(textura_inferior, sizeof(BYTE), 8, Nivel_wad->wad_fd);
00284     fread(textura_media, sizeof(BYTE), 8, Nivel_wad->wad_fd);
00285     textura_superior[8] = textura_inferior[8] = textura_media[8] = '\0';
00286     lea_WORD_BE(&sector_id, Nivel_wad->wad_fd);
00287 
00288     textura_superior_id = Padre->deme_textura(textura_superior);
00289     textura_media_id =    Padre->deme_textura(textura_media);
00290     textura_inferior_id = Padre->deme_textura(textura_inferior);
00291 }
00292 
00293 void
00294 _BSP2D_PARED::calcule_normal(void)
00295 {
00296     //- Precalcule datos de vertices -----------------------------------------
00297     v1 = Arco_padre->Padre->Vertices[Arco_padre->v_origen];
00298     v2 = Arco_padre->Padre->Vertices[Arco_padre->v_destino];
00299     altura1 = Arco_padre->Padre->Sectores[sector_id].altura_piso;
00300     altura2 = Arco_padre->Padre->Sectores[sector_id].altura_techo;
00301 
00302     //- Precalcule el vector normal a esta pared -----------------------------
00303     VECTOR a, b;
00304 
00305     a.x = A_METROS(v1.x); a.y = A_METROS(v1.y); a.z = A_METROS(altura1+32768);
00306     b.x = A_METROS(v2.x); b.y = A_METROS(v2.y); b.z = A_METROS(altura1+32768);
00307 
00308     n = b.producto_cruz(a);
00309     if ( n.z < 0 ) {
00310         n.x = -n.x;
00311         n.y = -n.y;
00312         n.z = -n.z;
00313     }
00314     n.normalizar();
00315 }
00316 
00317 #ifdef GL_ENABLED
00318 void
00319 _BSP2D_PARED::pintar_gl_3D(void)
00323 {
00324     WORD otra_altura1;
00325     WORD otra_altura2;
00326 
00327     if ( ARCO_IMPASABLE(*Arco_padre) ) {
00328         glBegin(PRIMITIVA_cuadros);
00329             glNormal3d(n.x, n.y, n.z);
00330             PINTAR_VERTICE(v1, altura1);
00331             PINTAR_VERTICE(v2, altura1);
00332             PINTAR_VERTICE(v2, altura2);
00333             PINTAR_VERTICE(v1, altura2);
00334         glEnd();
00335       }
00336       else if ( ARCO_DOBLE_CARA(*Arco_padre) ) {
00337         // OJO: No se verifica que haya pared del otro lado!
00338 
00339         otra_altura1 = Del_otro_lado->altura1;
00340         if ( otra_altura1 > altura1 ) {
00341             glBegin(PRIMITIVA_cuadros);
00342                 glNormal3d(n.x, n.y, n.z);
00343                 PINTAR_VERTICE(v1, altura1);
00344                 PINTAR_VERTICE(v2, altura1);
00345                 PINTAR_VERTICE(v2, otra_altura1);
00346                 PINTAR_VERTICE(v1, otra_altura1);
00347             glEnd();
00348         }
00349         otra_altura2 = Del_otro_lado->altura2;
00350         if ( otra_altura2 < altura2 ) {
00351             glBegin(PRIMITIVA_cuadros);
00352                 glNormal3d(n.x, n.y, n.z);
00353                 PINTAR_VERTICE(v1, otra_altura2);
00354                 PINTAR_VERTICE(v2, otra_altura2);
00355                 PINTAR_VERTICE(v2, altura2);
00356                 PINTAR_VERTICE(v1, altura2);
00357             glEnd();
00358         }
00359      }
00360      else {
00361         /*
00362         glDisable(GL_LIGHTING);
00363         glColor3f(1, 0, 0);
00364         glBegin(GL_LINES);
00365             glNormal3d(n.x, n.y, n.z);
00366             PINTAR_VERTICE(v1, altura1);
00367             PINTAR_VERTICE(v2, altura1);
00368             PINTAR_VERTICE(v2, altura2);
00369             PINTAR_VERTICE(v1, altura2);
00370         glEnd();
00371         glEnable(GL_LIGHTING);
00372         */
00373       }
00374     ;
00375 }
00376 #endif
00377 
00378 //===========================================================================
00379 //= Clase BSP2D_SEGMENTOi                                                   =
00380 //===========================================================================
00381 
00382 _BSP2D_SEGMENTOi::_BSP2D_SEGMENTOi()
00383 {
00384     angulo_recta = 0;
00385 }
00386 
00387 void
00388 _BSP2D_SEGMENTOi::importe_wad(BSP_2D *pp, WAD_LEVEL *Nivel_wad, long int pos)
00389 {
00390     Padre = pp;
00391 
00392     if ( !Nivel_wad->Segs ) {
00393         fprintf(stderr, "ERROR FATAL: No se tienen sub-sectores!\n");
00394         fflush(stderr);
00395         return;
00396     }
00397 
00398     if ( pos > (Nivel_wad->Segs->size)/12 ) {
00399         fprintf(stderr,
00400                 "Warning: El segmento %ld esta fuera de rango!\n", pos);
00401         fflush(stderr);
00402         return;
00403     }
00404 
00405     fseek(Nivel_wad->wad_fd, Nivel_wad->Segs->offset + pos*12, SEEK_SET);
00406 
00407     lea_WORD_BE(&v_origen, Nivel_wad->wad_fd);
00408     lea_WORD_BE(&v_destino, Nivel_wad->wad_fd);
00409     lea_WORD_BE(&angulo, Nivel_wad->wad_fd);
00410     lea_WORD_BE(&arco_i, Nivel_wad->wad_fd);
00411     lea_WORD_BE(&direccion, Nivel_wad->wad_fd);
00412     lea_WORD_BE(&offset, Nivel_wad->wad_fd);
00413 
00414     // Preprocesamiento de datos...
00415     angulo_recta = (((PI/2)/16384.0) * angulo) + DEG2RAD(180);
00416     if ( v_origen == Padre->Arcos[arco_i].v_origen ) {
00417         Pared = Padre->Arcos[arco_i].Der;
00418       }
00419       else {
00420         // OJO: Porque?
00421         Pared = Padre->Arcos[arco_i].Der;
00422     }
00423 
00424     // OJO: Esto no se sabe si funciona!
00425     // Se asume que los vertices y el angulo de este segmento ya estan
00426     // precalculados, haciendo la informacion de direccion, arco y offset
00427     // redundante (y por ende aqui no se usa) (!).
00428     /*
00429       WORD tmp;
00430       if ( direccion ) {
00431       tmp = v_origen;
00432       v_origen = v_destino;
00433       v_destino = tmp;
00434       }*/
00435 
00436     _BSP2D_PARED *p;
00437     // Determine el sector al que bordea
00438     if ( !direccion ) {
00439             // Soy el lado derecho
00440         p = Padre->Arcos[arco_i].Der;
00441     }
00442     else {
00443         // Soy un lado izquierdo
00444         p = Padre->Arcos[arco_i].Izq;
00445     }
00446     if ( !p ) {
00447         fprintf(stderr, "Warning: direccion incorrecta sobre el arco %d.\n",
00448                 arco_i);
00449         fflush(stdout);
00450         sector_id = 0;
00451         return;
00452     }
00453     sector_id = p->sector_id;
00454 }
00455 
00456 #ifdef GL_ENABLED
00457 void
00458 _BSP2D_SEGMENTOi::pintar_gl_2D(double angulo_camara)
00479 {
00480     //- 1. Algoritmo de back-face culling! ---------------------------------
00481     double fov = 85;  // OJO: Toca des-cablear esto!
00482 
00483     if ( cos(angulo_camara - angulo_recta) < -cos(DEG2RAD(fov)) ) return;
00484 
00485     //- 2. Pintado de vectores de guia (ayuda para el desarrollador!) ------
00486     _BSP2D_VERTICEi v, medio_i, medio_f;
00487 
00488 #ifdef NONONO
00489     // Verificacion de vertices (normalmente desactivado por eficiencia)
00490     if ( v_origen >= Padre->num_vertices || 
00491          v_destino >= Padre->num_vertices ) {
00492         fprintf(stderr, "ERROR: Vertices (%d, %d) fuera de rango\n", 
00493                 v_origen, v_destino);
00494         fflush(stderr);
00495         return;
00496     }
00497 #endif
00498 
00499     //glLineWidth(1.0f);
00500 
00501 #ifdef NONONO
00502     // Pintar un vector de direccion del segmento
00503     glColor3f(0, 1, 0);
00504     glBegin(GL_LINES);
00505         medio_i.x=(Padre->Vertices[v_origen].x+Padre->Vertices[v_destino].x)/2;
00506         medio_i.y=(Padre->Vertices[v_origen].y+Padre->Vertices[v_destino].y)/2;
00507         PINTAR_VERTICE(medio_i, 1);
00508 
00509         medio_f.x = medio_i.x + (int)(20.0 * sin(angulo_recta));
00510         medio_f.y = medio_i.y - (int)(20.0 * cos(angulo_recta));
00511         PINTAR_VERTICE(medio_f, 1);
00512     glEnd();
00513 #endif
00514 
00515     // Pintar la rayita de orientacion
00516     glColor3f(0, 0, 1);
00517     glBegin(GL_LINES);
00518         double a = (PI/2) * ((long int) angulo) / 16384;
00519         medio_i.x=(Padre->Vertices[v_origen].x+Padre->Vertices[v_destino].x)/2;
00520         medio_i.y=(Padre->Vertices[v_origen].y+Padre->Vertices[v_destino].y)/2;
00521         PINTAR_VERTICE(medio_i, 1);
00522 
00523         medio_f.x = medio_i.x + (int)(20.0 * sin(a));
00524         medio_f.y = medio_i.y - (int)(20.0 * cos(a));
00525         PINTAR_VERTICE(medio_f, 1);
00526     glEnd();
00527 
00528 #ifdef NONONO
00529     // Pintar el vector de orientacion de la camara
00530     if ( cos(angulo_camara - angulo_recta) > -cos(DEG2RAD(fov)) )
00531     glColor3f(0, 1, 1); else glColor3f(0, 0.3, 0.3);
00532     glBegin(GL_LINES);
00533         PINTAR_VERTICE(medio_i, 1);
00534         medio_f.x = medio_i.x + (int)(20.0 * sin(angulo_camara));
00535         medio_f.y = medio_i.y - (int)(20.0 * cos(angulo_camara));
00536         PINTAR_VERTICE(medio_f, 1);
00537     glEnd();
00538 #endif
00539 
00540     //- 3. Pintar el segmento en si -----------------------------------------
00541     glBegin(GL_LINES);
00542         glColor3f(1, 0, 0);
00543         v = Padre->Vertices[v_origen];
00544         PINTAR_VERTICE(v, 1);
00545 
00546         v = Padre->Vertices[v_destino];
00547         PINTAR_VERTICE(v, 1);
00548     glEnd();
00549 
00550     NUM_poligonos++;
00551 }
00552 
00553 void
00554 _BSP2D_SEGMENTOi::pintar_gl_3D(CALIDAD_VISUAL *Calidad, double angulo_camara)
00560 {
00561     //- 1. Algoritmo de back-face culling! ---------------------------------
00562     double fov = 60;  // OJO: Toca des-cablear esto!
00563 
00564     if ( cos(angulo_camara - angulo_recta) < -cos(DEG2RAD(fov)) ) return;
00565 
00566     //- 2. Pintar el segmento en si -----------------------------------------
00567     WORD otra_altura1;
00568     WORD otra_altura2;
00569     double u1, u2, u3, u4;
00570     double v1, v2, v3, v4;
00571     double u, v, d, du, dv;
00572     IMAGEN *Img;
00573 
00574     if ( ARCO_IMPASABLE(Padre->Arcos[arco_i]) ) {
00575         ACTIVAR_TEXTURA_PARED(Pared->textura_media_id);
00576         //-------------------------------------------------------------------
00577         Img = Padre->sprites[Pared->textura_media_id];
00578         d = DISTANCIA(A_METROS(Padre->Vertices[v_origen].x), 
00579                       A_METROS(Padre->Vertices[v_origen].y), 0,
00580                       A_METROS(Padre->Vertices[v_destino].x),
00581                       A_METROS(Padre->Vertices[v_destino].y), 0);
00582         u = d / ((double)Img->xtam()/50.0);
00583         v = (A_METROS(Pared->altura2) - A_METROS(Pared->altura1))/((double)Img->ytam()/50.0);
00584         du = ((double)Pared->dx)/128.0;
00585         dv = -((double)Pared->dy)/128.0;
00586         u1 = -(u+du);     v1 = (1-v) + dv;
00587         u2 = -du;         v2 = (1-v) + dv;
00588         u3 = -du;         v3 = 1 + dv;
00589         u4 = -(u+du);     v4 = 1 + dv;
00590         //-------------------------------------------------------------------
00591         glBegin(PRIMITIVA_cuadros);
00592             glNormal3d(Pared->n.x, Pared->n.y, Pared->n.z);
00593             glTexCoord2d(u1, v1);
00594             PINTAR_VERTICE(Padre->Vertices[v_origen], Pared->altura1);
00595             glTexCoord2d(u2, v2);
00596             PINTAR_VERTICE(Padre->Vertices[v_destino], Pared->altura1);
00597             glTexCoord2d(u3, v3);
00598             PINTAR_VERTICE(Padre->Vertices[v_destino], Pared->altura2);
00599             glTexCoord2d(u4, v4);
00600             PINTAR_VERTICE(Padre->Vertices[v_origen], Pared->altura2);
00601         glEnd();
00602         //-------------------------------------------------------------------
00603       }
00604       else if ( ARCO_DOBLE_CARA(Padre->Arcos[arco_i]) ) {
00605         // OJO: No se verifica que haya pared del otro lado!
00606         if ( !Pared->Del_otro_lado ) {
00607             fprintf(stderr, "<_BSP2D_SEGMENTOi> No hay pared del otro lado!"); 
00608             fflush(stderr);
00609         }
00610         otra_altura1 = Pared->Del_otro_lado->altura1;
00611         if ( otra_altura1 > Pared->altura1 ) {
00612             ACTIVAR_TEXTURA_PARED(Pared->textura_inferior_id);
00613             //---------------------------------------------------------------
00614             Img = Padre->sprites[Pared->textura_inferior_id];
00615             d = DISTANCIA(A_METROS(Padre->Vertices[v_origen].x), 
00616                           A_METROS(Padre->Vertices[v_origen].y), 0,
00617                           A_METROS(Padre->Vertices[v_destino].x),
00618                           A_METROS(Padre->Vertices[v_destino].y), 0);
00619             u = d / (Img->xtam()/50.0);
00620             v = (A_METROS(Pared->altura2) - A_METROS(Pared->altura1))/(Img->ytam()/25.0);
00621             du = ((double)Pared->dx)/128.0;
00622             dv = -((double)Pared->dy)/128.0;
00623             u1 = -(u+du);     v1 = (1-v) + dv;
00624             u2 = -du;         v2 = (1-v) + dv;
00625             u3 = -du;         v3 = 1 + dv;
00626             u4 = -(u+du);     v4 = 1 + dv;
00627             //---------------------------------------------------------------
00628             glBegin(PRIMITIVA_cuadros);
00629                 glNormal3d(Pared->n.x, Pared->n.y, Pared->n.z);
00630                 glTexCoord2d(u1, v1);
00631                 PINTAR_VERTICE(Padre->Vertices[v_origen], Pared->altura1);
00632                 glTexCoord2d(u2, v2);
00633                 PINTAR_VERTICE(Padre->Vertices[v_destino], Pared->altura1);
00634                 glTexCoord2d(u3, v3);
00635                 PINTAR_VERTICE(Padre->Vertices[v_destino], otra_altura1);
00636                 glTexCoord2d(u4, v4);
00637                 PINTAR_VERTICE(Padre->Vertices[v_origen], otra_altura1);
00638             glEnd();
00639             //---------------------------------------------------------------
00640         }
00641         otra_altura2 = Pared->Del_otro_lado->altura2;
00642         if ( otra_altura2 < Pared->altura2 ) {
00643             ACTIVAR_TEXTURA_PARED(Pared->textura_superior_id);
00644             //---------------------------------------------------------------
00645             Img = Padre->sprites[Pared->textura_superior_id];
00646             d = DISTANCIA(A_METROS(Padre->Vertices[v_origen].x), 
00647                           A_METROS(Padre->Vertices[v_origen].y), 0,
00648                           A_METROS(Padre->Vertices[v_destino].x),
00649                           A_METROS(Padre->Vertices[v_destino].y), 0);
00650             u = d / (Img->xtam()/50.0);
00651             v = (A_METROS(Pared->altura2) - A_METROS(Pared->altura1))/(Img->ytam()/50.0);
00652             du = ((double)Pared->dx)/128.0;
00653             dv = -((double)Pared->dy)/128.0;
00654             u1 = -(u+du);     v1 = (1-v) + dv;
00655             u2 = -du;         v2 = (1-v) + dv;
00656             u3 = -du;         v3 = 1 + dv;
00657             u4 = -(u+du);     v4 = 1 + dv;
00658             //---------------------------------------------------------------
00659             glBegin(PRIMITIVA_cuadros);
00660                 glNormal3d(Pared->n.x, Pared->n.y, Pared->n.z);
00661                 glTexCoord2d(u1, v1);
00662                 PINTAR_VERTICE(Padre->Vertices[v_origen], otra_altura2);
00663                 glTexCoord2d(u2, v2);
00664                 PINTAR_VERTICE(Padre->Vertices[v_destino], otra_altura2);
00665                 glTexCoord2d(u3, v3);
00666                 PINTAR_VERTICE(Padre->Vertices[v_destino], Pared->altura2);
00667                 glTexCoord2d(u4, v4);
00668                 PINTAR_VERTICE(Padre->Vertices[v_origen], Pared->altura2);
00669             glEnd();
00670             //---------------------------------------------------------------
00671         }
00672       }
00673     ;
00674 
00675     // Como yo me veo, mi piso y mi techo deben verse
00676     Padre->Sectores[sector_id].marcado = TRUE;
00677 
00678     NUM_poligonos++;
00679 }
00680 #endif // GL_ENABLED
00681 
00682 void
00683 _BSP2D_SEGMENTOi::anexe_vertices(LISTA <_BSP2D_VERTICEi *> *Vertices)
00688 {
00689     Vertices->anx(&Padre->Vertices[v_origen]);
00690     Vertices->anx(&Padre->Vertices[v_destino]);
00691 }
00692 
00693 //===========================================================================
00694 //= Clase _BSP2D_SECTOR                                                     =
00695 //===========================================================================
00696 
00697 int
00698 triangularice_cara(int answer[][3], double *Vertices, int nvertices, 
00699                    int *contour_sizes, int ncontours)
00703 {
00704     int num_vertices, nmonpoly;
00705 
00706         /* Prepare segments */
00707     num_vertices = 
00708         prepare_segments(Vertices, nvertices, contour_sizes, ncontours);
00709 
00710         /* Do the trick */
00711     initialise(num_vertices);
00712     construct_trapezoids(num_vertices);
00713     nmonpoly = monotonate_trapezoids(num_vertices);
00714     return triangulate_monotone_polygons(num_vertices, nmonpoly, answer);
00715 }
00716 
00717 void
00718 _BSP2D_SECTOR::triangularize(void)
00739 {
00740     long int i, j;
00741     LISTA <_BSP2D_ARCO *> arcos;
00742     LISTA <_BSP2D_CONTORNOi *> cOntornos;
00743     _BSP2D_CONTORNOi *Contorno;
00744     _BSP2D_ARCO *Arco;
00745     WORD v_i, v_tmp;
00746 
00747     //- Seleccione los arcos que son de este sector -------------------------
00748     for ( i = 0, j = 0; i < Padre->num_paredes; i++ ) {
00749         if ( Padre->Paredes[i].sector_id == pos ) {
00750             Arco = new _BSP2D_ARCO(); // OJO: Porque?
00751             (*Arco) = (*Padre->Paredes[i].Arco_padre);
00752             arcos.anx(Arco);
00753             if ( Arco->Der == &(Padre->Paredes[i]) ) {
00754                 v_tmp = Arco->v_origen;
00755                 Arco->v_origen = Arco->v_destino;
00756                 Arco->v_destino = v_tmp;
00757             }
00758             j++;
00759         }
00760     }
00761 
00762     //- Arme contornos ------------------------------------------------------
00763     while ( arcos.tam() > 0 ) {
00764         Contorno = new _BSP2D_CONTORNOi;
00765         Contorno->arcos.anx(arcos[0]);
00766         arcos.elimElem(0);
00767 
00768         for ( v_i = Contorno->arcos[0]->v_destino; TRUE;
00769               v_i = Contorno->arcos[Contorno->arcos.tam()-1]->v_destino ) {
00770             for ( i = 0; i < (long int)arcos.tam(); i++ ) {
00771                 if ( arcos[i]->v_origen == v_i ) {
00772                     Contorno->arcos.anx(arcos[i]);
00773                     arcos.elimElem(i);
00774                     i = 0; break;
00775                 }
00776             }
00777             if ( i >= (long int)arcos.tam() ) {
00778                 break;
00779             }
00780         }
00781         if ( Contorno->arcos[0]->v_origen != 
00782              Contorno->arcos[Contorno->arcos.tam()-1]->v_destino ||
00783              Contorno->arcos.tam() < 3 ) {
00784                 // Arcos extrannos encontrados comunmente en la estructura de
00785                 // niveles WAD de IdSoftware que no definen sectores.
00786             delete Contorno;
00787         }
00788         else {
00789             cOntornos.anx(Contorno);
00790         }
00791     }
00792 
00793     //- Valide los contornos -----------------------------------------------
00794     //- OJO: Este segmento es un machete.  Parece que en los niveles de DOOM
00795     //- hay algunas irregularidades, como pares de arcos que parten en dos a
00796     //- el borde de su sector (y dannando contornos).
00797     for ( i = 0; i < (long int)cOntornos.tam(); i++ ) {
00798         Contorno = cOntornos[i];
00799 
00800         // Quite lineas contiguas que se sobre-rayan la una a la otra
00801         for ( j = 0; j < (long int)Contorno->arcos.tam() - 1; j++ ) {
00802             if (Contorno->arcos[j]->v_origen==Contorno->arcos[j+1]->v_destino
00803                  &&
00804                 Contorno->arcos[j+1]->v_origen==Contorno->arcos[j]->v_destino){
00805                 Contorno->arcos.elimElem(j);
00806                 Contorno->arcos.elimElem(j);
00807                 j--;
00808             }
00809         }
00810         //
00811     }
00812 
00813     // Elimine contornos nulos
00814     for ( i = 0; i < (long int)cOntornos.tam(); i++ ) {
00815         if ( cOntornos[i]->arcos.tam() <= 0 ) {
00816             cOntornos.elimElem(i);
00817             i--;
00818         }
00819     }
00820     if ( cOntornos.tam() <= 0 ) {
00821         return;
00822     }
00823 
00824     //- Triangularice esta cara! -------------------------------------------
00825     int nvertices, *contour_sizes;
00826     long int ncontours; /* Conversion a polygon */
00827     long int ntriangles;
00828     double *Vertices;
00829     int op[500][3], vertice_actual;
00830     _BSP2D_VERTICEi vert;
00831 
00832     ncontours = cOntornos.tam();
00833     contour_sizes = new int[ncontours];
00834     for ( i = 0; i < ncontours; i++ ) {
00835         contour_sizes[i] = cOntornos[i]->arcos.tam();
00836     }
00837 
00838     nvertices = 0;
00839     for ( i = 0; i < (long int)cOntornos.tam(); i++ ) {
00840         for ( j = 0; j < (long int)cOntornos[i]->arcos.tam(); j++ ) {
00841             nvertices++;
00842         }
00843     }
00844     Vertices = new double[2*nvertices];
00845     for ( i = 0, vertice_actual = 0; i < (long int)cOntornos.tam(); i++ ) {
00846         for ( j = 0; j < (long int)cOntornos[i]->arcos.tam();
00847               j++, vertice_actual++ ) {
00848             vert = Padre->Vertices[cOntornos[i]->arcos[j]->v_origen];
00849             Vertices[2*vertice_actual] = A_METROS(vert.x);
00850             Vertices[2*vertice_actual+1] = A_METROS(vert.y);
00851         }
00852     }
00853 
00854         //
00855         /*printf("There are %d vertices in %d contours!\n", nvertices, ncontours);
00856           printf("The contours sizes are:\n    ");
00857           for ( i = 0; i < ncontours; i++ ) {
00858           printf("%d ", contour_sizes[i]);
00859           }
00860           printf("\n");
00861           printf("The vertices are:\n");
00862           for ( i = 0; i < nvertices; i++ ) {
00863           printf("  - (%.2f, %.2f)\n", Vertices[2*i], Vertices[2*i+1]);
00864           }
00865           fflush(stdout);*/
00866 
00867     //
00868     ntriangles = triangularice_cara(op, 
00869                                     Vertices, nvertices, contour_sizes, ncontours);
00870     //
00871     /*for ( i = 0; i < ntriangles; i++ ) {
00872       printf("triangle #%d: %d %d %d\n", i, op[i][0], op[i][1], op[i][2]);
00873       }*/
00874     //
00875 
00876     //- Deje armaditos los triangulos ----------------------------------------
00877     num_triangulos = ntriangles;
00878     Triangulos = new double[6*num_triangulos];
00879 
00880     for ( i = 0; i < ntriangles; i++ ) {
00881         Triangulos[6*i]   = Vertices[2*(op[i][0]-1)];
00882         Triangulos[6*i+1] = Vertices[2*(op[i][0]-1)+1];
00883         Triangulos[6*i+2] = Vertices[2*(op[i][1]-1)];
00884         Triangulos[6*i+3] = Vertices[2*(op[i][1]-1)+1];
00885         Triangulos[6*i+4] = Vertices[2*(op[i][2]-1)];
00886         Triangulos[6*i+5] = Vertices[2*(op[i][2]-1)+1];
00887     }
00888     // Calcule min-max (que sera usado por el metodo altura)
00889     min_x = min_y = FLT_MAX;  max_x = max_y = FLT_MIN;
00890     for ( i = 0; i < 3*ntriangles; i++ ) {
00891         if ( Triangulos[2*i] > max_x ) max_x = Triangulos[2*i];
00892         if ( Triangulos[2*i] < min_x ) min_x = Triangulos[2*i];
00893         if ( Triangulos[2*i+1] > max_y ) max_y = Triangulos[2*i+1];
00894         if ( Triangulos[2*i+1] < min_y ) min_y = Triangulos[2*i+1];
00895     }
00896 
00897     //- Elimine las estructuras de datos temporales ------------------------
00898     delete Vertices;    delete contour_sizes;
00899     for ( i = 0; i < (long int)cOntornos.tam(); i++ ) delete cOntornos[i];
00900     for ( i = 0; i < (long int)arcos.tam(); i++ ) delete arcos[i];
00901 }
00902 
00903 BOOLEAN
00904 _BSP2D_SECTOR::altura(double x, double y, double *Altura)
00905 {
00906     if ( x < min_x || x > max_x || y < min_y || y > max_y ) {
00907         return FALSE;
00908     }
00909 
00910     long int i;
00911     VECTOR p, p1, p2, p3, u, v, w, a, b, c;
00912     p.x = x, p.y = y;
00913     p1.z = p2.z = p3.z = p.z = 0;
00914     for ( i = 0; i < num_triangulos; i++ ) {
00915         p1.x = Triangulos[6*i];  p1.y = Triangulos[6*i+1];
00916         p2.x = Triangulos[6*i+2];  p2.y = Triangulos[6*i+3];
00917         p3.x = Triangulos[6*i+4];  p3.y = Triangulos[6*i+5];
00918         u = p2 - p1; v = p3 - p2; w = p1 - p3;
00919         a = p - p1;  b = p - p2; c = p - p3;
00920         if ( (u.producto_cruz(a)).z > 0 && 
00921              (v.producto_cruz(b)).z > 0 &&
00922              (w.producto_cruz(c)).z > 0 ) {
00923             (*Altura) = A_METROS(32768 + altura_piso);
00924             return TRUE;
00925         }
00926     }
00927     return FALSE;
00928 }
00929 
00930 
00931 _BSP2D_SECTOR::_BSP2D_SECTOR()
00932 {
00933     marcado = FALSE;
00934     con_paredes = FALSE;
00935 }
00936 
00937 void
00938 _BSP2D_SECTOR::importe_wad(BSP_2D *pp, WAD_LEVEL *Nivel_wad, long int p)
00939 {
00940     Padre = pp;
00941 
00942     if ( !Nivel_wad->Sectors ) {
00943         fprintf(stderr, "ERROR FATAL: No se tienen paredes (SIDEDEFS)!\n");
00944         fflush(stderr);
00945         return;
00946     }
00947 
00948     if ( pos > (Nivel_wad->Sectors->size)/26 ) {
00949         fprintf(stderr, 
00950                 "Warning: La pared (SIDEDEF) %ld esta fuera de rango!\n", pos);
00951         fflush(stderr);
00952         return;
00953     }
00954 
00955     pos = p;
00956     fseek(Nivel_wad->wad_fd, Nivel_wad->Sectors->offset + pos*26, SEEK_SET);
00957 
00958     lea_WORD_BE(&altura_piso, Nivel_wad->wad_fd);
00959     lea_WORD_BE(&altura_techo, Nivel_wad->wad_fd);
00960     fread(textura_piso, sizeof(BYTE), 8, Nivel_wad->wad_fd);
00961     fread(textura_techo, sizeof(BYTE), 8, Nivel_wad->wad_fd);
00962     textura_piso[8] = textura_techo[8] = '\0';
00963     lea_WORD_BE(&id, Nivel_wad->wad_fd);
00964 
00965     // - 
00966     textura_piso_id = Padre->deme_flat(textura_piso);
00967     textura_techo_id = Padre->deme_flat(textura_techo);
00968 }
00969 
00970 #ifdef GL_ENABLED
00971 void
00972 _BSP2D_SECTOR::pintar_gl_3D(CALIDAD_VISUAL *Calidad)
00982 {
00983     long int i;
00984     double a;
00985 
00986     // Factor de escalamiento del espacio [u, v] (pixels) al espacio [i, j, k]
00987     double FT = 1.2; // Ojo: Deberia ser 1.4
00988     // Incrementos de la coodenada de la textura en el espacio [u,v]
00989     double IU = 0;   // OJO: Deberian ser 0, 0
00990     double IV = -0.3;
00991 
00992     if ( !marcado ) return;
00993 
00994     //- Pintar el piso ------------------------------------------------------
00995     if ( Calidad->con_textura && Calidad->con_caras ) {
00996         Padre->flats[textura_piso_id]->activar_gl();
00997     }
00998 
00999     glNormal3d(0, 0, 1);
01000     glBegin(PRIMITIVA_triangulos);
01001     a = ESCALA_ALTURA*A_METROS(altura_piso + 32768);
01002     for ( i = 0; i < num_triangulos; i++ ) {
01003         glTexCoord2d(Triangulos[6*i]/FT + IU,    Triangulos[6*i+1]/FT + IV);
01004         glVertex3d(  Triangulos[6*i],            Triangulos[6*i+1], a     );
01005         glTexCoord2d(Triangulos[6*i+2]/FT + IU,  Triangulos[6*i+3]/FT + IV);
01006         glVertex3d(  Triangulos[6*i+2],          Triangulos[6*i+3], a     );
01007         glTexCoord2d(Triangulos[6*i+4]/FT + IU,  Triangulos[6*i+5]/FT + IV);
01008         glVertex3d(  Triangulos[6*i+4],          Triangulos[6*i+5], a     );
01009     }
01010     glEnd();
01011 
01012     //- Pintar el techo -----------------------------------------------------
01013     if ( Calidad->con_textura && Calidad->con_caras ) {
01014         Padre->flats[textura_techo_id]->activar_gl();
01015     }
01016 
01017     glNormal3d(0, 0, 1);
01018     glBegin(PRIMITIVA_triangulos);
01019     a = ESCALA_ALTURA*A_METROS(altura_techo + 32768);
01020     for ( i = 0; i < num_triangulos; i++ ) {
01021         glTexCoord2d(Triangulos[6*i]/FT + IU,   Triangulos[6*i+1]/FT + IV);
01022         glVertex3d(  Triangulos[6*i],           Triangulos[6*i+1], a     );
01023         glTexCoord2d(Triangulos[6*i+4]/FT + IU, Triangulos[6*i+5]/FT + IV);
01024         glVertex3d(  Triangulos[6*i+4],         Triangulos[6*i+5], a     );
01025         glTexCoord2d(Triangulos[6*i+2]/FT + IU, Triangulos[6*i+3]/FT + IV);
01026         glVertex3d(  Triangulos[6*i+2],         Triangulos[6*i+3], a     );
01027     }
01028     glEnd();
01029 
01030 
01031     //- Pintar las paredes (usando arcos) -----------------------------------
01032     if ( con_paredes ) {
01033         // Solo ocurre si no estamos en modo BSP
01034         // OJO: Deberian recorrerse los segmentos para que las paredes
01035         //      salgan con texturas!
01036         for ( i = 0; i < Padre->num_paredes; i++ ) {
01037             if ( Padre->Paredes[i].sector_id == pos ) {
01038                 Padre->Paredes[i].pintar_gl_3D();
01039             }
01040         }
01041     }
01042     marcado = FALSE;
01043 }
01044 #endif // GL_ENABLED
01045 
01046 //=*************************************************************************=
01047 //= SEGUNDA SECCION: PARTICION BINARIA DEL ESPACIO                          =
01048 //=-------------------------------------------------------------------------=
01049 //= Aqui se encuentran, en este orden, las siguientes clases:               =
01050 //=   - _BSP2D_ELEMENTO                                                      =
01051 //=   - _BSP2D_HOJA                                                          =
01052 //=   - _BSP2D_NODO                                                          =
01053 //=*************************************************************************=
01054 
01055 //===========================================================================
01056 //= Clase _BSP2D_ELEMENTO                                                    =
01057 //===========================================================================
01058 
01059 _BSP2D_ELEMENTO::_BSP2D_ELEMENTO()
01060 {
01061     mi_tipo = '\0';
01062 }
01063 
01064 _BSP2D_ELEMENTO::~_BSP2D_ELEMENTO()
01065 {
01066     ;
01067 }
01068 
01069 void
01070 _BSP2D_ELEMENTO::init(BSP_2D *p)
01071 {
01072     Padre = p;
01073 }
01074 
01075 //===========================================================================
01076 //= Clase _BSP2D_HOJA                                                        =
01077 //===========================================================================
01078 
01079 _BSP2D_HOJA::_BSP2D_HOJA()
01080 {
01081     mi_tipo = 'h';
01082 }
01083 
01084 _BSP2D_HOJA::~_BSP2D_HOJA()
01085 {
01086     elim();
01087 }
01088 
01089 void
01090 _BSP2D_HOJA::elim(void)
01091 {
01092 
01093 }
01094 
01095 void
01096 _BSP2D_HOJA::mover(_BSP2D_VERTICEi /*delta*/)
01097 {
01098     ;
01099 }
01100 
01101 void
01102 _BSP2D_HOJA::importe_wad(WAD_LEVEL *Nivel_wad, long int pos)
01106 {
01107     if ( !Nivel_wad->Ssectors ) {
01108         fprintf(stderr, "ERROR FATAL: No se tienen sub-sectores!\n");
01109         fflush(stderr);
01110         return;
01111     }
01112 
01113     if ( pos > (Nivel_wad->Ssectors->size)/4 ) {
01114         fprintf(stderr, 
01115                 "Warning: El subsector %ld esta fuera de rango!\n", pos);
01116         fflush(stderr);
01117         return;
01118     }
01119 
01120     fseek(Nivel_wad->wad_fd, Nivel_wad->Ssectors->offset + pos*4, SEEK_SET);
01121 
01122     lea_WORD_BE(&num_segmentos, Nivel_wad->wad_fd);
01123     lea_WORD_BE(&primer_segmento, Nivel_wad->wad_fd);
01124 }
01125 
01126 #ifdef GL_ENABLED
01127 void
01128 _BSP2D_HOJA::pintar_gl_2D(
01129     VECTOR /*posicion_camara*/,
01130     VECTOR orientacion_camara, CALIDAD_VISUAL * /*Calidad*/)
01131 {
01132     WORD i;
01133 
01134     orientacion_camara.normalizar();
01135 
01136     double cam;
01137     if ( orientacion_camara.y < 0 ) cam=asin(orientacion_camara.x);
01138     else cam = DEG2RAD(180)-asin(orientacion_camara.x);
01139 
01140     for ( i = primer_segmento; 
01141           i < primer_segmento + num_segmentos && 
01142               i < (WORD)Padre->num_segmentos; i++ ) {
01143         Padre->Segmentos[i].pintar_gl_2D(cam);
01144     }
01145 }
01146 
01147 void
01148 _BSP2D_HOJA::pintar_gl_3D(
01149     VECTOR /*posicion_camara*/,
01150     VECTOR orientacion_camara, CALIDAD_VISUAL *Calidad)
01151 {
01152     WORD i;
01153 
01154     orientacion_camara.normalizar();
01155 
01156     double cam;
01157     if ( orientacion_camara.y < 0 ) cam=asin(orientacion_camara.x);
01158     else cam = DEG2RAD(180)-asin(orientacion_camara.x);
01159 
01160     for ( i = primer_segmento; 
01161           i < primer_segmento + num_segmentos && 
01162               i < (WORD)Padre->num_segmentos; i++ ) {
01163         Padre->Segmentos[i].pintar_gl_3D(Calidad, cam);
01164     }
01165 }
01166 #endif // GL_ENABLED
01167 
01168 double
01169 _BSP2D_HOJA::altura_cuadro(WORD /*x*/, WORD /*y*/)
01174 {
01175     WORD id = Padre->Segmentos[primer_segmento].sector_id;
01176 
01177     return A_METROS(Padre->Sectores[id].altura_piso+32768);
01178 }
01179 
01180 //===========================================================================
01181 //= Clase _BSP2D_NODO                                                        =
01182 //===========================================================================
01183 
01184 _BSP2D_NODO::_BSP2D_NODO()
01185 {
01186     mi_tipo = 'n';
01187 
01188     min_izq.x = 400;     min_izq.y = 1600;
01189     max_izq.x = 900;     max_izq.y = 4000;
01190     min_der.x = 1000;     min_der.y = 1600;
01191     max_der.x = 3000;     max_der.y = 4000;
01192 
01193     linea_x = linea_y = 1000;
01194     linea_dx = linea_dy = 500;
01195 }
01196 
01197 _BSP2D_NODO::~_BSP2D_NODO()
01198 {
01199     elim();
01200 }
01201 
01202 void
01203 _BSP2D_NODO::elim(void)
01204 {
01205     Izq->elim();
01206     Der->elim();
01207 }
01208 
01209 void
01210 _BSP2D_NODO::mover(_BSP2D_VERTICEi delta)
01211 {
01212     min_izq.x += delta.x;     min_izq.y += delta.y;
01213     max_izq.x += delta.x;     max_izq.y += delta.y;
01214 
01215     min_der.x += delta.x;     min_der.y += delta.y;
01216     max_der.x += delta.x;     max_der.y += delta.y;
01217 
01218     linea_x += delta.x;       linea_y += delta.y;
01219 
01220     Izq->mover(delta);  Der->mover(delta);
01221 }
01222 
01223 void
01224 _BSP2D_NODO::importe_wad(WAD_LEVEL *Nivel_wad, long int pos)
01225 {
01226     if ( !Nivel_wad->Nodes) {
01227         fprintf(stderr, "ERROR FATAL: No se tiene una estructura BSP!\n");
01228         fflush(stderr);
01229         return;
01230     }
01231 
01232     if ( pos > (Nivel_wad->Nodes->size)/28 ) {
01233         fprintf(stderr, "Warning: El nodo %ld esta fuera de rango!\n", pos);
01234         fflush(stderr);
01235         return;
01236     }
01237 
01238     fseek(Nivel_wad->wad_fd, Nivel_wad->Nodes->offset + pos*28, SEEK_SET);
01239 
01240     WORD temp;
01241 
01242     lea_WORD_BE(&linea_x, Nivel_wad->wad_fd);
01243     CORREGIR(linea_x);
01244     lea_WORD_BE(&linea_y, Nivel_wad->wad_fd);
01245     CORREGIR(linea_y);
01246 
01247     lea_WORD_BE(&linea_dx, Nivel_wad->wad_fd);
01248     lea_WORD_BE(&linea_dy, Nivel_wad->wad_fd);
01249     if ( linea_dx > 32768 ) linea_dx -= 65536;  // OJO: Machete horroroso!
01250     if ( linea_dy > 32768 ) linea_dy -= 65536;
01251 
01252     lea_WORD_BE(&max_der.y, Nivel_wad->wad_fd);
01253     CORREGIR(max_der.y);
01254     lea_WORD_BE(&min_der.y, Nivel_wad->wad_fd);
01255     CORREGIR(min_der.y);
01256     lea_WORD_BE(&min_der.x, Nivel_wad->wad_fd);
01257     CORREGIR(min_der.x);
01258     lea_WORD_BE(&max_der.x, Nivel_wad->wad_fd);
01259     CORREGIR(max_der.x);
01260 
01261     lea_WORD_BE(&max_izq.y, Nivel_wad->wad_fd);
01262     CORREGIR(max_izq.y);
01263     lea_WORD_BE(&min_izq.y, Nivel_wad->wad_fd);
01264     CORREGIR(min_izq.y);
01265     lea_WORD_BE(&min_izq.x, Nivel_wad->wad_fd);
01266     CORREGIR(min_izq.x);
01267     lea_WORD_BE(&max_izq.x, Nivel_wad->wad_fd);
01268     CORREGIR(max_izq.x);
01269 
01270     // OJO: Aqui se hace un alegre acto de fe y no se verifican limites en los
01271     // indices de hojas y/o nodos.
01272     lea_WORD_BE(&temp, Nivel_wad->wad_fd);
01273     if ( !(temp & BIT_15) ) {
01274         temp = (WORD)(temp & ~(BIT_15));
01275         Der = &(Padre->Nodos[temp]);
01276     }
01277     else {
01278         temp = (WORD)(temp & ~(BIT_15));
01279         Der = &(Padre->Hojas[temp]);
01280     }
01281 
01282     lea_WORD_BE(&temp, Nivel_wad->wad_fd);
01283     if ( !(temp & BIT_15) ) {
01284         temp = (WORD)(temp & ~(BIT_15));
01285         Izq = &(Padre->Nodos[temp]);
01286     }
01287     else {
01288         temp = (WORD)(temp & ~(BIT_15));
01289         Izq = &(Padre->Hojas[temp]);
01290     }
01291     fflush(stdout);
01292 }
01293 
01294 /*---------------------------------------------------------------------------
01295 OJO: Esta macro debe ser vista como si se tratase de un metodo de la clase
01296      _BSP2D_NODO.  Implementa un servicio privado para los metodos de
01297      visualizacion del _BSP2D_NODO.
01298 */
01299 #define PINTADO_NODO(metodo)                                                 \
01300     posicion_camara.z = 0;                                                   \
01301     orientacion_camara.z = 0;        /* OJO: Machete.                     */ \
01302     orientacion_camara.normalizar(); /* OJO: Esto asume que el vector esta*/ \
01303                                      /*      en el plano z = 0            */ \
01304                                                                              \
01305     VECTOR orientacion_cortante(linea_dx, linea_dy, 0);                      \
01306     VECTOR posicion_cortante(A_METROS(linea_x), A_METROS(linea_y), 0);       \
01307     VECTOR orientacion_camara_i;                                             \
01308     VECTOR orientacion_camara_d;                                             \
01309     orientacion_cortante.normalizar();                                       \
01310                                                                              \
01311     VECTOR normal;                                                           \
01312     MATRIZ_4x4 R;                                                            \
01313     double criterio;                                                         \
01314                                                                              \
01315     R.rotacion_eje(DEG2RAD(-30), 0, 0, 1);                                   \
01316     orientacion_camara_d = R*orientacion_camara;                             \
01317     R.rotacion_eje(DEG2RAD(30), 0, 0, 1);                                    \
01318     orientacion_camara_i = R*orientacion_camara;                             \
01319                                                                              \
01320     if (                                                                     \
01321         se_intersectan(posicion_camara, orientacion_camara_i,                \
01322                        posicion_cortante, orientacion_cortante) ||           \
01323         se_intersectan(posicion_camara, orientacion_camara_d,                \
01324                        posicion_cortante, orientacion_cortante)              \
01325        ) {                                                                   \
01326         /*- Caso recursivo -----------------------------------------------*/ \
01327         if ( Der ) {                                                         \
01328             Der->metodo(posicion_camara, orientacion_camara, Calidad);       \
01329         }                                                                    \
01330         if ( Izq ) {                                                         \
01331             Izq->metodo(posicion_camara, orientacion_camara, Calidad);       \
01332         }                                                                    \
01333       }                                                                      \
01334       else {                                                                 \
01335         /*- Caso recursivo -----------------------------------------------*/ \
01336         R.rotacion_eje(DEG2RAD(90), 0, 0, 1);                                \
01337         normal = R*orientacion_cortante;                                     \
01338         criterio = normal.producto_punto(posicion_camara-posicion_cortante); \
01339                                                                              \
01340         if ( criterio < 0 && Der ) {                                         \
01341             Der->metodo(posicion_camara, orientacion_camara, Calidad);       \
01342         }                                                                    \
01343         if ( criterio > 0 && Izq ) {                                         \
01344             Izq->metodo(posicion_camara, orientacion_camara, Calidad);       \
01345         }                                                                    \
01346     }
01347 
01348 #ifdef GL_ENABLED
01349 void
01350 _BSP2D_NODO::pintar_gl_2D(
01351     VECTOR posicion_camara, VECTOR orientacion_camara, CALIDAD_VISUAL *Calidad)
01354 {
01355     //----------------------------------------------------------------------
01356     PINTADO_NODO(pintar_gl_2D);
01357 
01358     //- Caso trivial -------------------------------------------------------
01359 #ifdef NONONO
01360     _BSP2D_VERTICEi v;
01361 
01362     // Minmax del hijo izquierdo
01363     if ( Izq && Izq->mi_tipo == 'n' ) {
01364         //glLineWidth(0.5f);
01365         glColor3f(0.7, 0, 0.7);
01366 
01367         glBegin(GL_LINE_LOOP);
01368         v.x = min_izq.x; v.y = min_izq.y;    PINTAR_VERTICE(v, 0);
01369         v.x = min_izq.x; v.y = max_izq.y;    PINTAR_VERTICE(v, 0);
01370         v.x = max_izq.x; v.y = max_izq.y;    PINTAR_VERTICE(v, 0);
01371         v.x = max_izq.x; v.y = min_izq.y;    PINTAR_VERTICE(v, 0);
01372         glEnd();
01373     }
01374 
01375     // Minmax del hijo derecho
01376     if ( Der && Der->mi_tipo == 'n' ) {
01377         //glLineWidth(0.5f);
01378         glColor3f(0, 0.7, 0.7);
01379         glBegin(GL_LINE_LOOP);
01380         v.x = min_der.x; v.y = min_der.y;    PINTAR_VERTICE(v, 0);
01381         v.x = min_der.x; v.y = max_der.y;    PINTAR_VERTICE(v, 0);
01382         v.x = max_der.x; v.y = max_der.y;    PINTAR_VERTICE(v, 0);
01383         v.x = max_der.x; v.y = min_der.y;    PINTAR_VERTICE(v, 0);
01384         glEnd();
01385     }
01386 
01387     // Recta de particion
01388     glShadeModel(GL_SMOOTH);
01389     //glLineWidth(2.0f);
01390     glBegin(GL_LINES);
01391         glColor3f(0, 1, 0);     v.x = linea_x;          v.y = linea_y;
01392         PINTAR_VERTICE(v, 0.05);
01393 
01394         glColor3f(0, 0.5, 0); v.x = linea_x+linea_dx; v.y = linea_y+linea_dy;
01395         PINTAR_VERTICE(v, 0.05);
01396     glEnd();
01397 #endif
01398 }
01399 
01400 void
01401 _BSP2D_NODO::pintar_gl_3D(
01402     VECTOR posicion_camara, VECTOR orientacion_camara, CALIDAD_VISUAL *Calidad)
01405 {
01406     //----------------------------------------------------------------------
01407     PINTADO_NODO(pintar_gl_3D);
01408 }
01409 #endif // GL_ENABLED
01410 
01411 double
01412 _BSP2D_NODO::altura_cuadro(WORD xx, WORD yy)
01418 {
01419     int x = xx, y = yy;
01420 
01421     // Caso recursivo
01422     if ( x>=min_izq.x && x<=max_izq.x && y>=min_izq.y && y<=max_izq.y ) {
01423         return Izq->altura_cuadro(x, y);
01424     }
01425 
01426     if ( x>=min_der.x && x<=max_der.x && y>=min_der.y && y<=max_der.y ) {
01427         return Der->altura_cuadro(x, y);
01428     }
01429 
01430     // Caso trivial: verificacion fallida de min-max (Notese otro final de la
01431     // recursion es una llamada al metodo HOJA::altura_cuadro)
01432 
01433     return 0;
01434 }
01435 
01436 //=*************************************************************************=
01437 //= TERCARA SECCION: ENCAPSULAMIENTO DEL MODELO Y PRESTACION DE SERVICIOS   =
01438 //=*************************************************************************=
01439 
01440 //===========================================================================
01441 //= Clase BSP_2D                                                            =
01442 //=-------------------------------------------------------------------------=
01443 //= Esta seccion esta divida en tres trozos:                                =
01444 //=   - Servicios basicos                                                   =
01445 //=   - Servicios de persistencia (metodo `importe_wadlevel`)               =
01446 //=   - Servicios de visualizacion (metodos `pintar*` y sus subrutinas)     =
01447 //===========================================================================
01448 
01449 //= SERVICIOS BASICOS DE LA CLASE BSP_2D ====================================
01450 
01451 BSP_2D::BSP_2D()
01452 {
01453     //- Inicializaciones varias --------------------------------------------
01454     min.x = min.y = INT_MAX;
01455     max.x = max.y = INT_MIN;
01456     datos_wad = NULL;
01457 
01458     //- Estructura geometrica BREP nula ------------------------------------
01459     Vertices = NULL;    num_vertices = 0;
01460     Arcos = NULL;       num_arcos = 0;
01461     Segmentos = NULL;   num_segmentos = 0;
01462     Paredes = NULL;     num_paredes = 0;
01463     Sectores = NULL;    num_sectores = 0;
01464 
01465     //- Arbol de particion nulo --------------------------------------------
01466     Nodos = NULL;       num_nodos = 0;
01467     Hojas = NULL;       num_hojas = 0;
01468     Raiz = NULL;
01469 }
01470 
01471 BSP_2D::~BSP_2D()
01472 {
01473     ;
01474 }
01475 
01476 void
01477 BSP_2D::mover(_BSP2D_VERTICEi delta)
01478 {
01479     long int i;
01480 
01481     min.x = min.y = INT_MAX;    max.x = max.y = INT_MIN;
01482     for ( i = 0; i < num_vertices; i++ ) {
01483         Vertices[i].x += delta.x;
01484         Vertices[i].y += delta.y;
01485 
01486         if ( Vertices[i].x > max.x ) max.x = Vertices[i].x;
01487         if ( Vertices[i].y > max.y ) max.y = Vertices[i].y;
01488         if ( Vertices[i].x < min.x ) min.x = Vertices[i].x;
01489         if ( Vertices[i].y < min.y ) min.y = Vertices[i].y;
01490     }
01491 
01492     //Raiz->mover(delta);
01493 }
01494 
01495 double
01496 BSP_2D::altura(double x, double y)
01501 {
01502     //WORD i = A_RECUADROS(x), j = A_RECUADROS(y);
01503     //return Raiz->altura_cuadro(i, j);
01504 
01505     long int i;
01506     double altura;
01507     for ( i = 0; i < num_sectores; i++ ) {
01508         if ( Sectores[i].altura(x, y, &altura) ) return altura;
01509     }
01510     return 0;
01511 }
01512 
01513 void
01514 BSP_2D::anexar_textura(IMAGEN * /*img*/)
01515 {
01516     fprintf(stderr, "<BSP_2D> OJO: `anexar_textura` no implementado!\n");
01517     fflush(stderr);
01518 }
01519 
01520 int
01521 BSP_2D::clasificar_punto(VECTOR /*p*/)
01522 {
01523     fprintf(stderr, "<BSP_2D> OJO: `clasificar_punto` no implementado!\n");
01524     fflush(stderr);
01525 
01526     return 0;
01527 }
01528 
01529 GEOMETRIA *
01530 BSP_2D::crear_copia(void)
01531 {
01532     fprintf(stderr, "<BSP_2D> OJO: `crear_copia` no implementado!\n");
01533     fflush(stderr);
01534     return NULL;
01535 }
01536 
01537 //= SERVICIOS DE PERSISTENCIA DE LA CLASE BSP_2D ============================
01538 
01539 BOOLEAN
01540 BSP_2D::importe_wadlevel(WAD_DATABASE *w, int id_nivel)
01549 {
01550     WAD_LEVEL *Nivel_wad = w->niveles[id_nivel];
01551     unsigned long i;
01552     char cad[1000];
01553 
01554     datos_wad = w;
01555 
01556     //- Importe vertices ------------------------------------------------------
01557     CHEQUEO_WAD(Nivel_wad->Vertexes, "No hay vertices en el nivel WAD!");
01558 
01559     Vertices = new _BSP2D_VERTICEi[Nivel_wad->Vertexes->size / 4];
01560     sprintf(cad, "No se pueden crear %ld vertices.",
01561         Nivel_wad->Vertexes->size/4);
01562     CHEQUEO_WAD(Vertices, cad);
01563 
01564     num_vertices = Nivel_wad->Vertexes->size / 4;
01565     fseek(Nivel_wad->wad_fd, Nivel_wad->Vertexes->offset, SEEK_SET);
01566 
01567     for ( i = 0; i < (unsigned long)num_vertices; i++ ) {
01568         lea_WORD_BE(&Vertices[i].x, Nivel_wad->wad_fd);
01569         lea_WORD_BE(&Vertices[i].y, Nivel_wad->wad_fd);
01570 
01571         // OJO: Esta correccion es de dudosa procedencia empirica: Al parecer
01572         // en el archivo las unidades son enteros con signo (complemento a 2)
01573         // y no "WORD" (que son sin signo).
01574         CORREGIR(Vertices[i].x);    CORREGIR(Vertices[i].y);
01575         //
01576 
01577         if ( Vertices[i].x > max.x ) max.x = Vertices[i].x;
01578         if ( Vertices[i].y > max.y ) max.y = Vertices[i].y;
01579         if ( Vertices[i].x < min.x ) min.x = Vertices[i].x;
01580         if ( Vertices[i].y < min.y ) min.y = Vertices[i].y;
01581     }
01582 
01583     // OJO!
01584     //LA_vista->centro_x = (max.x + min.x) / 2;
01585     //LA_vista->centro_y = (max.y + min.y) / 2;
01586 
01587 
01588     // OJO: Sera mejor correr los vertices de tal manera que el nivel quede
01589     // "Centrado"?    
01590     _BSP2D_VERTICEi delta;
01591 
01592     delta.x = -(max.x - min.x)/2 - (min.x - 32768);
01593     delta.y = -(max.y - min.y)/2 - (min.y - 32768);
01594     mover(delta);
01595 
01596     //- Prepare las paredes ---------------------------------------------------
01597     Paredes = new _BSP2D_PARED[Nivel_wad->Sidedefs->size / 30];
01598     CHEQUEO_WAD(Paredes, "No se pueden crear las paredes (SIDEDEFS)!");
01599     num_paredes = Nivel_wad->Sidedefs->size / 30;
01600 
01601     for ( i = 0; i < (unsigned long)num_paredes; i++ ) {
01602         Paredes[i].importe_wad(this, Nivel_wad, i);
01603     }
01604 
01605     //- Importe arcos ---------------------------------------------------------
01606     Arcos = new _BSP2D_ARCO[Nivel_wad->Linedefs->size / 14];
01607     VERIFIQUE(Arcos, "ERROR: No se pueden crear %ld arcos.\n", 
01608               Nivel_wad->Linedefs->size / 14);
01609     num_arcos = Nivel_wad->Linedefs->size / 14;
01610 
01611     for ( i = 0; i < (unsigned long)num_arcos ; i++) {
01612         Arcos[i].importe_wad(this, Nivel_wad, i);
01613     }
01614 
01615     //- Prepare los segmentos  ------------------------------------------------
01616     Segmentos = new _BSP2D_SEGMENTOi[(Nivel_wad->Segs->size)/12];
01617     VERIFIQUE(Arcos, "ERROR: No se pueden crear %ld segmentos.\n", 
01618               Nivel_wad->Segs->size / 12);
01619     num_segmentos = (Nivel_wad->Segs->size)/12;
01620 
01621     for ( i = 0; i < (unsigned long)num_segmentos; i++ ) {
01622         Segmentos[i].importe_wad(this, Nivel_wad, i);
01623     }
01624 
01625     //- Prepare los sectores --------------------------------------------------
01626     Sectores = new _BSP2D_SECTOR[(Nivel_wad->Sectors->size)/26];
01627     VERIFIQUE(Sectores, "ERROR: No se pueden crear %ld sectores.\n", 
01628               Nivel_wad->Sectors->size / 26);
01629     num_sectores = (Nivel_wad->Sectors->size)/26;
01630 
01631     for ( i = 0; i < (unsigned long)num_sectores; i++ ) {
01632         Sectores[i].importe_wad(this, Nivel_wad, i);
01633     }
01634 
01635     //- Prepare las hojas del arbol BSP ---------------------------------------
01636     Hojas = new _BSP2D_HOJA[(Nivel_wad->Ssectors->size)/4];
01637     VERIFIQUE(Hojas, "ERROR: No se pueden crear %ld hojas (SSECTORS).\n", 
01638               Nivel_wad->Ssectors->size / 4);
01639     num_hojas = (Nivel_wad->Ssectors->size)/4;
01640 
01641     for ( i = 0; i < (unsigned long)num_hojas; i++ ) {
01642         Hojas[i].init(this);
01643         Hojas[i].importe_wad(Nivel_wad, i);
01644     }
01645 
01646     //- Construya la estructura BSP (!) ---------------------------------------
01647     Nodos = new _BSP2D_NODO[(Nivel_wad->Nodes->size)/28];
01648     VERIFIQUE(Hojas, "ERROR: No se pueden crear %ld hojas (SSECTORS).\n", 
01649               Nivel_wad->Nodes->size / 28);
01650     num_nodos = (Nivel_wad->Nodes->size)/28;
01651 
01652     for ( i = 0; i < (unsigned long)num_nodos; i++ ) {
01653         Nodos[i].init(this);
01654         Nodos[i].importe_wad(Nivel_wad, i);
01655     }
01656     Raiz = &Nodos[num_nodos - 1]; 
01657 
01658     //- Ejecute la etapa de preprocesamiento ----------------------------------
01659     for ( i = 0; i < (unsigned long)num_paredes; i++ ) {
01660         // Normales de las paredes
01661         Paredes[i].calcule_normal();
01662     }
01663     for ( i = 0; i < (unsigned long)num_sectores; i++ ) {
01664         // Triangularizacion de sectores
01665         Sectores[i].triangularize();
01666     }
01667     Raiz->mover(delta);               // Colocar la estructura cerca del origen
01668     datos_wad->localice_paleta(0);    // Prepare la paleta de colores
01669     paleta_para_texturas.importar_raw256(datos_wad->fd);
01670     paleta_para_texturas.aplique_gamma(1.5);
01671 
01672     return TRUE;
01673 }
01674 
01675 int
01676 BSP_2D::deme_flat(char *nombre)
01688 {
01689     int i;
01690 
01691     if ( strcmp(nombre, "-") == 0 ) return -1;
01692 
01693     // Busque el nombre de la textura a ver si ya estaba
01694     for ( i = 0; i < nombres_flats.tam(); i++ ) {
01695         if ( strcmp(nombre, nombres_flats[i]) == 0 ) {
01696             return i;
01697         }
01698     }
01699 
01700     // Esta es una textura nueva!
01701     char *nuevo_nombre;
01702     IMAGEN_PAL *nueva_imagen;
01703 
01704     // Busque esta textura en el WAD
01705     if ( !datos_wad->localice_flat_por_nombre(nombre) ) {
01706         printf("Warning: La imagen flat-\"%s\" no se encontro en el WAD!\n",
01707                nombre);
01708         return -2;
01709     }
01710 
01711     nuevo_nombre = new char[9];
01712     strcpy(nuevo_nombre, nombre);
01713     nombres_flats.anx(nuevo_nombre);
01714 
01715     nueva_imagen = new IMAGEN_PAL();
01716     nueva_imagen->importar_wadflat(datos_wad->fd);
01717     flats.anx(nueva_imagen);
01718 
01719     return nombres_flats.tam() - 1;
01720 }
01721 
01722 int
01723 BSP_2D::deme_textura(char *nombre)
01736 {
01737     int i;
01738 
01739     for ( i = 0; i < 8; i++ ) nombre[i] = (char)toupper(nombre[i]);
01740 
01741     if ( strcmp(nombre, "-") == 0 ) return -1;
01742 
01743     // Busque el nombre de la textura a ver si ya estaba
01744     for ( i = 0; i < nombres_sprites.tam(); i++ ) {
01745         if ( strcmp(nombre, nombres_sprites[i]) == 0 ) {
01746             return i;
01747         }
01748     }
01749 
01750     // Esta es una textura nueva!
01751     char *nuevo_nombre;
01752     IMAGEN_PAL *nueva_imagen, *bitmap_i;
01753     int x_tam, y_tam, num_trozos, *Arr_x, *Arr_y, *Arr_i;
01754 
01755     // Busque esta textura en el WAD
01756     if ( !datos_wad->localice_textura_por_nombre(nombre,
01757              &x_tam, &y_tam, &num_trozos, &Arr_x, &Arr_y, &Arr_i) ) {
01758         fprintf(stderr, "<BSP_2D> - Error: La textura \"%s\" es invalida!\n",
01759             nombre);
01760         fflush(stderr);
01761         return -1;
01762       }
01763       else {
01764         // Cree la textura final
01765         nueva_imagen = new IMAGEN_PAL();
01766         if ( !nueva_imagen || !nueva_imagen->init(x_tam, y_tam) ) {
01767             fprintf(stderr, "<BSP_2D> - Error fatal: mal de memoria!\n");
01768             fflush(stderr);
01769             return -1;
01770         }
01771 
01772         // Pegue a manera de retazos todos los trozos sobre la textura final
01773         for ( i = 0; i < num_trozos; i++ ) {
01774             bitmap_i = new IMAGEN_PAL();
01775             if ( !bitmap_i ) {
01776                 fprintf(stderr, "<BSP_2D> - Error fatal: mal de memoria!\n");
01777                 fflush(stderr);
01778                 return -1;
01779             }
01780 
01781             if ( !datos_wad->localice_imagen_por_nombre(
01782                     datos_wad->tabla_pname[Arr_i[i]]) || 
01783                     !bitmap_i->importar_wadsprite(datos_wad->fd) ) {
01784                 fprintf(stderr, "<BSP_2D> - Error fatal: mal de memoria!\n");
01785                 fflush(stderr);
01786                 return -1;
01787             }
01788             nueva_imagen->pegar_subimagen(bitmap_i, Arr_x[i], Arr_y[i]);
01789             delete bitmap_i;
01790             bitmap_i = NULL;
01791         }
01792 
01793         // Elimine estructuras temporales
01794         delete Arr_x;
01795         delete Arr_y;
01796         delete Arr_i;
01797     }
01798 
01799     // Inserte la textura en la lista de imagenes preprocesadas
01800     printf("."); fflush(stdout);
01801     nuevo_nombre = new char[9];
01802     strcpy(nuevo_nombre, nombre);
01803     nombres_sprites.anx(nuevo_nombre);
01804     sprites.anx(nueva_imagen);
01805 
01806     return nombres_sprites.tam() - 1;
01807 }
01808 
01809 //= SERVICIOS DE VISUALIZACION DE LA CLASE BSP_2D ===========================
01810 
01811 #ifdef GL_ENABLED
01812 void
01813 BSP_2D::activar_calidad(CALIDAD_VISUAL *Calidad, MATERIAL *Material)
01820 {
01821     if ( Calidad->calidad_caras == CVC_CONSTANTE ) {
01822         glDisable(GL_LIGHTING);
01823         glColor3f(0.9f, 0.9f, 0.9f);
01824       } 
01825       else {
01826         glEnable(GL_LIGHTING);
01827     }
01828     if ( Calidad->calidad_caras == CVC_SHADE ) {
01829         glShadeModel(GL_SMOOTH);
01830       }
01831       else {
01832         glShadeModel(GL_FLAT);
01833     }
01834 
01835     if ( Calidad->con_textura ) {
01836         paleta_para_texturas.activar_gl();
01837         glEnable(GL_TEXTURE_2D); 
01838       }
01839       else {
01840         glDisable(GL_TEXTURE_2D);
01841     }
01842 
01843     Material->activar_gl();
01844     PRIMITIVA_triangulos = GL_TRIANGLES;
01845     PRIMITIVA_cuadros = GL_QUADS;
01846 }
01847 
01848 void
01849 BSP_2D::pintar_gl_3D_wireframe(CALIDAD_VISUAL *Calidad)
01858 {
01859     long int i;
01860 
01861     for ( i = 0; i < num_sectores; i++ ) {
01862         Sectores[i].marcado = TRUE;
01863         Sectores[i].con_paredes = TRUE;
01864     }
01865     PRIMITIVA_triangulos = GL_LINE_LOOP;
01866     PRIMITIVA_cuadros = GL_LINE_LOOP;
01867     glDisable(GL_LIGHTING);
01868     glColor3f(1, 0, 0);
01869     pintar_gl_3D(Calidad);
01870 }
01871 
01872 void
01873 BSP_2D::pintar_gl_3D(CALIDAD_VISUAL *Calidad)
01890 {
01891     long int i;
01892 
01893     for ( i = 0; i < num_sectores; i++ ) Sectores[i].pintar_gl_3D(Calidad);
01894 
01895     // OJO: Si, en este momento el metodo esta cortico... pero tenga en
01896     //      cuenta que aqui se debera detectar cuando la camara este por
01897     //      fuera de un sector, y cambiar el algoritmo por uno que solo
01898     //      pintar (desde afuera) el cascaron de todo el modelo BSP... (!)
01899 }
01900 
01901 void
01902 BSP_2D::pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material, CAMARA * /*Camara*/)
01915 {
01916     //- En el modo indiscriminado todos los sectores se pintan -------------
01917     long int i;
01918     for ( i = 0; i < num_sectores; i++ ) {
01919         Sectores[i].marcado = TRUE;
01920         Sectores[i].con_paredes = TRUE;
01921     }
01922 
01923     //- Pintado wireframe --------------------------------------------------
01924     if ( Calidad->con_bordes ) pintar_gl_3D_wireframe(Calidad);
01925 
01926     //- Pintado standard ---------------------------------------------------
01927     if ( Calidad->con_caras ) {
01928         activar_calidad(Calidad, Material);
01929         pintar_gl_3D(Calidad);
01930     }
01931 }
01932 
01933 void
01934 BSP_2D::pintar_bsp(CALIDAD_VISUAL *Calidad, MATERIAL *Material, CAMARA *Camara)
01947 {
01948     //- Pintado wireframe (no se usa el BSP) -------------------------------
01949     if ( Calidad->con_bordes ) pintar_gl_3D_wireframe(Calidad);
01950 
01951     //- Inicializacion para el recorrido en modo BSP -----------------------
01952     long int i;
01953     for ( i = 0; i < num_sectores; i++ ) {
01954         Sectores[i].marcado = FALSE;
01955         Sectores[i].con_paredes = FALSE;
01956     }
01957 
01958     //- Pintado usando la estructura BSP -----------------------------------
01959     if ( Calidad->con_caras ) activar_calidad(Calidad, Material);
01960 
01961     // Notese como se tiene en cuenta la camara!
01962     VECTOR orientacion_camara, ejex(1, 0, 0);
01963     MATRIZ_4x4 R;
01964     double pitch, yaw, roll;
01965 
01966     R.importar_quaternion(Camara->orientacion());
01967     R.exportar_angulos_euler(&yaw, &pitch, &roll);
01968     R.rotacion_eje(yaw, 0, 0, 1);
01969     orientacion_camara = R * ejex;
01970 
01971     // Recorra la estructura BSP... dentro de eso esta todo el truco!
01972     NUM_poligonos = 0;
01973     BOOLEAN pintar_plano = FALSE;  // OJO!
01974 
01975     if ( pintar_plano ) {
01976         glDisable(GL_LIGHTING);
01977         Raiz->pintar_gl_2D(Camara->posicion(), orientacion_camara, Calidad);
01978       }
01979       else{
01980         glEnable(GL_LIGHTING);
01981         Raiz->pintar_gl_3D(Camara->posicion(), orientacion_camara, Calidad);
01982         for ( i = 0; i < num_sectores; i++ ) Sectores[i].pintar_gl_3D(Calidad);
01983     }
01984     //printf("Pinto %d poligonos!\n", NUM_poligonos);  fflush(stdout);
01985 }
01986 #endif // GL_ENABLED
01987 
01988 void
01989 BSP_2D::pintar_aqz(FILE *fd)
01990 {
01991     fprintf(fd, "    // Pilas: No hay pintar_aqz... \n");
01992     fprintf(fd, "    geometria ESFERA 1 \"\"\n");
01993 }
01994 
01995 void
01996 BSP_2D::pintar_povray(FILE *fd)
01997 {
01998     // OJO: Esto no se ha hecho!
01999     fprintf(fd,
02000         "sphere {\n"
02001         "    <0, 0, 0>, 0.3\n"
02002     );
02003 }
02004 
02005 //===========================================================================
02006 //= Fin de la accion!                                                       =
02007 //===========================================================================
02008 

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.