00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "core/cosas/cosa.h"
00023
00024 #include <ctype.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028
00029
00030
00031
00032
00033 #define VERIFICAR(m) \
00034 if ( !(m) ) { \
00035 fprintf(stderr, "<TELA> - ERROR FATAL: Memoria insuficiente!\n"); \
00036 fflush(stderr); \
00037 return FALSE; \
00038 }
00039
00040 #define ESPERO(tipo, msg) \
00041 if ( tipo_token != (tipo) ) { \
00042 fprintf(stderr, "<TELA> ERROR: Esperaba %s y recibi [%s].\n", \
00043 (msg), cad); fflush(stderr); return FALSE; \
00044 }
00045
00046
00047
00048
00049
00050 TELA::TELA() : COSA_FLEXIBLE()
00051 {
00052 _tipo_de_cosa = CC_TELA;
00053 x_tam = 0;
00054 y_tam = 0;
00055 Arr_masas = NULL;
00056 Resortes1 = NULL;
00057 Resortes2 = NULL;
00058 Resortes3 = NULL;
00059 plantilla[0] = new RESORTE;
00060 plantilla[1] = new RESORTE;
00061 plantilla[2] = new RESORTE;
00062 Textura = NULL;
00063 Superficie = NULL;
00064 recien_simulado = FALSE;
00065 }
00066
00067 TELA::~TELA()
00068 {
00069 if ( Arr_masas ) delete Arr_masas;
00070 if ( Resortes1 ) delete Resortes1;
00071 if ( Resortes2 ) delete Resortes2;
00072 if ( Resortes3 ) delete Resortes3;
00073 if ( _nombre_padre ) delete _nombre_padre;
00074 if ( Textura ) delete Textura;
00075 }
00076
00077
00078
00079 GEOMETRIA *
00080 TELA::geometria(void)
00081 {
00082 return NULL;
00083 }
00084
00085 BOOLEAN
00086 TELA::precalcular_resortes(void)
00087 {
00088 int pos, x, y;
00089
00090
00091 num_resortes1 = (x_tam-1)*(y_tam) + (x_tam)*(y_tam-1);
00092 Resortes1 = new RESORTE[num_resortes1];
00093 VERIFICAR(Resortes1);
00094
00095
00096 for ( x = 0, pos = 0; x < x_tam - 1; x++ ) {
00097 for ( y = 0; y < y_tam; y++, pos++ ) {
00098
00099 Resortes1[pos] = *(plantilla[0]);
00100 Resortes1[pos].Extremo1 = &Arr_masas[x + y * x_tam];
00101 Resortes1[pos].Extremo2 = &Arr_masas[(x+1) + y * x_tam];
00102 }
00103 }
00104
00105
00106 for ( x = 0; x < x_tam; x++ ) {
00107 for ( y = 0; y < y_tam - 1; y++, pos++ ) {
00108
00109 Resortes1[pos] = *(plantilla[0]);
00110 Resortes1[pos].Extremo1 = &Arr_masas[y * x_tam + x];
00111 Resortes1[pos].Extremo2 = &Arr_masas[(y+1) * x_tam + x];
00112 }
00113 }
00114
00115
00116 num_resortes2 = 2*(x_tam-1)*(y_tam-1);
00117 Resortes2 = new RESORTE[num_resortes2];
00118 VERIFICAR(Resortes2);
00119
00120 for ( x = 0, pos = 0; x < x_tam - 1; x++ ) {
00121 for ( y = 0; y < y_tam - 1; y++, pos++ ) {
00122
00123 Resortes2[pos] = *(plantilla[1]);
00124 Resortes2[pos].Extremo1 = &Arr_masas[y * x_tam + x];
00125 Resortes2[pos].Extremo2 = &Arr_masas[(y+1) * x_tam + (x+1)];
00126 pos++;
00127
00128 Resortes2[pos] = *(plantilla[1]);
00129 Resortes2[pos].Extremo1 = &Arr_masas[(y+1) * x_tam + x];
00130 Resortes2[pos].Extremo2 = &Arr_masas[y * x_tam + (x+1)];
00131 }
00132 }
00133
00134
00135
00136 return TRUE;
00137 }
00138
00139 void
00140 TELA::minmax(VECTOR *min, VECTOR *max)
00141 {
00142 int i;
00143 VECTOR p, nada(0, 0, 0);
00144
00145 min->x = INFINITO;
00146 min->y = INFINITO;
00147 min->z = INFINITO;
00148 max->x = -INFINITO;
00149 max->y = -INFINITO;
00150 max->z = -INFINITO;
00151
00152 for ( i = 0; i < x_tam * y_tam; i++ ) {
00153 p = Arr_masas[i].posicion_absoluta(nada);
00154 if ( p.x < min->x ) min->x = p.x;
00155 if ( p.y < min->y ) min->y = p.y;
00156 if ( p.z < min->z ) min->z = p.z;
00157 if ( p.x > max->x ) max->x = p.x;
00158 if ( p.y > max->y ) max->y = p.y;
00159 if ( p.z > max->z ) max->z = p.z;
00160 }
00161 }
00162
00163 #ifdef GL_ENABLED
00164 void
00165 TELA::pintar_gl(CALIDAD_VISUAL *Calidad, CAMARA *Camara)
00172 {
00173 glPushMatrix();
00174
00175
00176 int i;
00177
00178 if ( Calidad->con_bordes ) {
00179
00180 glDisable(GL_LIGHTING);
00181 glColor3d(1, 1, 1);
00182 for ( i = 0; i < x_tam * y_tam; i++ ) {
00183 Arr_masas[i].pintar_gl(Calidad, Camara);
00184 }
00185 if ( !Calidad->con_caras ) {
00186 for ( i = 0; i < num_resortes1; i++ ) {
00187 Resortes1[i].pintar_gl(Calidad);
00188 }
00189 for ( i = 0; i < num_resortes2; i++ ) {
00190 Resortes2[i].pintar_gl(Calidad);
00191 }
00192 }
00193 }
00194
00195
00196 if ( Calidad->con_caras ) {
00197
00198 if ( recien_simulado ) {
00199 VERTICE_GL *V;
00200 VECTOR p, nada(0, 0, 0);
00201 long int n, i;
00202 int x, y;
00203
00204 Superficie->get_vertices(&V, &n);
00205 for ( y = 0; y < y_tam; y++ ) {
00206 for ( x = 0; x < x_tam; x++ ) {
00207 p = Arr_masas[x + y * x_tam].posicion_absoluta(nada);
00208 i = x_tam*y + x;
00209 V[i].x = (float)p.x;
00210 V[i].y = (float)p.y;
00211 V[i].z = (float)p.z;
00212 }
00213 }
00214 Superficie->init();
00215 recien_simulado = FALSE;
00216 }
00217
00218 Material->set_doble_cara(TRUE);
00219 Superficie->pintar_gl(Calidad, Material, Camara);
00220 }
00221
00222
00223 glDisable(GL_TEXTURE_2D);
00224 glPopMatrix();
00225 }
00226 #endif
00227
00228 void
00229 TELA::pintar_povray(FILE *fd)
00232 {
00233 fprintf(fd, "// Falta TELA!\n");
00234 }
00235
00236
00237
00238 BOOLEAN
00239 TELA::leer_resortes(TOKENIZADOR *Sabiondo, int tipo)
00240 {
00241 char cad[1000];
00242 int tipo_token = TK_DESCONOCIDO, pos;
00243
00244 pos = 2;
00245 while ( tipo_token != TK_CERRAR ) {
00246 tipo_token = Sabiondo->siguiente_token(cad);
00247 switch ( pos ) {
00248 case 2: ESPERO(TK_ABRIR, "\"{\""); pos++; break;
00249 default:
00250 if ( tipo_token == TK_CERRAR ) break;
00251 ESPERO(TK_IDENTIFICADOR, "un identificador (1)");
00252 if ( strcmp(cad, "ks") == 0 ) {
00253 tipo_token = Sabiondo->siguiente_token(cad);
00254 ESPERO(TK_NUMERO, "el valor de ks");
00255 plantilla[tipo]->ks = atof(cad);
00256 }
00257 else if ( strcmp(cad, "kd") == 0 ) {
00258 tipo_token = Sabiondo->siguiente_token(cad);
00259 ESPERO(TK_NUMERO, "el valor de kd");
00260 plantilla[tipo]->kd = atof(cad);
00261 }
00262 else if ( strcmp(cad, "l") == 0 ) {
00263 tipo_token = Sabiondo->siguiente_token(cad);
00264 ESPERO(TK_NUMERO, "el valor de l");
00265 plantilla[tipo]->l = atof(cad);
00266 }
00267 ;
00268 break;
00269 }
00270 }
00271
00272 return TRUE;
00273 }
00274
00275 BOOLEAN
00276 TELA::leer_malla(TOKENIZADOR *Sabiondo)
00277 {
00278 char cad[1000];
00279 int tipo_token = TK_DESCONOCIDO, pos;
00280 VECTOR posicion, velocidad;
00281 long accum = 0;
00282 BOOLEAN bandera_fijacion = FALSE;
00283
00284 pos = 1;
00285 while ( tipo_token != TK_CERRAR ) {
00286 tipo_token = Sabiondo->siguiente_token(cad);
00287 switch ( pos ) {
00288 case 1:
00289
00290 ESPERO(TK_VECTOR_INICIO, "Un tamanno en X para la tela");
00291 x_tam = atoi(&cad[1]);
00292 tipo_token = Sabiondo->siguiente_token(cad);
00293 ESPERO(TK_VECTOR_FIN, "Un tamanno en Y para la tela");
00294 cad[strlen(cad) - 1] = '\0';
00295 y_tam = atoi(cad);
00296
00297 if ( y_tam < 2 || x_tam < 2 ) {
00298 fprintf(stderr,
00299 "<TELA> - ERROR: No tiene sentido ninguna TELA de menos "
00300 "de 2x2 de tamanno!\n");
00301 fflush(stderr);
00302 return FALSE;
00303 }
00304
00305 Arr_masas = new MASA_PUNTUAL[x_tam * y_tam];
00306 VERIFICAR(Arr_masas);
00307 pos++;
00308 break;
00309 case 2: ESPERO(TK_ABRIR, "\"{\""); pos++; break;
00310 default:
00311 if ( tipo_token == TK_CERRAR ) break;
00312
00313 ESPERO(TK_ABRIR, "\"{\", como el inicio de una MASA_PUNTUAL");
00314
00315 if ( accum >= ((long)x_tam * (long)y_tam) ) {
00316 fprintf(stderr, "<TELA> Error: "
00317 "Hay mas de %d x %d masas en la malla!\n", x_tam, y_tam);
00318 fflush(stderr);
00319 return FALSE;
00320 }
00321
00322 bandera_fijacion = FALSE;
00323 tipo_token = Sabiondo->siguiente_token(cad);
00324 if ( tipo_token == TK_IDENTIFICADOR ) {
00325 if ( strcmp(cad, "FIJA") != 0 ) {
00326 fprintf(stderr, "<TELA> ERROR: El unico modificador "
00327 "valido es \"FIJA\".\n");
00328 fflush(stderr);
00329 return FALSE;
00330 }
00331 bandera_fijacion = TRUE;
00332 tipo_token = Sabiondo->siguiente_token(cad);
00333 }
00334
00335 ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR posicion");
00336 posicion.x = atof(&cad[1]);
00337
00338 tipo_token = Sabiondo->siguiente_token(cad);
00339 ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR posicion)");
00340 posicion.y = atof(cad);
00341 tipo_token = Sabiondo->siguiente_token(cad);
00342 ESPERO(TK_VECTOR_FIN, "el final de un VECTOR posicion");
00343 cad[strlen(cad) - 1] = '\0';
00344 posicion.z = atof(cad);
00345
00346 tipo_token = Sabiondo->siguiente_token(cad);
00347 ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR velocidad");
00348 velocidad.x = atof(&cad[1]);
00349 tipo_token = Sabiondo->siguiente_token(cad);
00350 ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR velocidad)");
00351 velocidad.y = atof(cad);
00352 tipo_token = Sabiondo->siguiente_token(cad);
00353 ESPERO(TK_VECTOR_FIN, "el final de un VECTOR velocidad");
00354 cad[strlen(cad) - 1] = '\0';
00355 velocidad.z = atof(cad);
00356
00357 Arr_masas[accum]._posicion = posicion;
00358 Arr_masas[accum]._velocidad = velocidad;
00359 Arr_masas[accum]._estoy_fijo = bandera_fijacion;
00360
00361 tipo_token = Sabiondo->siguiente_token(cad);
00362 ESPERO(TK_CERRAR, "\"}\", como el final de una MASA_PUNTUAL");
00363 accum++;
00364 tipo_token = TK_DESCONOCIDO;
00365
00366 break;
00367 }
00368 }
00369
00370
00371
00372 if ( accum < ((long)x_tam * (long)y_tam) ) {
00373 fprintf(stderr, "<TELA> Error: "
00374 "Hay menos de %d x %d masas en la malla!\n", x_tam, y_tam);
00375 fflush(stderr);
00376 return FALSE;
00377 }
00378
00379 printf("<TELA> He leido satisfactoriamente %ld puntos.\n", accum);
00380 fflush(stdout);
00381
00382
00383 Superficie = new MESH(0 , FALSE, FALSE, 1);
00384 if ( Textura ) Superficie->anexar_textura(Textura);
00385 Superficie->set_material_global(TRUE);
00386
00387
00388 COLOR ambient, diffuse, specular;
00389
00390 ambient.r = ambient.g = ambient.b = 0.2f;
00391 diffuse.r = 0.85f; diffuse.g = 0.85f; diffuse.b = 0.1f;
00392 specular.r = specular.g = specular.b = 1.0;
00393 ambient.alpha = diffuse.alpha = specular.alpha = 1.0;
00394 Superficie->anx_material(ambient, diffuse, specular, "WG_DEFAULT", "", 1);
00395
00396
00397 VERTICE_GL v;
00398 VECTOR nada(0, 0, 0), p;
00399 double s, t;
00400 int x, y;
00401
00402 for ( y = 0; y < y_tam; y++ ) {
00403 for ( x = 0; x < x_tam; x++ ) {
00404 s = (double)x/(double)(x_tam - 1);
00405 t = (double)y/(double)(y_tam - 1);
00406 p = Arr_masas[x + y * x_tam].posicion_absoluta(nada);
00407 v.x = (float)p.x;
00408 v.y = (float)p.y;
00409 v.z = (float)p.z;
00410 v.u = (float)s;
00411 v.v = (float)t;
00412 Superficie->anx_vertex(v);
00413 }
00414 }
00415
00416 TRIANGULO_GL triangulo_gl;
00417
00418 for ( y = 0; y < y_tam - 1; y++ ) {
00419 for ( x = 0; x < x_tam - 1; x++ ) {
00420 triangulo_gl.p0 = (y)*x_tam+(x);
00421 triangulo_gl.p1 = (y)*x_tam+(x+1);
00422 triangulo_gl.p2 = (y+1)*x_tam+(x);
00423 Superficie->anx_triangle(triangulo_gl, "WG_DEFAULT");
00424 triangulo_gl.p0 = (y)*x_tam+(x+1);
00425 triangulo_gl.p1 = (y+1)*x_tam+(x+1);
00426 triangulo_gl.p2 = (y+1)*x_tam+(x);
00427 Superficie->anx_triangle(triangulo_gl, "WG_DEFAULT");
00428 }
00429 }
00430 Superficie->init();
00431
00432 return TRUE;
00433 }
00434
00435 void
00436 TELA::grabar(FILE *fd)
00437 {
00438 fprintf(fd, "// COSA (TELA sin metodo de grabar!)\n");
00439 }
00440
00441 BOOLEAN
00442 TELA::leer(TOKENIZADOR *Sabiondo)
00443 {
00444 char cad[1000];
00445 int tipo_token = TK_DESCONOCIDO, pos, i;
00446 BOOLEAN con_mi_color = FALSE;
00447 FILE *fd;
00448
00449 pos = 1;
00450 while ( tipo_token != TK_CERRAR ) {
00451 tipo_token = Sabiondo->siguiente_token(cad);
00452 switch ( pos ) {
00453 case 1:
00454 ESPERO(TK_CADENA, "una cadena");
00455 if ( strlen(cad) > MAX_CAD-1 ) cad[MAX_CAD-1] = '\0';
00456 des_comille(cad);
00457 set_nombre(cad);
00458 pos++;
00459 break;
00460 case 2: ESPERO(TK_ABRIR, "\"{\""); pos++; break;
00461 default:
00462 if ( tipo_token == TK_CERRAR ) break;
00463 ESPERO(TK_IDENTIFICADOR, "un identificador (2)");
00464
00465 if ( strstr(cad, "textura") ) {
00466 tipo_token = Sabiondo->siguiente_token(cad);
00467 ESPERO(TK_CADENA, "un nombre de archivo");
00468 des_comille(cad);
00469 fd = fopen(cad, "rb");
00470 if ( !fd ) {
00471 fprintf(stderr,
00472 "<TELA> - ERROR: No puedo abrir el archivo \"%s\".\n",
00473 cad);
00474 fflush(stderr);
00475 return FALSE;
00476 }
00477 Textura = new IMAGEN_RGB();
00478 if ( !Textura||!((IMAGEN_RGB*)Textura)->importar_ppm(fd) ) {
00479 fprintf(stderr,
00480 "<TELA> - ERROR: No puedo leer la imagen \"%s\".\n",
00481 cad);
00482 fflush(stderr);
00483 fclose(fd);
00484 return FALSE;
00485 }
00486 fclose(fd);
00487 }
00488
00489 else if ( strcmp(cad, "resortes_tipo1") == 0 ) {
00490 if ( !leer_resortes(Sabiondo, 0) ) return FALSE;
00491 }
00492 else if ( strcmp(cad, "resortes_tipo2") == 0 ) {
00493 if ( !leer_resortes(Sabiondo, 1) ) return FALSE;
00494 }
00495 else if ( strcmp(cad, "resortes_tipo3") == 0 ) {
00496 if ( !leer_resortes(Sabiondo, 2) ) return FALSE;
00497 }
00498 else if ( strcmp(cad, "malla") == 0 ) {
00499 if ( !leer_malla(Sabiondo) ) return FALSE;
00500 }
00501 else if ( !leer_basico(Sabiondo, cad, &con_mi_color) ) {
00502 return FALSE;
00503 }
00504 ;
00505 break;
00506 }
00507 }
00508
00509 if ( !con_mi_color ) _color = Material->difusa();
00510
00511 for ( i = 0; i < x_tam * y_tam; i++ ) {
00512 Arr_masas[i]._color = _color;
00513 Arr_masas[i]._masa = _masa / (x_tam * y_tam);
00514 Arr_masas[i]._ke = _ke;
00515 }
00516
00517 if ( !precalcular_resortes() ) return FALSE;
00518
00519 return TRUE;
00520 }
00521
00522
00523
00524 void
00525 TELA::actualizar(double delta_t)
00530 {
00531 int i;
00532
00533
00534
00535 for ( i = 0; i < num_resortes1; i++ ) Resortes1[i].actualizar();
00536 for ( i = 0; i < num_resortes2; i++ ) Resortes2[i].actualizar();
00537 for ( i = 0; i < x_tam*y_tam; i++ ) Arr_masas[i].actualizar(delta_t);
00538 recien_simulado = TRUE;
00539 }
00540
00541 int
00542 TELA::ODE_numero_de_variables_de_estado(void)
00543 {
00544 return 0;
00545 }
00546
00547 void
00548 TELA::ODE_reportar_variables_de_estado(double * )
00549 {
00550 ;
00551 }
00552
00553 void
00554 TELA::ODE_actualizar_variables_de_estado(double * )
00555 {
00556 ;
00557 }
00558
00559 void
00560 TELA::ODE_calcular_la_primera_derivada(double * )
00561 {
00562 ;
00563 }
00564
00565 void
00566 TELA::aplicar_campo_vectorial(CAMPO_VECTORIAL *Campo)
00567 {
00568 int i;
00569
00570 for ( i = 0; i < x_tam*y_tam; i++ ) {
00571 Arr_masas[i].aplicar_campo_vectorial(Campo);
00572 }
00573 }
00574
00575 void
00576 TELA::aplicar_drag(double Kd)
00577 {
00578 int i;
00579
00580 for ( i = 0; i < x_tam*y_tam; i++ ) {
00581 Arr_masas[i].aplicar_drag(Kd);
00582 }
00583 }
00584
00585
00586
00587
00588