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
00038 #include "lista.cc"
00039 #endif
00040
00041 class TERRENO : public GEOMETRIA
00042 {
00043 private:
00044
00045 PALETA *Paleta;
00046 IMAGEN *imagen;
00047 long int _x_tam;
00048 long int _y_tam;
00049 long int vertices_tam;
00050 VERTICE_GL *vertices_arr;
00051 GLubyte *colores_arr;
00052 GLuint **TIras_arr;
00053
00054 VECTOR _min;
00055 VECTOR _max;
00056 double _escala;
00057 double _factor_exageracion;
00058
00059
00060 LISTA <int> arr_debug_x;
00061 LISTA <int> arr_debug_y;
00062 #ifdef DEBUG_TERRENO
00063 COLOR color_debug;
00064 #endif
00065
00066
00067
00068
00069 #ifdef GL_ENABLED
00070 void pintar_tiras_gl(void);
00071 void pintar_tirasv_gl(void);
00072 #endif
00073
00074
00075 void calcular_color(float z, float *r, float *g, float *b);
00076 VECTOR calcule_subnormal(int x1, int y1, int x2, int y2, int x3, int y3);
00077 VECTOR calcule_normal(int x, int y);
00078 double interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal,
00079 int x, int y);
00080 int coord2index_x(double x_coord);
00081 int coord2index_y(double y_coord);
00082
00083 public:
00084
00085 TERRENO(GLOBAL_DEM *Fuente,
00086 long int origen_x, long int origen_y, long int xtam, long int ytam,
00087 double escala, double exageracion);
00088 virtual ~TERRENO();
00089
00090
00091 double interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal);
00092
00093
00094 void anexar_textura(IMAGEN *img);
00095 int clasificar_punto(VECTOR p);
00096 virtual GEOMETRIA *crear_copia(void);
00097
00098 void minmax(VECTOR *min, VECTOR *max);
00099
00100 #ifdef GL_ENABLED
00101 void
00102 pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material, CAMARA *Camara);
00103 #endif
00104 void pintar_povray(FILE *fd);
00105 void pintar_aqz(FILE *fd);
00106
00107
00108 void set_paleta(PALETA *P);
00109
00110 BOOLEAN seleccionar(RAYO *Rayito, int *i, int *j);
00111 double index2coord_x(int i);
00112 double index2coord_y(int j);
00113 void elim(void);
00114 };
00115
00116 inline int
00117 TERRENO::coord2index_x(double x_coord)
00123 {
00124 int i;
00125
00126 i = (int)(x_coord / (1000*_escala)) - 1;
00127
00128 return i;
00129 }
00130
00131 inline int
00132 TERRENO::coord2index_y(double y_coord)
00138 {
00139 int j;
00140
00141
00142 j = (int)(y_coord / (1000 * _escala)) + _y_tam - 1 - 2;
00143
00144 return j;
00145 }
00146
00147 inline double
00148 TERRENO::index2coord_x(int i)
00152 {
00153 double x;
00154
00155
00156 x = vertices_arr[i].x;
00157
00158 return x;
00159 }
00160
00161 inline double
00162 TERRENO::index2coord_y(int j)
00166 {
00167 double y;
00168
00169
00170 y = vertices_arr[j*_x_tam].y;
00171
00172 return y;
00173 }
00174
00175 inline double
00176 TERRENO::interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal,
00177 int x, int y)
00191 {
00192
00193 VECTOR a, b, c, d;
00194
00195 a.x = index2coord_x(x);
00196 a.y = index2coord_y(y);
00197 a.z = vertices_arr[y*_x_tam + x].z;
00198
00199 b.x = index2coord_x(x);
00200 b.y = index2coord_y(y+1);
00201 b.z = vertices_arr[(y+1)*_x_tam + x].z;
00202
00203 c.x = index2coord_x(x+1);
00204 c.y = index2coord_y(y);
00205 c.z = vertices_arr[y*_x_tam + x+1].z;
00206
00207 d.x = index2coord_x(x+1);
00208 d.y = index2coord_y(y+1);
00209 d.z = vertices_arr[(y+1)*_x_tam + x+1].z;
00210
00211
00212 VECTOR O = Rayo->origen;
00213 VECTOR l = Rayo->direccion;
00214 double T = 0;
00215 double pp, pq, m;
00216 double D;
00217
00218 l.normalizar();
00219
00220
00221 double t1 = INFINITO;
00222 VECTOR p1, n1;
00223
00224 n1 = (a-b).producto_cruz(d-b);
00225 n1.normalizar();
00226 D = n1.x*d.x + n1.y*d.y + n1.z*d.z;
00227
00228 pp = n1.producto_punto(l);
00229 pq = n1.producto_punto(O-b);
00230 if ( pp < -EPSILON && pq > EPSILON ||
00231 pp > EPSILON && pq < -EPSILON ) {
00232
00233
00234 t1 = (-1) * ( (n1.x*O.x + n1.y*O.y + n1.z*O.z - D) /
00235 (n1.x*l.x + n1.y*l.y + n1.z*l.z) );
00236 p1 = O + l * t1;
00237 m = (d.y - a.y)/(d.x - a.x);
00238 if ( p1.x >= a.x-EPSILON && p1.y <= d.y+EPSILON &&
00239 p1.y >= m*(p1.x - a.x) + a.y - EPSILON ) {
00240
00241 normal = n1;
00242 punto = p1;
00243 T = t1;
00244 }
00245 else {
00246 t1 = INFINITO;
00247 }
00248 }
00249
00250
00251 double t2 = 0.0;
00252 VECTOR p2, n2;
00253
00254 n2 = (d-c).producto_cruz(a-c);
00255 n2.normalizar();
00256 D = n2.x*d.x + n2.y*d.y + n2.z*d.z;
00257
00258 pp = n2.producto_punto(l);
00259 pq = n2.producto_punto(O-c);
00260 if ( pp < -EPSILON && pq > EPSILON ||
00261 pp > EPSILON && pq < -EPSILON ) {
00262
00263
00264 t2 = (-1) * ( (n2.x*O.x + n2.y*O.y + n2.z*O.z - D) /
00265 (n2.x*l.x + n2.y*l.y + n2.z*l.z) );
00266 p2 = O + l * t2;
00267 m = (d.y - a.y)/(d.x - a.x);
00268 if ( p2.x <= d.x+EPSILON && p2.y >= c.y-EPSILON &&
00269 p2.y <= m*(p2.x - a.x) + a.y + EPSILON ) {
00270
00271 if ( t2 <= t1 + EPSILON ) {
00272 normal = n2;
00273 punto = p2;
00274 T = t2;
00275 }
00276 }
00277 }
00278
00279
00280 return T;
00281 }
00282
00283 inline double
00284 TERRENO::interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal)
00295 {
00296
00297
00298
00299 int tipo_situacion = 0;
00300 VECTOR r;
00301 double m=0;
00302 double b=0;
00303
00304 arr_debug_x.elim();
00305 arr_debug_y.elim();
00306
00307
00308 r = Rayo->direccion;
00309 r.normalizar();
00310 r.z = 0;
00311
00312 if ( r.norma() < 5*EPSILON ) {
00313 tipo_situacion = 1;
00314 #ifdef DEBUG_TERRENO
00315 color_debug.r = 1; color_debug.g = 0; color_debug.b = 0;
00316 #endif
00317 }
00318
00319
00320 if ( !tipo_situacion ) {
00321 r.normalizar();
00322 if ( fabs(r.x) >= fabs(r.y) ) {
00323 tipo_situacion = 2;
00324 #ifdef DEBUG_TERRENO
00325 color_debug.r = 0; color_debug.g = 1; color_debug.b = 1;
00326 #endif
00327 }
00328 else {
00329 tipo_situacion = 3;
00330 #ifdef DEBUG_TERRENO
00331 color_debug.r = 1; color_debug.g = 0; color_debug.b = 1;
00332 #endif
00333 }
00334 }
00335
00336
00337 int x, y;
00338
00339 if ( tipo_situacion == 1 ) {
00340 x = coord2index_x(Rayo->origen.x);
00341 y = coord2index_y(Rayo->origen.y);
00342 if ( x >= -1 && x <= _x_tam - 3 &&
00343 y > 0 && y <= _y_tam ) {
00344 arr_debug_x.anx(x+2); arr_debug_y.anx(y-1);
00345 }
00346 }
00347
00348 double f_de_x;
00349
00350 if ( tipo_situacion == 2 ) {
00351 m = r.y / r.x;
00352 b = Rayo->origen.y - m*Rayo->origen.x;
00353 for ( x = 1; x < _x_tam - 2; x++ ) {
00354 f_de_x = m * index2coord_x(x) + b;
00355 y = coord2index_y(f_de_x);
00356 if ( y >= 1 && y < _y_tam - 2 ) {
00357 arr_debug_x.anx(x); arr_debug_y.anx(y);
00358 }
00359 if ( y >= 2 && y < _y_tam - 2 ) {
00360 arr_debug_x.anx(x); arr_debug_y.anx(y-1);
00361 }
00362 if ( y >= 3 && y < _y_tam - 2 ) {
00363 arr_debug_x.anx(x); arr_debug_y.anx(y-2);
00364 }
00365 }
00366 }
00367
00368
00369 double f_de_y;
00370
00371 if ( tipo_situacion == 3 ) {
00372 m = r.x / r.y;
00373 b = Rayo->origen.x - m*Rayo->origen.y;
00374 for ( y = 1; y < _y_tam - 2; y++ ) {
00375 f_de_y = m * index2coord_y(y) + b;
00376 x = coord2index_x(f_de_y);
00377 if ( x >= 0 && x < _x_tam - 3 ) {
00378 arr_debug_x.anx(x+1); arr_debug_y.anx(y);
00379 }
00380 if ( x >= -1 && x < _x_tam - 4 ) {
00381 arr_debug_x.anx(x+2); arr_debug_y.anx(y);
00382 }
00383 if ( x >= -2 && x < _x_tam - 5 ) {
00384 arr_debug_x.anx(x+3); arr_debug_y.anx(y);
00385 }
00386 }
00387 }
00388
00389
00390
00391
00392 double T = 0, distancia_minima = INFINITO, t;
00393 VECTOR p, n;
00394
00395 #ifdef NONONO
00396
00397 for ( x = 1; x < _x_tam - 2; x++ ) {
00398 for ( y = 1; y < _y_tam - 2; y++ ) {
00399 t = interseccion_celda(Rayo, p, n, x, y);
00400 if ( (t > EPSILON) && (t < distancia_minima) ) {
00401 distancia_minima = t;
00402 T = t;
00403 punto = p;
00404 normal = n;
00405 }
00406 }
00407 }
00408 #endif
00409
00410
00411
00412
00413 int i;
00414
00415 for ( i = 0; i < arr_debug_x.tam(); i++ ) {
00416 x = arr_debug_x[i];
00417 y = arr_debug_y[i];
00418 t = interseccion_celda(Rayo, p, n, x, y);
00419 if ( (t > EPSILON) && (t < distancia_minima) ) {
00420 distancia_minima = t;
00421 T = t;
00422 punto = p;
00423 normal = n;
00424 }
00425 }
00426
00427
00428 return T;
00429 }
00430
00431
00432
00433
00434