Página principal | Jerarquía de la clase | Lista alfabética | Lista de componentes | Lista de archivos | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

cosa_rigida.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= cosa_rigida.C                                             Julio de 1998 =
00003 //=-------------------------------------------------------------------------=
00004 //= Definiciones de la clase COSA                                           =
00005 //=-------------------------------------------------------------------------=
00006 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00007 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00008 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00009 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00010 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00011 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00012 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00013 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00014 //=-------------------------------------------------------------------------=
00015 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00016 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00017 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00018 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00019 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
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 //= VARIABLES GLOBALES Y MACROS                                             =
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 //= Clase COSA_RIGIDA                                                       =
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     // OJO: Aqui toca asignar un tensor de inercia por defecto!
00076     tensor_de_inercia_0.identidad(); // Esto es para un cubo unitario de masa
00077     tensor_de_inercia_0 = tensor_de_inercia_0 * (1.0/12.0); // total 1 y con
00078                                      // distribucion de masa uniforme!
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;  // Espacio de intercambio en introspeccion
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 ) { /* Carga de imagenes */ \
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         //CARGA_OPCIONAL_DE_IMAGEN();
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         // OJO: Algunas tiras quedan mal armadas! ... porque cambian de
00436         // orientacion!
00437         g = new MESH(80, FALSE/*strip*/, TRUE/*centrar*/, escala /*OJO!*/);
00438         //((MESH*)g)->set_material_global(TRUE);
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));  // OJO: Y este signo que?
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));  // OJO: Y este signo que?
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     // OJO: En este momento esto es un machete! Siempre se tiene el tensor de
00547     //      inercia de un bloque paralelogramo de masa constante!
00548     double x0, y0, z0; // El bloque es de x0 * y0 * z0 unidades
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   //printf("El tensor de inercia relativo a las coordenadas del objeto es:\n");
00561   //tensor_de_inercia_0.imprimir();
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     //- Ejecute el parser especifico de la COSA_RIGIDA -----------------
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                   // OJO: Es responsabilidad del UNIVERSO asignarme luego
00626                   // mi ESPACIO
00627                   //printf("  - espacio: %s\n", cad); 
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     //- Postprocesamiento de datos -------------------------------------
00642     if ( !con_mi_color ) _color = Material->difusa();
00643 
00644     // Tensor de inercia inicial, calculado a partir de la geometria.
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 Esto es un ridiculo metodo de prueba, debe ser eliminado! (o mejor,
00660 reemplazado por un esquema de evaluadores de funcion...)
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     // MUCHO OJO! No se ha implementado! Debe utilizar la _orientacion, la
00715     // _posicion y la transformacion geometrica del padre si lo hay!...
00716 
00717     // OJO: No es mejor usar directamente el quaternion para aplicar 
00718     //      la rotacion?
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     // OJO: Esto esta incompleto! Que pasa cuando soy parte de un solido
00745     //      articulado? (cuando tengo padre?)
00746 
00747     return _velocidad_angular;
00748 }
00749 
00750 void
00751 COSA_RIGIDA::set_velocidad_angular_absoluta(VECTOR omega)
00752 {
00753     // OJO: Esto esta incompleto! Que pasa cuando soy parte de un solido
00754     //      articulado? (cuando tengo padre?)
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     // OJO: Si es cierto? Que pasa cuando tengo un padre?
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     //- Calcule las esquinas del objeto envolvente en coordenadas locales ---
00783     VECTOR mmi, mmx;
00784     VECTOR esquinas[8];
00785 
00786     Geometria->minmax(&mmi, &mmx);
00787 
00788     GENERAR_ESQUINAS(esquinas);
00789 
00790     //- Calcule el min-max usando las esquinas en coordenadas globales ------
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     //- OJO: Esto deberia precalcularse! -----------------------------------
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     //- OJO: Esto deberia optimizarce! -------------------------------------
00842     double t;
00843     RAYO mi_rayo;
00844 
00845     // Pre-acomodo el rayito para la operacion centrada en el origen
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(); // Esto es necesario?
00850 
00851     // Ejecuto la operacion
00852     t = Geometria->interseccion(&mi_rayo, *Punto, *Normal);
00853 
00854     // Retorno los resultados a coordenadas globales
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     //- Calcule las esquinas del paralelogramo envolvente -------------------
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     //- Solo si el paralelepipedo envolvente de esta COSA se ve se pinta... -
00880     if ( !Camara->minmax_visible(esquinas) ) return;
00881 
00882     //- Inicializacion geometrica (OJO!) ------------------------------------
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     //- Pinte el objeto -----------------------------------------------------
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         // Esto es por si algo salio mal con la geometria
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     //- Finalizacion --------------------------------------------------------
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); // Porque POV piensa en mano izquierda...
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     //- Machete para implementar el drag rotacional! ------------------------
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     //- Viscosidad lineal --------------------------------------------------
00979     VECTOR centro_de_masa(0,0,0);
00980 
00981     // OJO: Estas posiciones deben estar bien pensadas!
00982     anexar_fuerza(velocidad_absoluta() * Kd,
00983       posicion_absoluta(centro_de_masa));
00984 
00985     //- Viscosidad rotacional ----------------------------------------------
00986     // Macheteado en COSA_RIGIDA::actualizar ...
00987 //#define ESTRATEGIA_FALLIDA
00988 //#define DEBUG_ROTFAL
00989 #ifdef ESTRATEGIA_FALLIDA
00990     // Esto es un machete para manejar el torque... mmm OJO: Seguir pensando
00991     // en la situacion del torque. La implementacion funciono, pero annade
00992     // rotacion un poco mal, haciendo que el objeto se de la vuelta un
00993     // poco hacia donde no deberia...
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         // OJO: Esto es una constante empirica! -> toca derivarla y mejorarla.
01010         //      Ademas... en la vida real depende de la geometria del objeto!
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 //= SERVICIOS DE ECUACION DIFERENCIAL! ======================================
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     // IMPORTANTE: Esto mantiene a raya el error numerico, al asegurar
01105     // que las matrices de rotacion siempre sean ortonormales.
01106     _orientacion.normalizar();
01107 }
01108 
01109 void
01110 COSA_RIGIDA::ODE_calcular_la_primera_derivada(double *Datos)
01169 {
01170     //- 1. CALCULE LA CONTRIBUCION TOTAL DE LAS FUERZAS SOBRE EL CUERPO -----
01171     int i;
01172     VECTOR fuerza_total(0, 0, 0);
01173     VECTOR torque_total(0, 0, 0);  // Cambio en el momento angular
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     // OJO: Los cuerpos fijos no se mueven (i.e. no se afectan por el SOLVER)
01185     if ( _estoy_fijo ) return;
01186 
01187     //- 2. ACTUALICE LOS DATOS LINEALES -------------------------------------
01188 
01189     // 2.1. X' = V
01190     Datos[0] = _velocidad.x;
01191     Datos[1] = _velocidad.y;
01192     Datos[2] = _velocidad.z;
01193 
01194     // 2.2. V' = F/m
01195     Datos[3] = fuerza_total.x / _masa;
01196     Datos[4] = fuerza_total.y / _masa;
01197     Datos[5] = fuerza_total.z / _masa;
01198 
01199     //- 3. ACTUALICE LOS DATOS ROTACIONALES ---------------------------------
01200 
01201     // 3.1. Orientacion usando el metodo de los quaternions: q' = (1/2)omega*q
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     // 3.1. Orientacion usando el metodo de las matrices de rotacion...
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; // 3.1.1. Haga efectivos los cambios
01221     Datos[7] = q_prima.direccion.y;
01222     Datos[8] = q_prima.direccion.z;
01223     Datos[9] = q_prima.magnitud;
01224 
01225     // 3.2. Actualizacion de la velocidad rotacional
01226     // OJO: Es necesario hacer varias pruebas para validar el funcionamiento
01227     //      de la contribucion rotacional del tensor de inercia!
01228     MATRIZ_4x4 R_t;       // Matriz de rotacion para la COSA en t
01229     MATRIZ_4x4 I_t;       // Tensor de inercia evaluado en t
01230     VECTOR delta_omega_t; // Cambio en la velocidad angular
01231 
01232     // No es mejor usar el metodo `tensor_de_innercia()` ?
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 //= EOF                                                                     =
01244 //===========================================================================
01245 

Este archivo HTML ha sido generado automáticamente a partir del código fuente AQUYNZA. NO LO EDITE. Para mayor información contacte al autor.