00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
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;
00054
00055 #endif
00056
00057
00058
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
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
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
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(§or_id, Nivel_wad->wad_fd);
00185
00186 lea_WORD_BE(&temp, Nivel_wad->wad_fd);
00187
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
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
00215
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
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
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(§or_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
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
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
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
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 }
00374 ;
00375 }
00376 #endif
00377
00378
00379
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
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
00421 Pared = Padre->Arcos[arco_i].Der;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 _BSP2D_PARED *p;
00437
00438 if ( !direccion ) {
00439
00440 p = Padre->Arcos[arco_i].Der;
00441 }
00442 else {
00443
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
00481 double fov = 85;
00482
00483 if ( cos(angulo_camara - angulo_recta) < -cos(DEG2RAD(fov)) ) return;
00484
00485
00486 _BSP2D_VERTICEi v, medio_i, medio_f;
00487
00488 #ifdef NONONO
00489
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
00500
00501 #ifdef NONONO
00502
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
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
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
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
00562 double fov = 60;
00563
00564 if ( cos(angulo_camara - angulo_recta) < -cos(DEG2RAD(fov)) ) return;
00565
00566
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
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
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
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
00707 num_vertices =
00708 prepare_segments(Vertices, nvertices, contour_sizes, ncontours);
00709
00710
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
00748 for ( i = 0, j = 0; i < Padre->num_paredes; i++ ) {
00749 if ( Padre->Paredes[i].sector_id == pos ) {
00750 Arco = new _BSP2D_ARCO();
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
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
00785
00786 delete Contorno;
00787 }
00788 else {
00789 cOntornos.anx(Contorno);
00790 }
00791 }
00792
00793
00794
00795
00796
00797 for ( i = 0; i < (long int)cOntornos.tam(); i++ ) {
00798 Contorno = cOntornos[i];
00799
00800
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
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
00825 int nvertices, *contour_sizes;
00826 long int ncontours;
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
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 ntriangles = triangularice_cara(op,
00869 Vertices, nvertices, contour_sizes, ncontours);
00870
00871
00872
00873
00874
00875
00876
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
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
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
00987 double FT = 1.2;
00988
00989 double IU = 0;
00990 double IV = -0.3;
00991
00992 if ( !marcado ) return;
00993
00994
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
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
01032 if ( con_paredes ) {
01033
01034
01035
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
01048
01049
01050
01051
01052
01053
01054
01055
01056
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
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 )
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 ,
01130 VECTOR orientacion_camara, CALIDAD_VISUAL * )
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 ,
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 , WORD )
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
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;
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
01271
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
01296
01297
01298
01299 #define PINTADO_NODO(metodo) \
01300 posicion_camara.z = 0; \
01301 orientacion_camara.z = 0; \
01302 orientacion_camara.normalizar(); \
01303 \
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 \
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 \
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
01359 #ifdef NONONO
01360 _BSP2D_VERTICEi v;
01361
01362
01363 if ( Izq && Izq->mi_tipo == 'n' ) {
01364
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
01376 if ( Der && Der->mi_tipo == 'n' ) {
01377
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
01388 glShadeModel(GL_SMOOTH);
01389
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
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
01431
01432
01433 return 0;
01434 }
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 BSP_2D::BSP_2D()
01452 {
01453
01454 min.x = min.y = INT_MAX;
01455 max.x = max.y = INT_MIN;
01456 datos_wad = NULL;
01457
01458
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
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
01493 }
01494
01495 double
01496 BSP_2D::altura(double x, double y)
01501 {
01502
01503
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 * )
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 )
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
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
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
01572
01573
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
01584
01585
01586
01587
01588
01589
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
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
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
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
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
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
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
01659 for ( i = 0; i < (unsigned long)num_paredes; i++ ) {
01660
01661 Paredes[i].calcule_normal();
01662 }
01663 for ( i = 0; i < (unsigned long)num_sectores; i++ ) {
01664
01665 Sectores[i].triangularize();
01666 }
01667 Raiz->mover(delta);
01668 datos_wad->localice_paleta(0);
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
01694 for ( i = 0; i < nombres_flats.tam(); i++ ) {
01695 if ( strcmp(nombre, nombres_flats[i]) == 0 ) {
01696 return i;
01697 }
01698 }
01699
01700
01701 char *nuevo_nombre;
01702 IMAGEN_PAL *nueva_imagen;
01703
01704
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
01744 for ( i = 0; i < nombres_sprites.tam(); i++ ) {
01745 if ( strcmp(nombre, nombres_sprites[i]) == 0 ) {
01746 return i;
01747 }
01748 }
01749
01750
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
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
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
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
01794 delete Arr_x;
01795 delete Arr_y;
01796 delete Arr_i;
01797 }
01798
01799
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
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
01896
01897
01898
01899 }
01900
01901 void
01902 BSP_2D::pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material, CAMARA * )
01915 {
01916
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
01924 if ( Calidad->con_bordes ) pintar_gl_3D_wireframe(Calidad);
01925
01926
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
01949 if ( Calidad->con_bordes ) pintar_gl_3D_wireframe(Calidad);
01950
01951
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
01959 if ( Calidad->con_caras ) activar_calidad(Calidad, Material);
01960
01961
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
01972 NUM_poligonos = 0;
01973 BOOLEAN pintar_plano = FALSE;
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
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
01999 fprintf(fd,
02000 "sphere {\n"
02001 " <0, 0, 0>, 0.3\n"
02002 );
02003 }
02004
02005
02006
02007
02008