00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "core/cosas/espacio.h"
00024
00025 #ifdef VEL_ROSITA
00026 #include "core/cosas/e_abierto.h"
00027 #endif
00028
00029 #include "arreglo.cc"
00030 #include "lista.cc"
00031 #include "toolkits/util/regexp.h"
00032
00033 #include <ctype.h>
00034 #include <string.h>
00035 #include <stdlib.h>
00036
00037
00038
00039
00040
00041 #define ESPERO(tipo, msg) \
00042 if ( tipo_token != (tipo) ) { \
00043 fprintf(stderr, "<ESPACIO_ABIERTO> ERROR: Esperaba %s y recibi [%s].\n", \
00044 (msg), cad); fflush(stderr); return FALSE; \
00045 }
00046
00047
00048 #define GENERAR_ESQUINAS(e) \
00049 (e)[0].x = mmi.x; (e)[0].y = mmi.y; (e)[0].z = mmi.z; \
00050 (e)[1].x = mmx.x; (e)[1].y = mmi.y; (e)[1].z = mmi.z; \
00051 (e)[2].x = mmi.x; (e)[2].y = mmi.y; (e)[2].z = mmx.z; \
00052 (e)[3].x = mmx.x; (e)[3].y = mmi.y; (e)[3].z = mmx.z; \
00053 (e)[4].x = mmi.x; (e)[4].y = mmx.y; (e)[4].z = mmi.z; \
00054 (e)[5].x = mmx.x; (e)[5].y = mmx.y; (e)[5].z = mmi.z; \
00055 (e)[6].x = mmi.x; (e)[6].y = mmx.y; (e)[6].z = mmx.z; \
00056 (e)[7].x = mmx.x; (e)[7].y = mmx.y; (e)[7].z = mmx.z;
00057
00058
00059
00060
00061
00062 ESPACIO_ABIERTO::ESPACIO_ABIERTO() : ESPACIO(), arr_parches(1)
00063 {
00064 target_xpos = 12654;
00065 target_ypos = 10190;
00066 target_xtam = 250;
00067 target_ytam = 250;
00068 Dem = NULL;
00069 Paleta = NULL;
00070 preprocesada = FALSE;
00071 _escala = 1.0/10000.0;
00072 _exageracion = 1;
00073 _tipo_de_cosa = CC_ESPACIO_ABIERTO;
00074 }
00075
00076 ESPACIO_ABIERTO::~ESPACIO_ABIERTO()
00077 {
00078 int i;
00079
00080 for ( i = 0; i < arr_parches.tam(); i++ ) {
00081 delete arr_parches[i];
00082 }
00083 arr_parches.elim();
00084 if ( Paleta ) delete Paleta;
00085 if ( Medio ) delete Medio;
00086 Medio = FALSE;
00087 }
00088
00089 BOOLEAN
00090 ESPACIO_ABIERTO::leer_espacio(TOKENIZADOR *Sabiondo, LISTA <GLOBAL_DEM *> *Lst)
00091 {
00092 char cad[1000];
00093 int tipo_token = TK_DESCONOCIDO, pos, i;
00094 BOOLEAN con_mi_color = FALSE;
00095 EXPRESION_REGULAR tmp;
00096
00097
00098 pos = 1;
00099 while ( tipo_token != TK_CERRAR) {
00100 tipo_token = Sabiondo->siguiente_token(cad);
00101 switch ( pos ) {
00102 case 1:
00103 ESPERO(TK_CADENA, "una cadena");
00104 if ( strlen(cad) > MAX_CAD-1 ) cad[MAX_CAD-1] = '\0';
00105 des_comille(cad);
00106 set_nombre(cad);
00107 pos++;
00108 break;
00109 case 2: ESPERO(TK_ABRIR, "\"{\""); pos++; break;
00110 default:
00111 if ( tipo_token == TK_CERRAR ) break;
00112 ESPERO(TK_IDENTIFICADOR, "un identificador (3)");
00113 if ( strcmp(cad, "espacio") == 0 ) {
00114 tipo_token = Sabiondo->siguiente_token(cad);
00115 ESPERO(TK_CADENA, "una cadena");
00116
00117
00118
00119 }
00120 else if ( strcmp(cad, "paleta") == 0 ) {
00121 tipo_token = Sabiondo->siguiente_token(cad);
00122 ESPERO(TK_CADENA, "una cadena (archivo de paleta)");
00123 des_comille(cad);
00124 Paleta = new PALETA();
00125 if ( !Paleta || !Paleta->leer(Sabiondo) ) {
00126 return FALSE;
00127 }
00128 }
00129 else if ( strcmp(cad, "escala") == 0 ) {
00130 tipo_token = Sabiondo->siguiente_token(cad);
00131 ESPERO(TK_CADENA, "una cadena (expresion regular)");
00132 des_comille(cad);
00133 tmp.init(cad);
00134 _escala = tmp.evaluar(0);
00135 }
00136 else if ( strcmp(cad, "exageracion") == 0 ) {
00137 tipo_token = Sabiondo->siguiente_token(cad);
00138 ESPERO(TK_CADENA, "una cadena (expresion regular)");
00139 des_comille(cad);
00140 tmp.init(cad);
00141 _exageracion = tmp.evaluar(0);
00142 }
00143 else if ( strcmp(cad, "xpos") == 0 ) {
00144 tipo_token = Sabiondo->siguiente_token(cad);
00145 ESPERO(TK_NUMERO, "un numero");
00146 target_xpos = atol(cad);
00147 }
00148 else if ( strcmp(cad, "ypos") == 0 ) {
00149 tipo_token = Sabiondo->siguiente_token(cad);
00150 ESPERO(TK_NUMERO, "un numero");
00151 target_ypos = atol(cad);
00152 }
00153 else if ( strcmp(cad, "xtam") == 0 ) {
00154 tipo_token = Sabiondo->siguiente_token(cad);
00155 ESPERO(TK_NUMERO, "un numero");
00156 target_xtam = atol(cad);
00157 }
00158 else if ( strcmp(cad, "ytam") == 0 ) {
00159 tipo_token = Sabiondo->siguiente_token(cad);
00160 ESPERO(TK_NUMERO, "un numero");
00161 target_ytam = atol(cad);
00162 }
00163 else if ( strcmp(cad, "dem") == 0 ) {
00164 tipo_token = Sabiondo->siguiente_token(cad);
00165 ESPERO(TK_CADENA, "una cadena");
00166 des_comille(cad);
00167 for ( i = 0; i < Lst->tam(); i++ ) {
00168 if ( strcmp((*Lst)[i]->nombre(), cad) == 0 ) {
00169 Dem = (*Lst)[i];
00170 break;
00171 }
00172 }
00173 }
00174 else if ( strcmp(cad, "MEDIO") == 0 ) {
00175 if ( !Medio->leer(Sabiondo) ) {
00176 fprintf(stderr,
00177 "<ESPACIO_ABIERTO> ERROR leyendo el MEDIO.\n");
00178 fflush(stderr);
00179 return FALSE;
00180 }
00181 }
00182 else if (
00183 !leer_basico(Sabiondo, cad, &con_mi_color) ||
00184 !leer_rigida(Sabiondo, cad)
00185 ) return FALSE;
00186 ;
00187 break;
00188 }
00189 }
00190
00191
00192 if ( !con_mi_color ) _color = Material->difusa();
00193
00194 if ( !Dem ) {
00195 fprintf(stderr, "<ESPACIO_ABIERTO> ERROR - "
00196 "No se tengo un DEM de donde leer altimetria!\n");
00197 fflush(stderr);
00198 return FALSE;
00199 }
00200
00201 resolver_tensor_de_inercia();
00202 init();
00203 return TRUE;
00204 }
00205
00206 void
00207 ESPACIO_ABIERTO::init(void)
00213 {
00214 PARCHE_TERRENO *P;
00215 long int ancho_x = 20, ancho_y = 20;
00216 long int xtam = target_xtam+1;
00217 long int ytam = target_ytam+1;
00218 long int x, y, dx, dy;
00219
00220 printf("Procesando un terreno con %ld parches: \n[",
00221 ((xtam-1)/ancho_x)*((ytam-1)/ancho_y));
00222 fflush(stdout);
00223 for ( x = 0; x < xtam-1; x += ancho_x ) {
00224 dx = ancho_x;
00225 if ( x + dx > xtam-1 ) dx = xtam - x - 1;
00226 for ( y = 0; y < ytam-1; y += ancho_y ) {
00227 dy = ancho_y;
00228 if ( y + dy > ytam-1 ) dy = ytam - y - 1;
00229 P = new PARCHE_TERRENO;
00230 P->Geometria =
00231 new TERRENO(Dem, target_xpos+x, target_ypos+y, dx+3, dy+3,
00232 _escala, _exageracion);
00233 if ( Paleta ) {
00234 P->Geometria->set_paleta(Paleta);
00235 }
00236 arr_parches.anx(P);
00237 P->delta_x = (double)x/(0.001/_escala);
00238 P->delta_y = -(double)y/(0.001/_escala);
00239 printf("."); fflush(stdout);
00240 }
00241 }
00242 printf("]\nOk!\n"); fflush(stdout);
00243
00244 preprocesada = TRUE;
00245 }
00246
00247 #ifdef GL_ENABLED
00248 void
00249 ESPACIO_ABIERTO::pintar_gl(CALIDAD_VISUAL *Calidad, CAMARA *Camara)
00250 {
00251 if ( !preprocesada ) init();
00252 Medio->activar_gl(Calidad, Camara);
00253
00254
00255
00256
00257 VECTOR centro_de_masa(0, 0, 0);
00258 MATRIZ_4x4 R;
00259 VECTOR p = posicion_absoluta(centro_de_masa);
00260
00261 glPushMatrix();
00262 glTranslatef((float)p.x, (float)p.y, (float)p.z);
00263 R.importar_quaternion(orientacion_absoluta());
00264 R.cargar_gl();
00265
00266
00267 int i, j;
00268 MATERIAL m;
00269 VECTOR mmi(0, 0, 0), mmx(1, 1, 1);
00270 VECTOR esquinas[8];
00271 GEOMETRIA *G;
00272
00273 glTranslated(-((double)target_xtam/(0.001/_escala))/2,
00274 ((double)target_ytam/(0.001/_escala))/2, 0);
00275 for ( i = 0; i < arr_parches.tam(); i++ ) {
00276 G = arr_parches[i]->Geometria;
00277 G->minmax(&mmi, &mmx);
00278 GENERAR_ESQUINAS(esquinas);
00279 for ( j = 0; j < 8; j++ ) {
00280 esquinas[j].x -= ((double)target_xtam/(0.001/_escala))/2;
00281 esquinas[j].x += arr_parches[i]->delta_x;
00282 esquinas[j].y += ((double)target_ytam/(0.001/_escala))/2;
00283 esquinas[j].y += arr_parches[i]->delta_y;
00284 esquinas[j] = posicion_absoluta(esquinas[j]);
00285 }
00286 if ( !Camara->minmax_visible(esquinas) ) continue;
00287 glPushMatrix();
00288 glTranslated(arr_parches[i]->delta_x, arr_parches[i]->delta_y, 0);
00289 G->pintar_gl(Calidad, &m, Camara);
00290 glPopMatrix();
00291 }
00292 glPopMatrix();
00293
00294
00295
00296 Medio->post_pintar_gl(Calidad, Camara);
00297 }
00298 #endif // GL_ENABLED
00299
00300 double
00301 ESPACIO_ABIERTO::altura_espacio(VECTOR p)
00302 {
00303
00304 VECTOR mmi(0, 0, 0), mmx(1, 1, 1);
00305 double max_z = -INFINITO;
00306 int i;
00307
00308 for ( i = 0; i < arr_parches.tam(); i++ ) {
00309 arr_parches[i]->Geometria->minmax(&mmi, &mmx);
00310 if ( mmx.z > max_z ) max_z = mmx.z;
00311 }
00312
00313
00314 double a;
00315 RAYO r;
00316 VECTOR d, n;
00317
00318 r.origen = p;
00319 r.origen.z = max_z + 1;
00320 r.direccion.x = 0;
00321 r.direccion.y = 0;
00322 r.direccion.z = -1;
00323
00324 a = interseccion(&r, &d, &n);
00325 if ( a < EPSILON ) return 0;
00326 return p.z - d.z;
00327 }
00328
00329 void
00330 ESPACIO_ABIERTO::anexar_objetos_rayables(
00331 ARREGLO <OBJETO_RAYABLE *> & arr_objetos)
00332 {
00333 int i;
00334 OBJETO_RAYABLE *O = NULL;
00335 VECTOR p;
00336 VECTOR centro_de_masa(0, 0, 0);
00337
00338 p = posicion_absoluta(centro_de_masa);
00339 p.x -= ( (double)target_xtam/(0.001/_escala) ) / 2;
00340 p.y += ( (double)target_ytam/(0.001/_escala) ) / 2;
00341 for ( i = 0; i < arr_parches.tam(); i++ ) {
00342 O = new OBJETO_RAYABLE;
00343 O->Geometria = arr_parches[i]->Geometria;
00344
00345 O->posicion = p;
00346 O->posicion.x += arr_parches[i]->delta_x;
00347 O->posicion.y += arr_parches[i]->delta_y;
00348 O->R.importar_quaternion(orientacion_absoluta());
00349
00350 O->R_i = O->R.inversa();
00351 O->ambiente = material()->ambiente();
00352 O->especular = material()->especular();
00353 O->phong_exp = material()->phong_exp();
00354 O->phong_coef = material()->phong_coef();
00355 O->difusa = color();
00356
00357 arr_objetos.anx(O);
00358 }
00359 }
00360
00361 double
00362 ESPACIO_ABIERTO::interseccion(RAYO *Rayo, VECTOR *Punto, VECTOR *Normal)
00363 {
00364 int i;
00365 double distancia_minima = INFINITO, d = 0, T = 0;
00366 MATRIZ_4x4 R, R_i;
00367 VECTOR po, pf, pff;
00368 VECTOR n(0, 0, 0);
00369 VECTOR p, nn;
00370 RAYO mi_rayo;
00371
00372 R.importar_quaternion(orientacion_absoluta());
00373 R_i = R.inversa();
00374 po = posicion_absoluta(n);
00375 po.x -= ( (double)target_xtam/(0.001/_escala) ) / 2;
00376 po.y += ( (double)target_ytam/(0.001/_escala) ) / 2;
00377
00378 for ( i = 0; i < arr_parches.tam(); i++ ) {
00379
00380 pf = po;
00381 pf.x += arr_parches[i]->delta_x;
00382 pf.y += arr_parches[i]->delta_y;
00383
00384 mi_rayo.origen = Rayo->origen - pf;
00385 mi_rayo.origen = R_i * mi_rayo.origen;
00386 mi_rayo.direccion = R_i * Rayo->direccion;
00387 mi_rayo.direccion.normalizar();
00388
00389
00390 T = arr_parches[i]->Geometria->interseccion(&mi_rayo, p, nn);
00391 if ( (T > EPSILON) && (T < distancia_minima) ) {
00392 distancia_minima = T;
00393 d = T;
00394 pff = pf;
00395 (*Punto) = p;
00396 (*Normal) = nn;
00397 }
00398 }
00399
00400 if ( d > EPSILON ) {
00401
00402 (*Punto) = R * (*Punto);
00403 (*Punto) = (*Punto) + pff;
00404 (*Normal) = R * (*Normal);
00405 }
00406 return d;
00407 }
00408
00409
00410
00411
00412