00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "jed_defs.h"
00025
00026 #ifndef __GEOMETRIA__
00027 #error "No incluya a terreno.h, incluya a geometria.h!"
00028 #endif
00029
00030 #ifdef VEL_ROSITA
00031 #include "toolkits/geom/geometria.h"
00032 #endif
00033 #include "toolkits/util/dem.h"
00034
00035
00036
00037 #ifdef DEBUG_TERRENO_LOD
00038 #include "lista.cc"
00039 #endif
00040
00041 class COORDENADA_2D
00042 {
00043 public:
00044 int x;
00045 int y;
00046
00047 COORDENADA_2D operator + (COORDENADA_2D otro) {
00048 COORDENADA_2D r;
00049
00050 r.x = x + otro.x;
00051 r.y = y + otro.y;
00052
00053 return r;
00054 };
00055
00056 COORDENADA_2D operator / (int otro) {
00057 COORDENADA_2D r;
00058
00059 r.x = x/otro;
00060 r.y = y/otro;
00061
00062 return r;
00063 };
00064
00065 int operator == (COORDENADA_2D otro) {
00066 if ( x == otro.x && y == otro.y ) {
00067 return 1;
00068 }
00069 return 0;
00070 };
00071 };
00072
00073
00074
00075
00076 class _TERRENO_LOD_ATRIBUTO_VERTICE {
00077 private:
00078 BYTE data;
00079 public:
00080 inline _TERRENO_LOD_ATRIBUTO_VERTICE();
00081 inline ~_TERRENO_LOD_ATRIBUTO_VERTICE();
00082 inline BOOLEAN enabled(void);
00083 inline void set_enabled(BOOLEAN e);
00084 inline BOOLEAN activated(void);
00085 inline void set_activated(BOOLEAN e);
00086 inline BOOLEAN dependency(int i);
00087 inline void set_dependency(int i, BOOLEAN e);
00088 };
00089
00090
00091
00092
00093
00094 _TERRENO_LOD_ATRIBUTO_VERTICE::_TERRENO_LOD_ATRIBUTO_VERTICE()
00095 {
00096 data = 0;
00097 set_enabled(FALSE);
00098 set_activated(FALSE);
00099
00100 set_dependency(0, FALSE);
00101 set_dependency(1, FALSE);
00102 set_dependency(2, FALSE);
00103 set_dependency(3, FALSE);
00104 }
00105
00106 _TERRENO_LOD_ATRIBUTO_VERTICE::~_TERRENO_LOD_ATRIBUTO_VERTICE()
00107 {
00108 ;
00109 }
00110
00111 BOOLEAN
00112 _TERRENO_LOD_ATRIBUTO_VERTICE::enabled(void)
00113 {
00114 return data & 0x01;
00115 }
00116
00117 void
00118 _TERRENO_LOD_ATRIBUTO_VERTICE::set_enabled(BOOLEAN e)
00119 {
00120 if ( e ) {
00121 data |= 0x01;
00122 }
00123 else {
00124 data &= ~0x01;
00125 }
00126 }
00127
00128 BOOLEAN
00129 _TERRENO_LOD_ATRIBUTO_VERTICE::activated(void)
00130 {
00131 return data & 0x02;
00132 }
00133
00134 void
00135 _TERRENO_LOD_ATRIBUTO_VERTICE::set_activated(BOOLEAN e)
00136 {
00137 if ( e ) {
00138 data |= 0x02;
00139 }
00140 else {
00141 data &= ~0x02;
00142 }
00143 }
00144
00145 BOOLEAN
00146 _TERRENO_LOD_ATRIBUTO_VERTICE::dependency(int i)
00147 {
00148 return data & (0x03<<i);
00149 }
00150
00151 void
00152 _TERRENO_LOD_ATRIBUTO_VERTICE::set_dependency(int i, BOOLEAN e)
00153 {
00154 if ( e ) {
00155 data |= (0x03<<i);
00156 }
00157 else {
00158 data &= ~(0x03<<i);
00159 }
00160 }
00161
00162
00163
00164
00165 class TERRENO_LOD : public GEOMETRIA
00166 {
00167 private:
00168
00169 COORDENADA_2D buffer[2];
00170 int nivel_anterior;
00171 int ptr;
00172 int dimension;
00173
00174
00175 IMAGEN *imagen;
00176 long int _x_tam;
00177 long int _y_tam;
00178 long int vertices_tam;
00179 VERTICE_GL *vertices_arr;
00180 _TERRENO_LOD_ATRIBUTO_VERTICE *atributos_arr;
00181
00182 VECTOR _min;
00183 VECTOR _max;
00184 double _escala;
00185 double _factor_exageracion;
00186
00187
00188 LISTA <int> arr_debug_x;
00189 LISTA <int> arr_debug_y;
00190 #ifdef DEBUG_TERRENO_LOD
00191 COLOR color_debug;
00192 #endif
00193
00194
00195
00196
00197 #ifdef GL_ENABLED
00198 void pintar_tiras_gl(void);
00199 void pintar_tirasv_gl(void);
00200 #endif
00201
00202
00203 VECTOR calcule_subnormal(int x1, int y1, int x2, int y2, int x3, int y3);
00204 VECTOR calcule_normal(int x, int y);
00205 double interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal,
00206 int x, int y);
00207 int coord2index_x(double x_coord);
00208 int coord2index_y(double y_coord);
00209
00210
00211 void
00212 pintar_cuadrante_gl(COORDENADA_2D l, COORDENADA_2D t, COORDENADA_2D r,
00213 int nivel);
00214 void toggle_ptr(void);
00215 BOOLEAN elem_buffer(COORDENADA_2D &o);
00216 void
00217 consultar_padres(COORDENADA_2D *h, COORDENADA_2D *p1, COORDENADA_2D *p2,
00218 int *i1, int *i2, int nivel);
00219 void update_vertex(COORDENADA_2D *v);
00220 void notify(COORDENADA_2D *v, int child, BOOLEAN state);
00221
00222 public:
00223
00224 TERRENO_LOD(GLOBAL_DEM *Fuente,
00225 long int origen_x, long int origen_y, long int xtam, long int ytam,
00226 double escala, double exageracion);
00227 virtual ~TERRENO_LOD();
00228
00229
00230 double interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal);
00231
00232
00233 void anexar_textura(IMAGEN *img);
00234 int clasificar_punto(VECTOR p);
00235 virtual GEOMETRIA *crear_copia(void);
00236
00237 void minmax(VECTOR *min, VECTOR *max);
00238
00239 #ifdef GL_ENABLED
00240 void
00241 pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material, CAMARA *Camara);
00242 #endif
00243 void pintar_povray(FILE *fd);
00244 void pintar_aqz(FILE *fd);
00245
00246
00247
00248 BOOLEAN seleccionar(RAYO *Rayito, int *i, int *j);
00249 double index2coord_x(int i);
00250 double index2coord_y(int j);
00251 };
00252
00253 inline int
00254 TERRENO_LOD::coord2index_x(double x_coord)
00260 {
00261 int i;
00262
00263 i = (int)(x_coord / (1000*_escala)) - 1;
00264
00265 return i;
00266 }
00267
00268 inline int
00269 TERRENO_LOD::coord2index_y(double y_coord)
00275 {
00276 int j;
00277
00278
00279 j = (int)(y_coord / (1000 * _escala)) + _y_tam - 1 - 2;
00280
00281 return j;
00282 }
00283
00284 inline double
00285 TERRENO_LOD::index2coord_x(int i)
00289 {
00290 double x;
00291
00292
00293 x = vertices_arr[i].x;
00294
00295 return x;
00296 }
00297
00298 inline double
00299 TERRENO_LOD::index2coord_y(int j)
00303 {
00304 double y;
00305
00306
00307 y = vertices_arr[j*_x_tam].y;
00308
00309 return y;
00310 }
00311
00312 inline double
00313 TERRENO_LOD::interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal,
00314 int x, int y)
00328 {
00329
00330 VECTOR a, b, c, d;
00331
00332 a.x = index2coord_x(x);
00333 a.y = index2coord_y(y);
00334 a.z = vertices_arr[y*_x_tam + x].z;
00335
00336 b.x = index2coord_x(x);
00337 b.y = index2coord_y(y+1);
00338 b.z = vertices_arr[(y+1)*_x_tam + x].z;
00339
00340 c.x = index2coord_x(x+1);
00341 c.y = index2coord_y(y);
00342 c.z = vertices_arr[y*_x_tam + x+1].z;
00343
00344 d.x = index2coord_x(x+1);
00345 d.y = index2coord_y(y+1);
00346 d.z = vertices_arr[(y+1)*_x_tam + x+1].z;
00347
00348
00349 VECTOR O = Rayo->origen;
00350 VECTOR l = Rayo->direccion;
00351 double T = 0;
00352 double pp, pq, m;
00353 double D;
00354
00355 l.normalizar();
00356
00357
00358 double t1 = INFINITO;
00359 VECTOR p1, n1;
00360
00361 n1 = (a-b).producto_cruz(d-b);
00362 n1.normalizar();
00363 D = n1.x*d.x + n1.y*d.y + n1.z*d.z;
00364
00365 pp = n1.producto_punto(l);
00366 pq = n1.producto_punto(O-b);
00367 if ( pp < -EPSILON && pq > EPSILON ||
00368 pp > EPSILON && pq < -EPSILON ) {
00369
00370
00371 t1 = (-1) * ( (n1.x*O.x + n1.y*O.y + n1.z*O.z - D) /
00372 (n1.x*l.x + n1.y*l.y + n1.z*l.z) );
00373 p1 = O + l * t1;
00374 m = (d.y - a.y)/(d.x - a.x);
00375 if ( p1.x >= a.x-EPSILON && p1.y <= d.y+EPSILON &&
00376 p1.y >= m*(p1.x - a.x) + a.y - EPSILON ) {
00377
00378 normal = n1;
00379 punto = p1;
00380 T = t1;
00381 }
00382 else {
00383 t1 = INFINITO;
00384 }
00385 }
00386
00387
00388 double t2 = 0.0;
00389 VECTOR p2, n2;
00390
00391 n2 = (d-c).producto_cruz(a-c);
00392 n2.normalizar();
00393 D = n2.x*d.x + n2.y*d.y + n2.z*d.z;
00394
00395 pp = n2.producto_punto(l);
00396 pq = n2.producto_punto(O-c);
00397 if ( pp < -EPSILON && pq > EPSILON ||
00398 pp > EPSILON && pq < -EPSILON ) {
00399
00400
00401 t2 = (-1) * ( (n2.x*O.x + n2.y*O.y + n2.z*O.z - D) /
00402 (n2.x*l.x + n2.y*l.y + n2.z*l.z) );
00403 p2 = O + l * t2;
00404 m = (d.y - a.y)/(d.x - a.x);
00405 if ( p2.x <= d.x+EPSILON && p2.y >= c.y-EPSILON &&
00406 p2.y <= m*(p2.x - a.x) + a.y + EPSILON ) {
00407
00408 if ( t2 <= t1 + EPSILON ) {
00409 normal = n2;
00410 punto = p2;
00411 T = t2;
00412 }
00413 }
00414 }
00415
00416
00417 return T;
00418 }
00419
00420 inline double
00421 TERRENO_LOD::interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal)
00432 {
00433
00434
00435
00436 int tipo_situacion = 0;
00437 VECTOR r;
00438 double m=0;
00439 double b=0;
00440
00441 arr_debug_x.elim();
00442 arr_debug_y.elim();
00443
00444
00445 r = Rayo->direccion;
00446 r.normalizar();
00447 r.z = 0;
00448
00449 if ( r.norma() < 5*EPSILON ) {
00450 tipo_situacion = 1;
00451 #ifdef DEBUG_TERRENO_LOD
00452 color_debug.r = 1; color_debug.g = 0; color_debug.b = 0;
00453 #endif
00454 }
00455
00456
00457 if ( !tipo_situacion ) {
00458 r.normalizar();
00459 if ( fabs(r.x) >= fabs(r.y) ) {
00460 tipo_situacion = 2;
00461 #ifdef DEBUG_TERRENO_LOD
00462 color_debug.r = 0; color_debug.g = 1; color_debug.b = 1;
00463 #endif
00464 }
00465 else {
00466 tipo_situacion = 3;
00467 #ifdef DEBUG_TERRENO_LOD
00468 color_debug.r = 1; color_debug.g = 0; color_debug.b = 1;
00469 #endif
00470 }
00471 }
00472
00473
00474 int x, y;
00475
00476 if ( tipo_situacion == 1 ) {
00477 x = coord2index_x(Rayo->origen.x);
00478 y = coord2index_y(Rayo->origen.y);
00479 if ( x >= -1 && x <= _x_tam - 3 &&
00480 y > 0 && y <= _y_tam ) {
00481 arr_debug_x.anx(x+2); arr_debug_y.anx(y-1);
00482 }
00483 }
00484
00485 double f_de_x;
00486
00487 if ( tipo_situacion == 2 ) {
00488 m = r.y / r.x;
00489 b = Rayo->origen.y - m*Rayo->origen.x;
00490 for ( x = 1; x < _x_tam - 2; x++ ) {
00491 f_de_x = m * index2coord_x(x) + b;
00492 y = coord2index_y(f_de_x);
00493 if ( y >= 1 && y < _y_tam - 2 ) {
00494 arr_debug_x.anx(x); arr_debug_y.anx(y);
00495 }
00496 if ( y >= 2 && y < _y_tam - 2 ) {
00497 arr_debug_x.anx(x); arr_debug_y.anx(y-1);
00498 }
00499 if ( y >= 3 && y < _y_tam - 2 ) {
00500 arr_debug_x.anx(x); arr_debug_y.anx(y-2);
00501 }
00502 }
00503 }
00504
00505
00506 double f_de_y;
00507
00508 if ( tipo_situacion == 3 ) {
00509 m = r.x / r.y;
00510 b = Rayo->origen.x - m*Rayo->origen.y;
00511 for ( y = 1; y < _y_tam - 2; y++ ) {
00512 f_de_y = m * index2coord_y(y) + b;
00513 x = coord2index_x(f_de_y);
00514 if ( x >= 0 && x < _x_tam - 3 ) {
00515 arr_debug_x.anx(x+1); arr_debug_y.anx(y);
00516 }
00517 if ( x >= -1 && x < _x_tam - 4 ) {
00518 arr_debug_x.anx(x+2); arr_debug_y.anx(y);
00519 }
00520 if ( x >= -2 && x < _x_tam - 5 ) {
00521 arr_debug_x.anx(x+3); arr_debug_y.anx(y);
00522 }
00523 }
00524 }
00525
00526
00527
00528
00529 double T = 0, distancia_minima = INFINITO, t;
00530 VECTOR p, n;
00531
00532 #ifdef NONONO
00533
00534 for ( x = 1; x < _x_tam - 2; x++ ) {
00535 for ( y = 1; y < _y_tam - 2; y++ ) {
00536 t = interseccion_celda(Rayo, p, n, x, y);
00537 if ( (t > EPSILON) && (t < distancia_minima) ) {
00538 distancia_minima = t;
00539 T = t;
00540 punto = p;
00541 normal = n;
00542 }
00543 }
00544 }
00545 #endif
00546
00547
00548
00549
00550 int i;
00551
00552 for ( i = 0; i < arr_debug_x.tam(); i++ ) {
00553 x = arr_debug_x[i];
00554 y = arr_debug_y[i];
00555 t = interseccion_celda(Rayo, p, n, x, y);
00556 if ( (t > EPSILON) && (t < distancia_minima) ) {
00557 distancia_minima = t;
00558 T = t;
00559 punto = p;
00560 normal = n;
00561 }
00562 }
00563
00564
00565 return T;
00566 }
00567
00568
00569
00570
00571