00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "toolkits/geom/geometria.h"
00023 #include "lista.cc"
00024
00025 #ifdef VEL_ROSITA
00026 #include "toolkits/geom/terreno.h"
00027 #endif
00028
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #define TRUCO_FAZ
00041
00042
00043 #define NATURAL
00044 #ifndef GL_COMPLETO
00045 #define NATURAL
00046 #endif
00047
00048
00049
00050
00051
00052 #define FACTOR 5000
00053
00054 #define VERIFICAR(p,c) \
00055 if ( !(p) ) { \
00056 fprintf(stderr, "<TERRENO> ERROR: No hay memoria para %s!\n", (c)); \
00057 fflush(stderr); \
00058 exit(1); \
00059 }
00060
00061
00062 #define EEE 10
00063 #define ALTURA_MUESTRA_PA_NORMALES(x, y) (vertices_arr[(y)*_x_tam+(x)].z*EEE)
00064
00065
00066
00067
00068
00109 static int normal_pattern[9][6] = {
00110 {0, 0, 0, 0, 0, 8},
00111 {0, 0, 0, 2, 2, 4},
00112 {0, 0, 0, 4, 4, 0},
00113 {2, 2, 0, 0, 0, 4},
00114 {1, 1, 2, 1, 1, 2},
00115 {0, 0, 4, 2, 2, 0},
00116 {4, 4, 0, 0, 0, 0},
00117 {2, 2, 4, 0, 0, 0},
00118 {0, 0, 8, 0, 0, 0}
00119 };
00120
00136 static int lados_primarios[6][2] = {
00137 {1, 0}, {1, -1}, {0, -1}, {-1, 0}, {-1, 1}, {0, 1} };
00138 static int lados_secundarios[6][2] = {
00139 {1, -1}, {0, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 0} };
00140
00141
00142
00143
00144
00145 TERRENO::TERRENO(GLOBAL_DEM *Fuente,
00146 long int origen_x, long int origen_y, long int xtam, long int ytam,
00147 double escala, double exageracion)
00152 {
00153
00154 #ifdef NONONO
00155 printf("Opciones de compilacion:\n"); fflush(stdout);
00156 #ifdef GL_COMPLETO
00157 printf(" - GL_COMPLETO: TRUE\n"); fflush(stdout);
00158 #endif
00159 #ifndef GL_COMPLETO
00160 printf(" - GL_COMPLETO: FALSE\n"); fflush(stdout);
00161 #endif
00162 #ifdef NATURAL
00163 printf(" - NATURAL: TRUE\n"); fflush(stdout);
00164 #endif
00165 #ifndef NATURAL
00166 printf(" - NATURAL: FALSE\n"); fflush(stdout);
00167 #endif
00168 #ifdef TRUCO_FAZ
00169 printf(" - TRUCO_FAZ: TRUE\n"); fflush(stdout);
00170 #endif
00171 #ifndef TRUCO_FAZ
00172 printf(" - TRUCO_FAZ: FALSE\n"); fflush(stdout);
00173 #endif
00174 #endif
00175
00176
00177 imagen = NULL;
00178 VERIFICAR(Fuente, "una fuente");
00179 _escala = escala;
00180 _factor_exageracion = exageracion;
00181
00182
00183 long int i;
00184
00185 _x_tam = xtam;
00186 _y_tam = ytam;
00187 vertices_tam = xtam * ytam;
00188 vertices_arr = new VERTICE_GL[vertices_tam];
00189 VERIFICAR(vertices_arr, "el arreglo de vertices");
00190
00191 Fuente->exportar_vertices(vertices_arr, origen_x, origen_y, xtam, ytam);
00192
00193 for ( i = 0; i < vertices_tam; i++ ) {
00194 vertices_arr[i].y += 1000;
00195
00196 vertices_arr[i].x -= 1000;
00197
00198
00199 vertices_arr[i].x *= (float)escala;
00200 vertices_arr[i].y *= (float)escala;
00201 vertices_arr[i].z *= (float)escala*(float)_factor_exageracion;
00202 }
00203
00204
00205 int x, y;
00206
00207 _min.x = INFINITO;
00208 _min.y = INFINITO;
00209 _min.z = INFINITO;
00210 _max.x = -INFINITO;
00211 _max.y = -INFINITO;
00212 _max.z = -INFINITO;
00213 for ( y = 1; y < _y_tam-1; y++ ) {
00214 for ( x = 1; x < _x_tam-1; x++ ) {
00215 i = _x_tam * y + x;
00216 if ( vertices_arr[i].x < _min.x ) _min.x = vertices_arr[i].x;
00217 if ( vertices_arr[i].y < _min.y ) _min.y = vertices_arr[i].y;
00218 if ( vertices_arr[i].z < _min.z ) _min.z = vertices_arr[i].z;
00219 if ( vertices_arr[i].x > _max.x ) _max.x = vertices_arr[i].x;
00220 if ( vertices_arr[i].y > _max.y ) _max.y = vertices_arr[i].y;
00221 if ( vertices_arr[i].z > _max.z ) _max.z = vertices_arr[i].z;
00222 }
00223 }
00224
00225
00226 colores_arr = new GLubyte[vertices_tam*3];
00227 VERIFICAR(colores_arr, "el arreglo de colores");
00228 set_paleta(NULL);
00229
00230
00231 TIras_arr = new GLuint *[_y_tam - 3];
00232 VERIFICAR(TIras_arr, "las tiras de triangulos");
00233 for ( y = 0; y < _y_tam-3; y+=
00234 #ifdef TRUCO_FAZ
00235 2
00236 #endif
00237 #ifndef TRUCO_FAZ
00238 1
00239 #endif
00240 ) {
00241 TIras_arr[y] = new GLuint[2*(_x_tam - 2)];
00242 VERIFICAR(TIras_arr[y], "una tira de triangulos");
00243 for ( x = 0; x < _x_tam-2; x++ ) {
00244
00245 TIras_arr[y][2*x] = _x_tam*(y+2)+x+1;
00246 TIras_arr[y][2*x+1] = _x_tam*(y+1)+x+1;
00247 }
00248 }
00249
00250 #ifdef TRUCO_FAZ
00251 for ( y = 1; y < _y_tam-3; y+=2 ) {
00252 TIras_arr[y] = new GLuint[2*(_x_tam - 2)];
00253 VERIFICAR(TIras_arr[y], "una tira de triangulos");
00254 for ( x = _x_tam - 3; x >= 0; x-- ) {
00255
00256 TIras_arr[y][2*x+1] = (_x_tam*(y+2)+x+1);
00257 TIras_arr[y][2*x] = (_x_tam*(y+1)+x+1);
00258 }
00259 }
00260 #endif
00261
00262
00263 VECTOR n(0, 0, 1);
00264 for ( y = 0; y < _y_tam; y++ ) {
00265 for ( x = 0; x < _x_tam; x++ ) {
00266 n = calcule_normal(x, y);
00267 vertices_arr[y*_x_tam+x].nx = (float)n.x;
00268 vertices_arr[y*_x_tam+x].ny = (float)n.y;
00269 vertices_arr[y*_x_tam+x].nz = (float)n.z;
00270 }
00271 }
00272 }
00273
00274 void
00275 TERRENO::elim(void)
00276 {
00277 if ( imagen ) delete imagen;
00278 if ( vertices_arr ) delete vertices_arr;
00279 vertices_arr = NULL;
00280 if ( colores_arr ) delete colores_arr;
00281 colores_arr = NULL;
00282
00283 int y;
00284 if ( TIras_arr ) {
00285 for ( y = 0; y < _y_tam-3; y++ ) {
00286 if ( TIras_arr[y] ) delete TIras_arr[y];
00287 TIras_arr[y] = NULL;
00288 }
00289 delete TIras_arr;
00290 TIras_arr = NULL;
00291 }
00292 }
00293
00294 TERRENO::~TERRENO()
00295 {
00296 elim();
00297 }
00298
00299 void
00300 TERRENO::set_paleta(PALETA *P)
00304 {
00305 Paleta = P;
00306 int x, y, i;
00307 float r, g, b;
00308
00309 for ( y = 1; y < _y_tam-1; y++ ) {
00310 for ( x = 1; x < _x_tam-1; x++ ) {
00311 i = _x_tam * y + x;
00312 calcular_color(vertices_arr[i].z, &r, &g, &b);
00313 colores_arr[3*i] = (GLubyte)((int)(floor(r*255)));
00314 colores_arr[3*i+1] = (GLubyte)((int)(floor(g*255)));
00315 colores_arr[3*i+2] = (GLubyte)((int)(floor(b*255)));
00316 }
00317 }
00318 }
00319
00320
00321
00322
00323 VECTOR
00324 TERRENO::calcule_subnormal(int x1, int y1, int x2, int y2, int x3, int y3)
00329 {
00330 VECTOR sub_normal, a, b;
00331 VECTOR p1;
00332 VECTOR p2;
00333 VECTOR p3;
00334
00335 p1.x = (float)x1;
00336 p1.y = (float)y1;
00337 p1.z = (float)ALTURA_MUESTRA_PA_NORMALES(x1, y1);
00338 p2.x = (float)x2;
00339 p2.y = (float)y2;
00340 p2.z = (float)ALTURA_MUESTRA_PA_NORMALES(x2, y2);
00341 p3.x = (float)x3;
00342 p3.y = (float)y3;
00343 p3.z = (float)ALTURA_MUESTRA_PA_NORMALES(x3, y3);
00344
00345 a.x = (p2.x - p1.x);
00346 a.y = (p2.y - p1.y);
00347 a.z = (p2.z - p1.z);
00348 b.x = (p3.x - p1.x);
00349 b.y = (p3.y - p1.y);
00350 b.z = (p3.z - p1.z);
00351
00352 sub_normal = a.producto_cruz(b);
00353 sub_normal.normalizar();
00354
00355 return sub_normal;
00356 }
00357
00358 VECTOR
00359 TERRENO::calcule_normal(int x, int y)
00365 {
00366 VECTOR normal(0, 0, 0);
00367
00368
00369 int tipo;
00370
00371 if ( y == _y_tam - 1 && x == _x_tam - 1 ) tipo = 8;
00372 else if ( y == 0 && x == _x_tam - 1 ) tipo = 2;
00373 else if ( x == 0 && y == _y_tam - 1 ) tipo = 6;
00374 else if ( y == 0 && x == 0 ) tipo = 0;
00375 else if ( y == _y_tam - 1 ) tipo = 7;
00376 else if ( y == 0 ) tipo = 1;
00377 else if ( x == _x_tam - 1 ) tipo = 5;
00378 else if ( x == 0 ) tipo = 3;
00379 else tipo = 4;
00380
00381
00382 int t, contribucion;
00383
00384 for ( t = 0; t < 6; t++ ) {
00385 contribucion = normal_pattern[tipo][t];
00386 if ( contribucion > 0 ) {
00387 VECTOR sub_normal = calcule_subnormal(
00388 x, y,
00389 x + lados_primarios[t][0], y + lados_primarios[t][1],
00390 x + lados_secundarios[t][0], y + lados_secundarios[t][1]
00391 );
00392 normal.x += sub_normal.x;
00393 normal.y += sub_normal.y;
00394 normal.z += sub_normal.z;
00395 }
00396 }
00397
00398
00399 normal = normal * (-1);
00400 normal.normalizar();
00401 return normal;
00402 }
00403
00404
00405
00406 void
00407 TERRENO::anexar_textura(IMAGEN *img)
00408 {
00409 #ifdef GL_ENABLED
00410 if ( imagen ) delete imagen;
00411 imagen = img;
00412 #endif
00413 }
00414
00415 int
00416 TERRENO::clasificar_punto(VECTOR p)
00423 {
00424 double d = DISTANCIA(0, 0, 0, p.x, p.y, p.z);
00425
00426 if ( IGUAL(1, d ) ) {
00427 return 0;
00428 }
00429 else if ( d < 1 ) {
00430 return 1;
00431 }
00432 return -1;
00433
00434 }
00435
00436 void
00437 TERRENO::minmax(VECTOR *min, VECTOR *max)
00438 {
00439 min->x = _min.x;
00440 min->y = _min.y;
00441 min->z = _min.z;
00442 max->x = _max.x;
00443 max->y = _max.y;
00444 max->z = _max.z;
00445 }
00446
00447 void
00448 TERRENO::calcular_color(float z, float *r, float *g, float *b)
00449 {
00450 z /= (float)_factor_exageracion;
00451
00452 double val;
00453 COLOR c;
00454
00455 if ( Paleta ) {
00456
00457 val = (z/_escala)/7000 + 0.19;
00458
00459 c = Paleta->escala(val);
00460 (*r) = c.r;
00461 (*g) = c.g;
00462 (*b) = c.b;
00463 return;
00464 }
00465
00466
00467 if ( z <= 0 ) {
00468 (*r) = 0;
00469 (*g) = 0;
00470 (*b) = 1;
00471 }
00472 else if ( z*FACTOR < 100 ) {
00473 (*r) = (float)0.5;
00474 (*g) = (float)0.8;
00475 (*b) = (float)0.5;
00476 }
00477 else if ( z*FACTOR < 200 ) {
00478 (*r) = (float)0.5;
00479 (*g) = (float)0.7;
00480 (*b) = (float)0.5;
00481 }
00482 else if ( z*FACTOR < 500 ) {
00483 (*r) = (float)0.7;
00484 (*g) = (float)0.7;
00485 (*b) = (float)0.5;
00486 }
00487 else if ( z*FACTOR< 1000 ) {
00488 (*r) = (float)0.5;
00489 (*g) = (float)0.5;
00490 (*b) = (float)0.3;
00491 }
00492 else if ( z*FACTOR < 2000 ) {
00493 (*r) = (float)0.5;
00494 (*g) = (float)0.5;
00495 (*b) = 0;
00496 }
00497 else if ( z*FACTOR < 3000 ) {
00498 (*r) = (float)0.5;
00499 (*g) = (float)0.5;
00500 (*b) = (float)0.2;
00501 }
00502 else if ( z*FACTOR < 4000 ) {
00503 (*r) = (float)0.5;
00504 (*g) = (float)0.5;
00505 (*b) = (float)0.5;
00506 }
00507 else if ( z*FACTOR < 5000 ) {
00508 (*r) = (float)0.9;
00509 (*g) = (float)0.9;
00510 (*b) = (float)0.9;
00511 }
00512 else {
00513 (*r) = 1;
00514 (*g) = 1;
00515 (*b) = 1;
00516 }
00517 ;
00518 }
00519
00520 #ifdef GL_ENABLED
00521
00522 void
00523 TERRENO::pintar_tiras_gl(void)
00530 {
00531
00532 #ifdef NATURAL
00533 int y;
00534
00535 #ifndef GL_COMPLETO
00536 float r = 1, g = 0, b = 0;
00537 int x;
00538
00539 for ( y = 0; y < _y_tam-3; y++ ) {
00540 #ifdef TRUCO_FAZ
00541 if ( y % 2 ) glFrontFace(GL_CW); else glFrontFace(GL_CCW);
00542 #endif
00543 glBegin(GL_TRIANGLE_STRIP);
00544 for ( x = 0; x < _x_tam - 2; x++ ) {
00545 calcular_color(vertices_arr[TIras_arr[y][2*x]].z, &r, &g, &b);
00546 glColor3f(r, g, b);
00547 glNormal3fv(&vertices_arr[TIras_arr[y][2*x]].nx);
00548 glVertex3fv(&vertices_arr[TIras_arr[y][2*x]].x);
00549
00550 calcular_color(vertices_arr[TIras_arr[y][2*x+1]].z, &r, &g, &b);
00551 glColor3f(r, g, b);
00552 glNormal3fv(&vertices_arr[TIras_arr[y][2*x+1]].nx);
00553 glVertex3fv(&vertices_arr[TIras_arr[y][2*x+1]].x);
00554 }
00555 glEnd();
00556 }
00557 #endif
00558
00559 #ifdef GL_COMPLETO
00560 glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertices_arr);
00561 glEnableClientState(GL_COLOR_ARRAY);
00562 glColorPointer(3, GL_UNSIGNED_BYTE, 0, colores_arr);
00563 for ( y = 0; y < _y_tam-3; y++ ) {
00564 #ifdef TRUCO_FAZ
00565 if ( y % 2 ) glFrontFace(GL_CW); else glFrontFace(GL_CCW);
00566 #endif
00567 glDrawElements(GL_TRIANGLE_STRIP,
00568 2*(_x_tam - 2), GL_UNSIGNED_INT,
00569 TIras_arr[y]);
00570 }
00571 glDisable(GL_COLOR_ARRAY);
00572 #endif
00573 #endif
00574
00575
00576
00577 #ifndef NATURAL
00578 int y;
00579
00580 glDisable(GL_LIGHTING);
00581 glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertices_arr);
00582 glEnableClientState(GL_COLOR_ARRAY);
00583 glColorPointer(3, GL_UNSIGNED_BYTE, 0, colores_arr);
00584 for ( y = 0; y < _y_tam-3; y++ ) {
00585 #ifdef TRUCO_FAZ
00586 if ( y % 2 ) glFrontFace(GL_CW); else glFrontFace(GL_CCW);
00587 #endif
00588 glDrawElements(GL_TRIANGLE_STRIP,
00589 2*(_x_tam - 2), GL_UNSIGNED_INT,
00590 TIras_arr[y]);
00591 }
00592 glDisable(GL_COLOR_ARRAY);
00593 #endif
00594
00595
00596 #ifdef TRUCO_FAZ
00597 glFrontFace(GL_CCW);
00598 #endif
00599
00600
00601 #ifdef NONONO
00602
00603 glDisable(GL_LIGHTING);
00604 glColor3f(1, 1, 0);
00605 for ( y = 0; y < _y_tam-3; y++ ) {
00606 glBegin(GL_LINES);
00607 for ( x = 0; x < _x_tam - 2; x++ ) {
00608 glVertex3f(vertices_arr[y*_x_tam+x].x,
00609 vertices_arr[y*_x_tam+x].y,
00610 vertices_arr[y*_x_tam+x].z);
00611 glVertex3f(vertices_arr[y*_x_tam+x].x+vertices_arr[y*_x_tam+x].nx/40,
00612 vertices_arr[y*_x_tam+x].y+vertices_arr[y*_x_tam+x].ny/40,
00613 vertices_arr[y*_x_tam+x].z+vertices_arr[y*_x_tam+x].nz/40);
00614 }
00615 glEnd();
00616 }
00617 #endif
00618
00619
00620 #ifdef DEBUG_TERRENO
00621 VERTICE_GL v;
00622 int i;
00623
00624 glDisable(GL_LIGHTING);
00625 glColor3d(color_debug.r, color_debug.g, color_debug.b);
00626 for ( i = 0; i < arr_debug_x.tam(); i++ ) {
00627 glPushMatrix();
00628 v = vertices_arr[arr_debug_y[i]*_x_tam+arr_debug_x[i]];
00629 glTranslated(v.x, v.y, v.z);
00630 pintar_cubo(0.01);
00631 glPopMatrix();
00632 }
00633
00634 #endif
00635 }
00636
00637 void
00638 TERRENO::pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material,
00639 CAMARA * )
00640 {
00641
00642 #ifdef NONONO
00643 long int i;
00644
00645
00646 glColor3f(1, 1, 1);
00647 glDisable(GL_LIGHTING);
00648 glBegin(GL_POINTS);
00649 for ( i = 0; i < vertices_tam; i++ ) {
00650 glVertex3fv(&vertices_arr[i].x);
00651 }
00652 glEnd();
00653 #endif
00654
00655
00656 COLOR cb(1, 0, 0);
00657
00658 if ( Calidad->con_bordes ) {
00659 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00660 if ( !Calidad->con_caras ) glDisable(GL_CULL_FACE);
00661 Calidad->activar_bordes_gl(cb, Material);
00662
00663 pintar_tiras_gl();
00664 }
00665
00666 if ( Calidad->con_cajas ) PINTAR_MINMAX_GL();
00667
00668
00669 COLOR c(1, 1, 1);
00670
00671 if ( Calidad->con_caras ) {
00672 glEnable(GL_CULL_FACE);
00673 glCullFace(GL_BACK);
00674 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00675 Material->activar_gl();
00676 Calidad->activar_caras_gl(c, Material);
00677 if ( imagen && Calidad->con_textura ) {
00678 imagen->activar_gl();
00679 glEnable(GL_TEXTURE_2D);
00680 Calidad->activar_textura_gl();
00681 }
00682 else if ( Calidad->con_caustics ) {
00683 Calidad->activar_textura_gl();
00684 }
00685 else {
00686 glDisable(GL_TEXTURE_2D);
00687 }
00688
00689 ACTIVAR_POLYGON_OFFSET();
00690
00691 glEnable(GL_COLOR_MATERIAL);
00692 glColorMaterial(GL_FRONT, GL_DIFFUSE);
00693
00694 pintar_tiras_gl();
00695
00696 glDisable(GL_COLOR_MATERIAL);
00697
00698 DESACTIVAR_POLYGON_OFFSET();
00699 glDisable(GL_TEXTURE_2D);
00700 }
00701
00702 }
00703 #endif
00704
00705 void
00706 TERRENO::pintar_aqz(FILE *fd)
00707 {
00708 fprintf(fd, " // Pilas: No hay pintar_aqz... \n");
00709 fprintf(fd, " geometria ESFERA 1 \"\"\n");
00710 }
00711
00712 void
00713 TERRENO::pintar_povray(FILE *fd)
00714 {
00715 fprintf(fd,
00716 "sphere {\n"
00717 " <0, 0, 0>, %f\n",
00718 1.0
00719 );
00720 }
00721
00722 GEOMETRIA *
00723 TERRENO::crear_copia(void)
00727 {
00728 TERRENO *e;
00729
00730 e = new TERRENO(NULL, 0, 0, 1, 1, 1, 1);
00731 VERIFICAR(e, "la copia de la GEOMETRIA");
00732 if ( !e ) return NULL;
00733
00734 (*e) = (*this);
00735
00736 if ( imagen ) {
00737 e->imagen = imagen->copie();
00738 if ( !e->imagen ) {
00739 fprintf(stderr,
00740 "<TERRENO> Warning: no se pudo replicar una textura.\n");
00741 fflush(stderr);
00742 }
00743 }
00744
00745 return (GEOMETRIA *)e;
00746 }
00747
00748 #ifdef NONONO
00749 double
00750 TERRENO::altura(double x, double y)
00754 {
00755 int i, j;
00756
00757 i = coord2index_x(x);
00758 j = coord2index_x(y);
00759 if ( i >= 0 && i < _x_tam &&
00760 j >= 0 && j < _y_tam ) {
00761
00762
00763 return vertices_arr[(i) + _x_tam*(j)].z;
00764 }
00765 return 0;
00766 }
00767 #endif
00768
00769 BOOLEAN
00770 TERRENO::seleccionar(RAYO *Rayito, int *i, int *j)
00771 {
00772 VECTOR p, n;
00773 if ( !interseccion(Rayito, p, n) ) return FALSE;
00774 p.x += 500*_escala;
00775 p.y += 500*_escala;
00776 (*i) = coord2index_x(p.x) + 2;
00777 (*j) = coord2index_y(p.y) - 1;
00778 return TRUE;
00779 }
00780
00781
00782
00783
00784
00785