00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "jed_gl.h"
00023 #include "core/cosas/cosa.h"
00024 #include "lista.cc"
00025 #include "toolkits/media/jed_img.h"
00026 #include "toolkits/geom/mesh.h"
00027 #include "toolkits/util/3dsload.h"
00028 #include "matriz4.h"
00029
00030 #include <ctype.h>
00031 #include <string.h>
00032 #include <stdlib.h>
00033
00034
00035
00036
00037
00038 #define ESPERO(tipo, msg) \
00039 if ( tipo_token != (tipo) ) { \
00040 fprintf(stderr, "<COSA_RIGIDA> ERROR: Esperaba %s y recibi [%s].\n", \
00041 (msg), cad); fflush(stderr); return FALSE; \
00042 }
00043
00044 #define GENERAR_ESQUINAS(e) \
00045 (e)[0].x = mmi.x; (e)[0].y = mmi.y; (e)[0].z = mmi.z; \
00046 (e)[1].x = mmx.x; (e)[1].y = mmi.y; (e)[1].z = mmi.z; \
00047 (e)[2].x = mmi.x; (e)[2].y = mmi.y; (e)[2].z = mmx.z; \
00048 (e)[3].x = mmx.x; (e)[3].y = mmi.y; (e)[3].z = mmx.z; \
00049 (e)[4].x = mmi.x; (e)[4].y = mmx.y; (e)[4].z = mmi.z; \
00050 (e)[5].x = mmx.x; (e)[5].y = mmx.y; (e)[5].z = mmi.z; \
00051 (e)[6].x = mmi.x; (e)[6].y = mmx.y; (e)[6].z = mmx.z; \
00052 (e)[7].x = mmx.x; (e)[7].y = mmx.y; (e)[7].z = mmx.z;
00053
00054
00055
00056
00057
00058 COSA_RIGIDA::COSA_RIGIDA() : COSA()
00059 {
00060 float magnitud = 0;
00061 VECTOR k(0, 0, 1);
00062
00063 _tipo_de_cosa = CC_COSA_RIGIDA;
00064
00065 _orientacion.importar_angulo_eje(magnitud, k);
00066
00067 _velocidad_angular.x = 0;
00068 _velocidad_angular.y = 0;
00069 _velocidad_angular.z = 0;
00070
00071 _centro_de_masa.x = 0;
00072 _centro_de_masa.y = 0;
00073 _centro_de_masa.z = 0;
00074
00075
00076 tensor_de_inercia_0.identidad();
00077 tensor_de_inercia_0 = tensor_de_inercia_0 * (1.0/12.0);
00078
00079
00080 Geometria = NULL;
00081 _ultimo_Kd = 0.1;
00082 }
00083
00084 COSA_RIGIDA::~COSA_RIGIDA()
00085 {
00086 if ( _nombre_padre ) delete _nombre_padre;
00087 }
00088
00089 GEOMETRIA *
00090 COSA_RIGIDA::geometria(void)
00091 {
00092 return Geometria;
00093 }
00094
00095 static QUATERNION TMP_quaternion;
00096 static VECTOR TMP_vector;
00097 static double TMP_float;
00098
00099 BOOLEAN
00100 COSA_RIGIDA::consultar_variable(const char *nombre_variable, int &tipo, void **ref)
00105 {
00106 double yaw, pitch, roll;
00107 MATRIZ_4x4 R;
00108
00109 if ( strcmp(nombre_variable, "orientacion_absoluta_euler") == 0 ) {
00110 R.importar_quaternion(orientacion_absoluta());
00111 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00112 TMP_vector.x = yaw;
00113 TMP_vector.y = pitch;
00114 TMP_vector.z = roll;
00115 tipo = T_VECTOR;(*ref) = &TMP_vector; return TRUE;
00116 }
00117 else if ( strcmp(nombre_variable, "yaw") == 0 ) {
00118 R.importar_quaternion(orientacion_absoluta());
00119 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00120 TMP_float = yaw;
00121 tipo = T_FLOAT; (*ref) = &TMP_float; return TRUE;
00122 }
00123 else if ( strcmp(nombre_variable, "pitch") == 0 ) {
00124 R.importar_quaternion(orientacion_absoluta());
00125 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00126 TMP_float = pitch;
00127 tipo = T_FLOAT; (*ref) = &TMP_float; return TRUE;
00128 }
00129 else if ( strcmp(nombre_variable, "roll") == 0 ) {
00130 R.importar_quaternion(orientacion_absoluta());
00131 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00132 TMP_float = roll;
00133 tipo = T_FLOAT; (*ref) = &TMP_float; return TRUE;
00134 }
00135 else if ( strcmp(nombre_variable, "yaw_relativo") == 0 ) {
00136 R.importar_quaternion(_orientacion);
00137 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00138 TMP_float = yaw;
00139 tipo = T_FLOAT; (*ref) = &TMP_float; return TRUE;
00140 }
00141 else if ( strcmp(nombre_variable, "pitch_relativo") == 0 ) {
00142 R.importar_quaternion(_orientacion);
00143 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00144 TMP_float = pitch;
00145 tipo = T_FLOAT; (*ref) = &TMP_float; return TRUE;
00146 }
00147 else if ( strcmp(nombre_variable, "roll_relativo") == 0 ) {
00148 R.importar_quaternion(_orientacion);
00149 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00150 TMP_float = roll;
00151 tipo = T_FLOAT; (*ref) = &TMP_float; return TRUE;
00152 }
00153 else if ( strcmp(nombre_variable, "orientacion_absoluta") == 0 ) {
00154 TMP_quaternion = orientacion_absoluta();
00155 tipo = T_QUATERNION; (*ref) = &TMP_quaternion; return TRUE;
00156 }
00157 else if ( strcmp(nombre_variable, "velocidad_angular") == 0 ) {
00158 tipo = T_VECTOR; (*ref) = &_orientacion; return TRUE;
00159 }
00160 else if ( strcmp(nombre_variable, "centro_de_masa") == 0 ) {
00161 tipo = T_VECTOR; (*ref) = &_centro_de_masa; return TRUE;
00162 }
00163 ;
00164
00165 return COSA::consultar_variable(nombre_variable, tipo, ref);
00166 }
00167
00168 BOOLEAN
00169 COSA_RIGIDA::actualizar_variable(const char *nombre_variable, int tipo, void *ref)
00170 {
00171 MATRIZ_4x4 R;
00172 double yaw, pitch, roll;
00173
00174 if ( strcmp(nombre_variable, "orientacion_absoluta_euler") == 0 ) {
00175 if ( tipo != T_VECTOR ) return FALSE;
00176 TMP_vector = *((VECTOR *)(ref));
00177 R.rotacion_angulos_euler(TMP_vector.x, TMP_vector.y, TMP_vector.z);
00178 set_orientacion_absoluta(R.exportar_quaternion());
00179 }
00180 else if ( strcmp(nombre_variable, "yaw") == 0 ) {
00181 if ( tipo != T_FLOAT ) return FALSE;
00182 R.importar_quaternion(orientacion_absoluta());
00183 R.exportar_angulos_euler(&TMP_float, &pitch, &roll);
00184 TMP_float = *((double *)(ref));
00185 R.rotacion_angulos_euler(TMP_float, pitch, roll);
00186 set_orientacion_absoluta(R.exportar_quaternion());
00187 }
00188 else if ( strcmp(nombre_variable, "pitch") == 0 ) {
00189 if ( tipo != T_FLOAT ) return FALSE;
00190 R.importar_quaternion(orientacion_absoluta());
00191 R.exportar_angulos_euler(&yaw, &TMP_float, &roll);
00192 TMP_float = *((double *)(ref));
00193 R.rotacion_angulos_euler(yaw, TMP_float, roll);
00194 set_orientacion_absoluta(R.exportar_quaternion());
00195 }
00196 else if ( strcmp(nombre_variable, "roll") == 0 ) {
00197 if ( tipo != T_FLOAT ) return FALSE;
00198 R.importar_quaternion(orientacion_absoluta());
00199 R.exportar_angulos_euler(&yaw, &pitch, &TMP_float);
00200 TMP_float = *((double *)(ref));
00201 R.rotacion_angulos_euler(yaw, pitch, TMP_float);
00202 set_orientacion_absoluta(R.exportar_quaternion());
00203 }
00204 else if ( strcmp(nombre_variable, "yaw_relativo") == 0 ) {
00205 if ( tipo != T_FLOAT ) return FALSE;
00206 R.importar_quaternion(_orientacion);
00207 R.exportar_angulos_euler(&TMP_float, &pitch, &roll);
00208 TMP_float = *((double *)(ref));
00209 R.rotacion_angulos_euler(TMP_float, pitch, roll);
00210 _orientacion = R.exportar_quaternion();
00211 }
00212 else if ( strcmp(nombre_variable, "pitch_relativo") == 0 ) {
00213 if ( tipo != T_FLOAT ) return FALSE;
00214 R.importar_quaternion(_orientacion);
00215 R.exportar_angulos_euler(&yaw, &TMP_float, &roll);
00216 TMP_float = *((double *)(ref));
00217 R.rotacion_angulos_euler(yaw, TMP_float, roll);
00218 _orientacion = R.exportar_quaternion();
00219 }
00220 else if ( strcmp(nombre_variable, "roll_relativo") == 0 ) {
00221 if ( tipo != T_FLOAT ) return FALSE;
00222 R.importar_quaternion(_orientacion);
00223 R.exportar_angulos_euler(&yaw, &pitch, &TMP_float);
00224 TMP_float = *((double *)(ref));
00225 R.rotacion_angulos_euler(yaw, pitch, TMP_float);
00226 _orientacion = R.exportar_quaternion();
00227 }
00228 else {
00229 return COSA::actualizar_variable(nombre_variable, tipo, ref);
00230 }
00231 ;
00232 return TRUE;
00233 }
00234
00235 COSA *
00236 COSA_RIGIDA::crear_copia(void)
00240 {
00241 GEOMETRIA *Forma;
00242 COSA_RIGIDA *Peluda;
00243
00244 Forma = Geometria->crear_copia();
00245 if ( !Forma ) return NULL;
00246
00247 Peluda = new COSA_RIGIDA;
00248 if ( !Peluda ) return NULL;
00249
00250 Peluda->Geometria = Forma;
00251 (*Peluda) = (*this);
00252 return (COSA *)Peluda;
00253 }
00254
00255 IMAGEN *
00256 cargar_imagen(char *archivo)
00262 {
00263 IMAGEN *Img;
00264 FILE *fd;
00265
00266 fd = fopen(archivo, "rb");
00267 if ( !fd ) {
00268 fprintf(stderr,
00269 "<COSA> Warning: No se puede abrir el archivo \"%s\"!\n",
00270 archivo);
00271 fflush(stderr);
00272 return NULL;
00273 }
00274 Img = new IMAGEN_RGB();
00275 if ( !( ((IMAGEN_RGB*)Img)->importar_ppm(fd) ) ) {
00276 fprintf(stderr, "<COSA> Warning: No se puede crear el bitmap IMG!\n");
00277 fflush(stderr); delete Img;
00278 return NULL;
00279 }
00280 fclose(fd);
00281 return Img;
00282 }
00283
00284 #define CARGA_OPCIONAL_DE_IMAGEN() \
00285 tipo_token = Sabiondo->siguiente_token(cad); \
00286 ESPERO(TK_CADENA, "una cadena (imagen)"); \
00287 if ( strlen(cad) > 2 ) { \
00288 des_comille(cad); \
00289 Img = cargar_imagen(cad); \
00290 if ( Img ) { \
00291 g->anexar_textura(Img); \
00292 } \
00293 else { \
00294 fprintf(stderr, \
00295 "<COSA> Warning: no se pudo cargar una imagen del archivo\n" \
00296 "\"%s\". La imagen a sido desactivada.\n", cad); \
00297 fflush(stderr); \
00298 } \
00299 }
00300
00301
00302 GEOMETRIA *
00303 leer_geometria(TOKENIZADOR *Sabiondo)
00304 {
00305 char cad[1000];
00306 #ifdef GLTT_ENABLED
00307 char cad2[1000];
00308 #endif
00309 int tipo_token;
00310 GEOMETRIA *g = NULL;
00311 IMAGEN *Img = NULL;
00312 VECTOR lados;
00313 ESCENA_3DS *Escena;
00314 BOOLEAN alphablending;
00315 double f1, f2, f3, f4, dummy, escala, nr = 1;
00316 double r1, r2, h;
00317 FILE *fd;
00318
00319 tipo_token = Sabiondo->siguiente_token(cad);
00320 ESPERO(TK_IDENTIFICADOR, "un identificador de geometria");
00321
00322 if ( strcmp(cad, "ESFERA") == 0 ) {
00323 tipo_token = Sabiondo->siguiente_token(cad);
00324 ESPERO(TK_NUMERO, "un numero (radio)");
00325 g = new ESFERA(atof(cad));
00326 CARGA_OPCIONAL_DE_IMAGEN();
00327 }
00328 else if ( strcmp(cad, "CUBO") == 0 ) {
00329 tipo_token = Sabiondo->siguiente_token(cad);
00330 ESPERO(TK_NUMERO, "un numero (lado)");
00331 g = new CUBO(atof(cad));
00332 CARGA_OPCIONAL_DE_IMAGEN();
00333 }
00334 else if ( strcmp(cad, "PLANTA_FRACTAL") == 0 ) {
00335 tipo_token = Sabiondo->siguiente_token(cad);
00336 ESPERO(TK_NUMERO, "un numero (nivel de recursion)");
00337 nr = atof(cad);
00338 tipo_token = Sabiondo->siguiente_token(cad);
00339 ESPERO(TK_NUMERO, "un numero (escala)");
00340 escala = atof(cad);
00341 g = new PLANTA_FRACTAL((int)(floor(nr)), escala);
00342
00343 }
00344 else if ( strcmp(cad, "OCTREE") == 0 ) {
00345 tipo_token = Sabiondo->siguiente_token(cad);
00346 ESPERO(TK_NUMERO, "un numero (lado)");
00347 g = new OCTREE(atof(cad));
00348 tipo_token = Sabiondo->siguiente_token(cad);
00349 ESPERO(TK_CADENA, "una cadena (archivo .oct)");
00350 des_comille(cad);
00351 fd = fopen(cad, "rb");
00352 if ( !fd ) {
00353 fprintf(stderr,"<COSA_RIGIDA> "
00354 "ERROR abriendo archivo de OCTREE!\n");
00355 fflush(stderr);
00356 return NULL;
00357 }
00358 ((OCTREE *)(g))->leer(fd);
00359 fclose(fd);
00360 CARGA_OPCIONAL_DE_IMAGEN();
00361 }
00362 else if ( strcmp(cad, "FLECHA") == 0 ) {
00363 tipo_token = Sabiondo->siguiente_token(cad);
00364 ESPERO(TK_NUMERO, "un numero (longitud flecha)");
00365 f1 = atof(cad);
00366 tipo_token = Sabiondo->siguiente_token(cad);
00367 ESPERO(TK_NUMERO, "un numero (longitud punta)");
00368 f2 = atof(cad);
00369 tipo_token = Sabiondo->siguiente_token(cad);
00370 ESPERO(TK_NUMERO, "un numero (grosor cuerpo)");
00371 f3 = atof(cad);
00372 tipo_token = Sabiondo->siguiente_token(cad);
00373 ESPERO(TK_NUMERO, "un numero (grosor punta)");
00374 f4 = atof(cad);
00375 g = new FLECHA(f1, f2, f3, f4);
00376 CARGA_OPCIONAL_DE_IMAGEN();
00377 }
00378 else if ( strcmp(cad, "PARALELEPIPEDO") == 0 ) {
00379 tipo_token = Sabiondo->siguiente_token(cad);
00380 ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
00381 lados.x = atof(&cad[1]);
00382 tipo_token = Sabiondo->siguiente_token(cad);
00383 ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
00384 lados.y = atof(cad);
00385 tipo_token = Sabiondo->siguiente_token(cad);
00386 ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
00387 lados.z = atof(cad);
00388 g = new PARALELEPIPEDO(lados);
00389 CARGA_OPCIONAL_DE_IMAGEN();
00390 }
00391 else if ( strcmp(cad, "CILINDRO") == 0 ) {
00392 tipo_token = Sabiondo->siguiente_token(cad);
00393 ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
00394 r1 = atof(&cad[1]);
00395 tipo_token = Sabiondo->siguiente_token(cad);
00396 ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
00397 r2 = atof(cad);
00398 tipo_token = Sabiondo->siguiente_token(cad);
00399 ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
00400 h = atof(cad);
00401 g = new CILINDRO(r1, r2, h);
00402 CARGA_OPCIONAL_DE_IMAGEN();
00403 }
00404 #ifdef GLTT_ENABLED
00405 else if ( strcmp(cad, "TEXTO_3D") == 0 ) {
00406 tipo_token = Sabiondo->siguiente_token(cad);
00407 ESPERO(TK_CADENA, "una cadena (truetype font)");
00408 strcpy(cad2, cad);
00409 tipo_token = Sabiondo->siguiente_token(cad);
00410 ESPERO(TK_NUMERO, "una numero (escala de la letra)");
00411 f1 = atof(cad);
00412 tipo_token = Sabiondo->siguiente_token(cad);
00413 ESPERO(TK_CADENA, "una cadena (texto)");
00414 des_comille(cad2); des_comille(cad);
00415 g = new TEXTO_3D(cad2, cad, f1);
00416 CARGA_OPCIONAL_DE_IMAGEN();
00417 }
00418 #else
00419 else if ( strcmp(cad, "TEXTO_3D") == 0 ) {
00420 fprintf(stderr,
00421 "<TEXTO_3D>: No disponible en esta version, debido a que AQUYNZA fue\n"
00422 "compilado si la libreria GLTT/FreeType.\n");
00423 fflush(stderr);
00424 exit(1);
00425 }
00426 #endif
00427 else if ( strcmp(cad, "MESH_3DS") == 0 ) {
00428 tipo_token = Sabiondo->siguiente_token(cad);
00429 ESPERO(TK_CADENA, "un archivo .3DS");
00430 des_comille(cad);
00431 Escena = new ESCENA_3DS(cad);
00432 tipo_token = Sabiondo->siguiente_token(cad);
00433 ESPERO(TK_NUMERO, "una numero (escala de la letra)");
00434 escala = atof(cad);
00435
00436
00437 g = new MESH(80, FALSE, TRUE, escala );
00438
00439 alphablending = FALSE;
00440 if ( !Escena || Escena->muerta() ) {
00441 if ( Escena ) delete Escena;
00442 fprintf(stderr, "<COSA> - ERROR: No puedo leer \"%s\"\n", cad);
00443 fflush(stderr);
00444 exit(-1);
00445 }
00446 importar_3DS(Escena, (MESH*)g, &alphablending, &dummy);
00447 delete Escena;
00448 }
00449 else {
00450 fprintf(stderr,
00451 "<COSA_RIGIDA> "
00452 "ERROR: El tipo de GEOMETRIA \"%s\" es desconocido\n", cad);
00453 fflush(stderr);
00454 exit(1);
00455 }
00456 ;
00457
00458 return g;
00459 }
00460
00461 BOOLEAN
00462 COSA_RIGIDA::resolver(LISTA <COSA *> *Cosas)
00463 {
00464 if ( !_nombre_padre ) return TRUE;
00465
00466 int i;
00467
00468 for ( i = 0; i < Cosas->tam(); i++ ) {
00469 if ( strcmp(_nombre_padre, (*Cosas)[i]->nombre()) == 0 ) {
00470 Padre = (*Cosas)[i];
00471 return TRUE;
00472 }
00473 }
00474 return FALSE;
00475 }
00476
00477 BOOLEAN
00478 COSA_RIGIDA::leer_rigida(TOKENIZADOR *Sabiondo, char *cad)
00482 {
00483 int tipo_token = TK_DESCONOCIDO;
00484 VECTOR direccion;
00485 double magnitud, yaw, pitch, roll;
00486 MATRIZ_4x4 R;
00487
00488 if ( strcmp(cad, "velocidad_angular") == 0 ) {
00489 tipo_token = Sabiondo->siguiente_token(cad);
00490 ESPERO(TK_NUMERO, "un numero (magnitud de rotacion)");
00491 magnitud = DEG2RAD(atof(cad));
00492 tipo_token = Sabiondo->siguiente_token(cad);
00493 ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
00494 direccion.x = atof(&(cad[1]));
00495 tipo_token = Sabiondo->siguiente_token(cad);
00496 ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
00497 direccion.y = atof(cad);
00498 tipo_token = Sabiondo->siguiente_token(cad);
00499 ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
00500 cad[strlen(cad) - 1] = '\0';
00501 direccion.z = atof(cad);
00502 direccion.normalizar();
00503 _velocidad_angular = direccion * magnitud;
00504 }
00505 else if ( strcmp(cad, "orientacion") == 0 ) {
00506 tipo_token = Sabiondo->siguiente_token(cad);
00507 ESPERO(TK_NUMERO, "un numero (magnitud de rotacion)");
00508 magnitud = DEG2RAD(atof(cad));
00509 tipo_token = Sabiondo->siguiente_token(cad);
00510 ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
00511 direccion.x = atof(&(cad[1]));
00512 tipo_token = Sabiondo->siguiente_token(cad);
00513 ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
00514 direccion.y = atof(cad);
00515 tipo_token = Sabiondo->siguiente_token(cad);
00516 ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
00517 cad[strlen(cad) - 1] = '\0';
00518 direccion.z = atof(cad);
00519 direccion.normalizar();
00520 _orientacion.importar_angulo_eje(magnitud, direccion);
00521 }
00522 else if ( strcmp(cad, "orientacion_euler") == 0 ) {
00523 tipo_token = Sabiondo->siguiente_token(cad);
00524 ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
00525 yaw = DEG2RAD(atof(&(cad[1])));
00526 tipo_token = Sabiondo->siguiente_token(cad);
00527 ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
00528 pitch = DEG2RAD(atof(cad));
00529 tipo_token = Sabiondo->siguiente_token(cad);
00530 ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
00531 cad[strlen(cad) - 1] = '\0';
00532 roll = DEG2RAD(atof(cad));
00533 R.rotacion_angulos_euler(yaw, pitch, roll);
00534 _orientacion = R.exportar_quaternion();
00535 }
00536
00537 return TRUE;
00538 }
00539
00540 void
00541 COSA_RIGIDA::resolver_tensor_de_inercia(void)
00545 {
00546
00547
00548 double x0, y0, z0;
00549
00550 x0 = 1;
00551 y0 = 0.5;
00552 z0 = 0.2;
00553
00554 tensor_de_inercia_0.identidad();
00555 tensor_de_inercia_0.M[0][0] = ((y0*y0)+(z0*z0)) * (_masa/12.0);
00556 tensor_de_inercia_0.M[1][1] = ((x0*x0)+(z0*z0)) * (_masa/12.0);
00557 tensor_de_inercia_0.M[2][2] = ((x0*x0)+(y0*y0)) * (_masa/12.0);
00558 tensor_de_inercia_0 = tensor_de_inercia_0;
00559
00560
00561
00562 }
00563
00564 void
00565 COSA_RIGIDA::grabar(FILE *fd)
00566 {
00567
00568 fprintf(fd, "COSA_RIGIDA \"%s\"\n", nombre());
00569 grabar_basico(fd);
00570
00571
00572 char n0[200];
00573 char n1[200];
00574 char n2[200];
00575 char n3[200];
00576 double yaw, pitch, roll, m;
00577 MATRIZ_4x4 R;
00578
00579 R.importar_quaternion(orientacion_absoluta());
00580 R.exportar_angulos_euler(&yaw, &pitch, &roll);
00581 sprintf(n1, "%f", yaw); simplifique_real(n1);
00582 sprintf(n2, "%f", pitch); simplifique_real(n2);
00583 sprintf(n3, "%f", roll); simplifique_real(n3);
00584 fprintf(fd, " orientacion_euler <%s, %s, %s>\n", n1, n2, n3);
00585
00586 m = _velocidad_angular.norma();
00587 sprintf(n0, "%f", RAD2DEG(m)); simplifique_real(n0);
00588 sprintf(n1, "%f", _velocidad_angular.x/m); simplifique_real(n1);
00589 sprintf(n2, "%f", _velocidad_angular.y/m); simplifique_real(n2);
00590 sprintf(n3, "%f", _velocidad_angular.z/m); simplifique_real(n3);
00591 fprintf(fd, " velocidad_angular %s:<%s, %s, %s>\n", n0, n1, n2, n3);
00592
00593 if ( Geometria ) Geometria->pintar_aqz(fd);
00594
00595
00596 fprintf(fd, "}\n\n");
00597 }
00598
00599 BOOLEAN
00600 COSA_RIGIDA::leer(TOKENIZADOR *Sabiondo)
00601 {
00602 char cad[1000];
00603 int tipo_token = TK_DESCONOCIDO, pos;
00604 BOOLEAN con_mi_color = FALSE;
00605
00606
00607 pos = 1;
00608 while ( tipo_token != TK_CERRAR) {
00609 tipo_token = Sabiondo->siguiente_token(cad);
00610 switch ( pos ) {
00611 case 1:
00612 ESPERO(TK_CADENA, "una cadena");
00613 if ( strlen(cad) > MAX_CAD-1 ) cad[MAX_CAD-1] = '\0';
00614 des_comille(cad);
00615 set_nombre(cad);
00616 pos++;
00617 break;
00618 case 2: ESPERO(TK_ABRIR, "\"{\""); pos++; break;
00619 default:
00620 if ( tipo_token == TK_CERRAR ) break;
00621 ESPERO(TK_IDENTIFICADOR, "un identificador (3)");
00622 if ( strcmp(cad, "espacio") == 0 ) {
00623 tipo_token = Sabiondo->siguiente_token(cad);
00624 ESPERO(TK_CADENA, "una cadena");
00625
00626
00627
00628 }
00629 else if ( strcmp(cad, "geometria") == 0 ) {
00630 Geometria = leer_geometria(Sabiondo);
00631 }
00632 else if (
00633 !leer_basico(Sabiondo, cad, &con_mi_color) ||
00634 !leer_rigida(Sabiondo, cad)
00635 ) return FALSE;
00636 ;
00637 break;
00638 }
00639 }
00640
00641
00642 if ( !con_mi_color ) _color = Material->difusa();
00643
00644
00645 if ( !Geometria ) {
00646 fprintf(stderr, "<COSA_RIGIDA> ERROR FATAL: Sin una geometria no "
00647 "puede calcularse un tensor de inercia!\n");
00648 fflush(stderr);
00649 return FALSE;
00650 }
00651
00652 resolver_tensor_de_inercia();
00653 return TRUE;
00654 }
00655
00656 void
00657 COSA_RIGIDA::tick(void)
00658
00659
00660
00661
00662 {
00663 static double t = 0;
00664
00665 t+=0.05;
00666
00667 _posicion.x = 0.5 + sin(t)/2;
00668 _posicion.y = 0.5 + cos(2*t)/2;
00669 _posicion.z = 0.5 - cos(3*t)/2;
00670 }
00671
00672 QUATERNION
00673 COSA_RIGIDA::orientacion_absoluta(void)
00680 {
00681 QUATERNION resultado = _orientacion;
00682
00683 if ( Padre ) {
00684 resultado = Padre->orientacion_absoluta() * resultado;
00685 }
00686 resultado.normalizar();
00687 return resultado;
00688 }
00689
00690 void
00691 COSA_RIGIDA::set_orientacion_absoluta(QUATERNION q)
00695 {
00696 if ( Padre ) {
00697 fprintf(stderr, "<COSA_RIGIDA> - ERROR: \n"
00698 "set_orientacion_absoluta() no implementada para cosas con padre.\n");
00699 fflush(stderr);
00700 exit(1);
00701 }
00702 _orientacion = q;
00703 }
00704
00705 VECTOR
00706 COSA_RIGIDA::posicion_absoluta(VECTOR p)
00713 {
00714
00715
00716
00717
00718
00719 VECTOR p_pos(0, 0, 0), resultado;
00720 void *interface1, *interface2;
00721 MATRIZ_4x4 R, p_ori;
00722 int tipo1, tipo2;
00723
00724 R.importar_quaternion(_orientacion);
00725
00726 if ( Padre && Padre->consultar_variable("posicion", tipo1, &interface1) &&
00727 Padre->consultar_variable("orientacion_absoluta",tipo2,&interface2) ) {
00728 if ( tipo1 == T_VECTOR && tipo2 == T_QUATERNION ) {
00729 p_pos = (*(VECTOR *)interface1);
00730 p_ori.importar_quaternion((*(QUATERNION *)interface2));
00731 }
00732 resultado = p_pos + p_ori*_posicion + R*p;
00733 }
00734 else {
00735 resultado = _posicion + R*p;
00736 }
00737
00738 return resultado;
00739 }
00740
00741 VECTOR
00742 COSA_RIGIDA::velocidad_angular_absoluta(void)
00743 {
00744
00745
00746
00747 return _velocidad_angular;
00748 }
00749
00750 void
00751 COSA_RIGIDA::set_velocidad_angular_absoluta(VECTOR omega)
00752 {
00753
00754
00755
00756 _velocidad_angular = omega;
00757 }
00758
00759 MATRIZ_4x4
00760 COSA_RIGIDA::tensor_de_inercia(void)
00761 {
00762 MATRIZ_4x4 I_t, R_t;
00763
00764
00765 R_t.importar_quaternion(_orientacion);
00766 I_t = R_t * (tensor_de_inercia_0 * R_t);
00767 return I_t;
00768 }
00769
00770 void
00771 COSA_RIGIDA::minmax(VECTOR *min, VECTOR *max)
00779 {
00780 if ( !Geometria ) return;
00781
00782
00783 VECTOR mmi, mmx;
00784 VECTOR esquinas[8];
00785
00786 Geometria->minmax(&mmi, &mmx);
00787
00788 GENERAR_ESQUINAS(esquinas);
00789
00790
00791 int i;
00792
00793 min->x = INFINITO;
00794 min->y = INFINITO;
00795 min->z = INFINITO;
00796 max->x = -INFINITO;
00797 max->y = -INFINITO;
00798 max->z = -INFINITO;
00799
00800 for ( i = 0; i < 8; i++ ) esquinas[i] = posicion_absoluta(esquinas[i]);
00801 for ( i = 0; i < 8; i++ ) {
00802 if ( esquinas[i].x < min->x ) min->x = esquinas[i].x;
00803 if ( esquinas[i].y < min->y ) min->y = esquinas[i].y;
00804 if ( esquinas[i].z < min->z ) min->z = esquinas[i].z;
00805 if ( esquinas[i].x > max->x ) max->x = esquinas[i].x;
00806 if ( esquinas[i].y > max->y ) max->y = esquinas[i].y;
00807 if ( esquinas[i].z > max->z ) max->z = esquinas[i].z;
00808 }
00809 }
00810
00811 double
00812 COSA_RIGIDA::interseccion(RAYO *Rayo, VECTOR *Punto, VECTOR *Normal)
00825 {
00826 if ( !Geometria ) {
00827 fprintf(stderr, "<COSA_RIGIDA> ERROR: No para herencia!\n");
00828 fflush(stderr);
00829 return 0;
00830 }
00831
00832
00833 MATRIZ_4x4 R, R_i;
00834 VECTOR po;
00835 VECTOR n(0, 0, 0);
00836
00837 R.importar_quaternion(orientacion_absoluta());
00838 R_i = R.inversa();
00839 po = posicion_absoluta(n);
00840
00841
00842 double t;
00843 RAYO mi_rayo;
00844
00845
00846 mi_rayo.origen = Rayo->origen - po;
00847 mi_rayo.origen = R_i * mi_rayo.origen;
00848 mi_rayo.direccion = R_i * Rayo->direccion;
00849 mi_rayo.direccion.normalizar();
00850
00851
00852 t = Geometria->interseccion(&mi_rayo, *Punto, *Normal);
00853
00854
00855 (*Punto) = R * (*Punto);
00856 (*Punto) = (*Punto) + po;
00857 (*Normal) = R * (*Normal);
00858 return t;
00859 }
00860
00861
00862 #ifdef GL_ENABLED
00863 void
00864 COSA_RIGIDA::pintar_gl(CALIDAD_VISUAL *Calidad, CAMARA *Camara)
00868 {
00869 int i;
00870
00871
00872 VECTOR mmi(0, 0, 0), mmx(1, 1, 1);
00873 VECTOR esquinas[8];
00874
00875 if ( Geometria ) Geometria->minmax(&mmi, &mmx);
00876 GENERAR_ESQUINAS(esquinas);
00877 for ( i = 0; i < 8; i++ ) esquinas[i] = posicion_absoluta(esquinas[i]);
00878
00879
00880 if ( !Camara->minmax_visible(esquinas) ) return;
00881
00882
00883 VECTOR centro_de_masa(0, 0, 0);
00884 MATRIZ_4x4 R;
00885 VECTOR p = posicion_absoluta(centro_de_masa);
00886
00887 glPushMatrix(); glLoadIdentity();
00888 glTranslatef((float)p.x, (float)p.y, (float)p.z);
00889 R.importar_quaternion(orientacion_absoluta());
00890 R.cargar_gl();
00891
00892
00893 static COLOR backup_color;
00894
00895 if ( Geometria ) {
00896 backup_color = Material->difusa();
00897 Material->set_difusa(_color);
00898 Geometria->pintar_gl(Calidad, Material, Camara);
00899 Material->set_difusa(backup_color);
00900 }
00901 else {
00902
00903 glBegin(GL_QUADS);
00904 glVertex2f(1.0/2.0, 1.0/2.0);
00905 glVertex2f(-1.0/2.0, 1.0/2.0);
00906 glVertex2f(-1.0/2.0, -1.0/2.0);
00907 glVertex2f(1.0/2.0, -1.0/2.0);
00908 glEnd();
00909 }
00910
00911
00912 glPopMatrix();
00913 }
00914 #endif // GL_ENABLED
00915
00916 void
00917 COSA_RIGIDA::pintar_povray(FILE *fd)
00920 {
00921 if ( !Geometria ) {
00922 fprintf(fd,
00923 "// <COSA_RIGIDA> - ERROR: No hay geometria!\n");
00924 return;
00925 }
00926
00927 MATRIZ_4x4 R;
00928 VECTOR centro_de_masa(0, 0, 0);
00929 VECTOR p;
00930 COLOR backup_color;
00931
00932 p = posicion_absoluta(centro_de_masa);
00933 R.importar_quaternion(orientacion_absoluta());
00934
00935 Geometria->pintar_povray(fd);
00936 R.inversa().activar_povray(fd);
00937 fprintf(fd, " translate <%f, %f, %f>\n", p.x, p.y, p.z);
00938
00939 backup_color = Material->difusa();
00940 Material->set_difusa(_color);
00941 Material->activar_povray(fd);
00942 Material->set_difusa(backup_color);
00943
00944 fprintf(fd, "}\n");
00945 }
00946
00947 void
00948 COSA_RIGIDA::actualizar(double delta_t)
00949 {
00950 SOLVER_EULER solver(this);
00951
00952 solver.ejecutar_solucion(delta_t);
00953
00954
00955 VECTOR omega;
00956 double factor;
00957
00958 omega = _velocidad_angular;
00959
00960 if ( omega.norma() > 2*EPSILON && _ultimo_Kd > EPSILON ) {
00961 factor = (_ultimo_Kd * delta_t) / 10;
00962 if ( factor < 0 ) {
00963 factor = 0;
00964 }
00965 if ( factor > 1 ) {
00966 factor = 1;
00967 }
00968
00969 omega = omega * (1 - factor);
00970 _velocidad_angular = omega;
00971 }
00972
00973 }
00974
00975 void
00976 COSA_RIGIDA::aplicar_drag(double Kd)
00977 {
00978
00979 VECTOR centro_de_masa(0,0,0);
00980
00981
00982 anexar_fuerza(velocidad_absoluta() * Kd,
00983 posicion_absoluta(centro_de_masa));
00984
00985
00986
00987
00988
00989 #ifdef ESTRATEGIA_FALLIDA
00990
00991
00992
00993
00994 VECTOR omega;
00995 VECTOR origen(0, 0, 0);
00996 MATRIZ_4x4 R;
00997 VECTOR fuerza_de_torque_positiva;
00998 VECTOR fuerza_de_torque_negativa;
00999 VECTOR i(1, 0, 0);
01000 VECTOR binormal;
01001
01002 omega = _velocidad_angular;
01003
01004 if ( omega.norma() > 10*EPSILON ) {
01005 omega.normalizar();
01006 R.rotacion_punto_punto(origen, omega);
01007
01008 fuerza_de_torque_positiva = R * i;
01009
01010
01011 fuerza_de_torque_positiva = fuerza_de_torque_positiva * Kd * 0.5;
01012
01013 fuerza_de_torque_negativa = fuerza_de_torque_positiva * -1;
01014
01015 binormal = fuerza_de_torque_positiva.producto_cruz(omega);
01016 binormal.normalizar();
01017
01018 anexar_fuerza(fuerza_de_torque_positiva,
01019 posicion_absoluta(centro_de_masa + binormal*0.001));
01020 anexar_fuerza(fuerza_de_torque_negativa,
01021 posicion_absoluta(centro_de_masa - binormal*0.001));
01022
01023 #ifdef DEBUG_ROTFAL
01024
01025 clrscr();
01026
01027 printf("omega = ");
01028 (_velocidad_angular*1000).imprimir();
01029 printf("\n");
01030
01031 printf("F+ = ");
01032 (fuerza_de_torque_positiva * 1000).imprimir();
01033 printf("\n");
01034
01035 printf("F- = ");
01036 (fuerza_de_torque_negativa * 1000).imprimir();
01037 printf("\n");
01038
01039 printf("Bn = ");
01040 binormal.imprimir();
01041 printf("\n");
01042
01043 fflush(stdout);
01044
01045 #endif
01046 }
01047 #endif
01048
01049 }
01050
01051
01052
01053 int
01054 COSA_RIGIDA::ODE_numero_de_variables_de_estado(void)
01061 {
01062 if ( _estoy_fijo ) return 0;
01063 return 13;
01064 }
01065
01066 void
01067 COSA_RIGIDA::ODE_reportar_variables_de_estado(double *Datos)
01068 {
01069 if ( _estoy_fijo ) return;
01070
01071 Datos[0] = _posicion.x;
01072 Datos[1] = _posicion.y;
01073 Datos[2] = _posicion.z;
01074 Datos[3] = _velocidad.x;
01075 Datos[4] = _velocidad.y;
01076 Datos[5] = _velocidad.z;
01077 Datos[6] = _orientacion.direccion.x;
01078 Datos[7] = _orientacion.direccion.y;
01079 Datos[8] = _orientacion.direccion.z;
01080 Datos[9] = _orientacion.magnitud;
01081 Datos[10] = _velocidad_angular.x;
01082 Datos[11] = _velocidad_angular.y;
01083 Datos[12] = _velocidad_angular.z;
01084 }
01085
01086 void
01087 COSA_RIGIDA::ODE_actualizar_variables_de_estado(double *Datos)
01088 {
01089 if ( _estoy_fijo ) return;
01090 _posicion.x = Datos[0];
01091 _posicion.y = Datos[1];
01092 _posicion.z = Datos[2];
01093 _velocidad.x = Datos[3];
01094 _velocidad.y = Datos[4];
01095 _velocidad.z = Datos[5];
01096 _orientacion.direccion.x = Datos[6];
01097 _orientacion.direccion.y = Datos[7];
01098 _orientacion.direccion.z = Datos[8];
01099 _orientacion.magnitud = Datos[9];
01100 _velocidad_angular.x = Datos[10];
01101 _velocidad_angular.y = Datos[11];
01102 _velocidad_angular.z = Datos[12];
01103
01104
01105
01106 _orientacion.normalizar();
01107 }
01108
01109 void
01110 COSA_RIGIDA::ODE_calcular_la_primera_derivada(double *Datos)
01169 {
01170
01171 int i;
01172 VECTOR fuerza_total(0, 0, 0);
01173 VECTOR torque_total(0, 0, 0);
01174 VECTOR r_i;
01175
01176 for ( i = 0; i < lista_fuerzas_externas.tam(); i++ ) {
01177 fuerza_total = fuerza_total + lista_fuerzas_externas[i]->fuerza;
01178 r_i = lista_fuerzas_externas[i]->punto - _posicion;
01179 torque_total = torque_total +
01180 r_i.producto_cruz(lista_fuerzas_externas[i]->fuerza);
01181 }
01182 limpiar_fuerzas();
01183
01184
01185 if ( _estoy_fijo ) return;
01186
01187
01188
01189
01190 Datos[0] = _velocidad.x;
01191 Datos[1] = _velocidad.y;
01192 Datos[2] = _velocidad.z;
01193
01194
01195 Datos[3] = fuerza_total.x / _masa;
01196 Datos[4] = fuerza_total.y / _masa;
01197 Datos[5] = fuerza_total.z / _masa;
01198
01199
01200
01201
01202 QUATERNION omega, q_prima;
01203
01204 omega.importar_quaternion_puro(_velocidad_angular);
01205 q_prima = omega*_orientacion;
01206 q_prima = q_prima * 0.5;
01207
01208
01209 #ifdef NONONO // Alternativo...
01210 MATRIZ_4x4 R_prima, omega_asterisco, R;
01211 QUATERNION q_prima;
01212
01213 R.importar_quaternion(_orientacion);
01214 omega_asterisco.importar_asterisco(_velocidad_angular);
01215 R_prima = omega_asterisco * R;
01216 q_prima = R_prima.exportar_quaternion();
01217 _orientacion = _orientacion + q_prima;
01218 #endif
01219
01220 Datos[6] = q_prima.direccion.x;
01221 Datos[7] = q_prima.direccion.y;
01222 Datos[8] = q_prima.direccion.z;
01223 Datos[9] = q_prima.magnitud;
01224
01225
01226
01227
01228 MATRIZ_4x4 R_t;
01229 MATRIZ_4x4 I_t;
01230 VECTOR delta_omega_t;
01231
01232
01233 R_t.importar_quaternion(_orientacion);
01234 I_t = R_t * (tensor_de_inercia_0 * R_t);
01235 delta_omega_t = (I_t.inversa())*torque_total;
01236
01237 Datos[10] = delta_omega_t.x;
01238 Datos[11] = delta_omega_t.y;
01239 Datos[12] = delta_omega_t.z;
01240 }
01241
01242
01243
01244
01245