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

camara.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= camara.C                                            Desde julio de 1998 =
00003 //=-------------------------------------------------------------------------=
00004 //= Definiciones de la clase CAMARA. Este modulo esta dividido en las si-   =
00005 //= guientes secciones:                                                     =
00006 //=   - Operaciones basicas                                                 =
00007 //=   - Operaciones de visualizacion                                        =
00008 //=   - Operaciones de soporte al manejo GUI                                =
00009 //=   - Operaciones de persistencia                                         =
00010 //=-------------------------------------------------------------------------=
00011 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00012 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00013 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00014 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00015 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00016 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00017 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00018 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00019 //=-------------------------------------------------------------------------=
00020 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00021 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00022 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00023 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00024 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
00025 //===========================================================================
00026 
00027 #include "jed_defs.h"  // Incluir antes que nada, en ese modulo se definen 
00028                        // aspectos importantes para la portabilidad del sistema
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include "toolkits/entorno/camara.h"
00034 #include "matriz4.h"
00035 
00036 #ifdef GLTT_ENABLED
00037     #include "toolkits/util/gl_fonts.h"
00038 #endif
00039 
00040 //===========================================================================
00041 //= VARIABLES GLOBALES Y MACROS                                             =
00042 //===========================================================================
00043 
00044 static VECTOR obj, arr;
00045 
00046 #define ESPERO(tipo, msg) \
00047     if ( tipo_token != (tipo) ) { \
00048         fprintf(stderr, "<CAMARA> ERROR: Esperaba %s y recibi [%s].\n", \
00049           (msg), cad); fflush(stderr);  return FALSE; \
00050     }
00051 
00052 #define DISMINUIR(n)                            \
00053     if ( (n) > 10000000 + EPSILON ) (n) /= 2;           \
00054     else if ( (n) > 1000000 + EPSILON ) (n) -= 1000000; \
00055     else if ( (n) > 100000 + EPSILON ) (n) -= 100000;   \
00056     else if ( (n) > 10000 + EPSILON ) (n) -= 10000;     \
00057     else if ( (n) > 1000 + EPSILON ) (n) -= 1000;               \
00058     else if ( (n) > 100 + EPSILON ) (n) -= 100;         \
00059     else if ( (n) > 10 + EPSILON ) (n) -= 10;           \
00060     else if ( (n) > 1 + EPSILON ) (n) -= 1;             \
00061     else if ( (n) > 0.1 + EPSILON ) (n) -= 0.1;         \
00062     else if ( (n) > 0.01 + EPSILON ) (n) -= 0.01;               \
00063     else if ( (n) > 0.001 + EPSILON ) (n) -= 0.001;     \
00064     else if ( (n) > 0.0001 + EPSILON ) (n) -= 0.0001;   \
00065     else (n) = 0.0001;
00066 
00067 #define AUMENTAR(n)                                     \
00068     if ( (n) < 0.001 ) (n) += 0.0001;                   \
00069     else if ( (n) < 0.01 ) (n) += 0.001;                \
00070     else if ( (n) < 0.1 - EPSILON ) (n) += 0.01;        \
00071     else if ( (n) < 1 - EPSILON ) (n) += 0.1;           \
00072     else if ( (n) < 10 - EPSILON ) (n) += 1;            \
00073     else if ( (n) < 100 - EPSILON ) (n) += 10;          \
00074     else if ( (n) < 1000 - EPSILON ) (n) += 100;        \
00075     else if ( (n) < 10000 - EPSILON ) (n) += 1000;      \
00076     else if ( (n) < 100000 - EPSILON ) (n) += 10000;    \
00077     else if ( (n) < 1000000 - EPSILON ) (n) += 100000;  \
00078     else if ( (n) < 10000000 - EPSILON ) (n) *= 2;      \
00079     else (n) = 10000000;
00080 
00081 //===========================================================================
00082 //= CLASE CAMARA                                                            =
00083 //===========================================================================
00084 
00085 //= OPERACIONES BASICAS =====================================================
00086 
00087 CAMARA::CAMARA()
00088 {
00089     // Posicion por defecto
00090     _posicion.x = 2.5;
00091     _posicion.y = 0.5;
00092     _posicion.z = 0.5;
00093 
00094     // Orientacion por defecto
00095     float magnitud = 0;
00096     VECTOR k(0, 0, 1);
00097     _orientacion.importar_angulo_eje(magnitud, k);
00098 
00099     // Las propiedades de la etiqueta
00100     mostrar_etiqueta = FALSE;
00101     transparencia_etiqueta = 1.0;
00102     color_etiqueta.r = 1;
00103     color_etiqueta.g = 1;
00104     color_etiqueta.b = 0;
00105 
00106     // Las demas vainas
00107     _ventana_xtam = _ventana_ytam = 200;
00108     _fov = 60.0;
00109     modo_seguimiento = CAM_GLOBAL;
00110     modo_control = CAM_STANDARD;
00111     _modo_proyeccion = CAM_PERSPECTIVA;
00112     _near_plane = 0.05;
00113     _far_plane = 100;  // OJO: Esto no es igual a 1? (al parecer no!)
00114 
00115     _nombre_padre = NULL;
00116     _Padre = NULL;
00117 
00118     _con_posicion = TRUE;
00119     tipo_modelo = 0;
00120 }
00121 
00122 CAMARA::~CAMARA()
00123 {
00124     if ( _nombre_padre ) delete _nombre_padre;
00125 }
00126 
00127 void
00128 CAMARA::set_far_plane(double f)
00129 {
00130     _far_plane = f;
00131 }
00132 
00133 double
00134 CAMARA::far_plane(void)
00135 {
00136     return _far_plane;
00137 }
00138 
00139 void
00140 CAMARA::set_near_plane(double f)
00141 {
00142     _near_plane = f;
00143 }
00144 
00145 double
00146 CAMARA::near_plane(void)
00147 {
00148     return _near_plane;
00149 }
00150 
00151 VECTOR CAMARA::posicion(void) { return _posicion; }
00152 QUATERNION CAMARA::orientacion(void) { return _orientacion; }
00153 void CAMARA::set_posicion(VECTOR p) { _posicion = p; }
00154 void CAMARA::set_orientacion(QUATERNION o) { _orientacion = o; }
00155 char * CAMARA::nombre_padre(void) { return _nombre_padre; }
00156 void CAMARA::asociar_padre(ENTIDAD *p) { _Padre = p; }
00157 double CAMARA::fov(void) { return _fov; };
00158 
00159 void
00160 CAMARA::set_fov(double in_nuevo_fov)
00161 {
00162     if ( in_nuevo_fov > EPSILON && in_nuevo_fov < 180.0 ) {
00163     _fov = in_nuevo_fov;
00164     }
00165 }
00166 
00167 static QUATERNION TMP_quaternion;
00168 
00169 BOOLEAN
00170 CAMARA::consultar_variable(const char *nombre_variable, int &tipo, void **ref)
00180 {
00181     if ( strcmp(nombre_variable, "posicion") == 0 ) {
00182         tipo = T_VECTOR;    (*ref) = &_posicion;    return TRUE;
00183       }
00184       if ( strcmp(nombre_variable, "orientacion") == 0 ) {
00185         // OJO: Esto toca redefinirlo! Es un la orientacion absoluta!
00186         TMP_quaternion = _orientacion; // = orientacion_absoluta();
00187         tipo = T_QUATERNION;(*ref) = &TMP_quaternion;    return TRUE;
00188       }
00189     ;
00190     return FALSE;
00191 }
00192 
00193 BOOLEAN
00194 CAMARA::minmax_visible(VECTOR esquinas[8])
00209 {
00210     //- Actualice la posicion y orientacion de la camara --------------------
00211     MATRIZ_4x4 R, T1, T2, R1, R2;
00212     QUATERNION p_ori;
00213     VECTOR p_pos(0, 0, 0);
00214     void *interfaz;
00215     int tipo;
00216 
00217     if ( _Padre && _Padre->consultar_variable("posicion", tipo, &interfaz) &&
00218          _con_posicion ) {
00219         if ( tipo == T_VECTOR ) p_pos = (*(VECTOR *)interfaz);
00220     }
00221 
00222     T1.translacion(_posicion.x, _posicion.y, _posicion.z);
00223     T2.translacion(p_pos.x, p_pos.y, p_pos.z);
00224 
00225     R1.importar_quaternion(_orientacion);
00226 
00227     if ( _Padre &&
00228          _Padre->consultar_variable("orientacion_absoluta", tipo, &interfaz) &&
00229          tipo == T_QUATERNION ) {
00230         p_ori = (*(QUATERNION *)interfaz);
00231         R2.importar_quaternion(p_ori);
00232         R = T2 * (R2 * (T1 * R1));
00233       }
00234       else {
00235         R = T2 * (T1 * R1);
00236     }
00237 
00238     //- Calcule los extremos del volumen de visualizacion -------------------
00239     double xn = 1, yn = 1;
00240     double xf = 1, yf = 1;
00241 
00242     if ( _modo_proyeccion != CAM_PARALELA ) {
00243         yn = 2 * _near_plane * tan(DEG2RAD(_fov) / 2);
00244         xn = yn * ((double)_ventana_xtam/(double)_ventana_ytam);
00245     }
00246     else {
00247         if ( _ventana_xtam > _ventana_ytam ) {
00248             xn = 1;
00249             yn = (double)_ventana_ytam / (double)_ventana_xtam;
00250           }
00251           else {
00252             xn = (double)_ventana_xtam / (double)_ventana_ytam;
00253             yn = 1;
00254         }
00255     }
00256 
00257     xf = xn;
00258     yf = yn;
00259     if ( _modo_proyeccion != CAM_PARALELA ) {
00260         yf = 2 * _far_plane * tan(DEG2RAD(_fov) / 2);
00261         xf = yf * ((double)_ventana_xtam/(double)_ventana_ytam);
00262     }
00263 
00264     //- Calcule las ecuaciones de los 6 planos a partir de los extremos -----
00265     VECTOR normales_planos[6];
00266     VECTOR puntos_planos[6];
00267     VECTOR p1, p2, p3;
00268     int i;
00269 
00270     for ( i = 0; i < 6; i++ ) {
00271         switch ( i ) {
00272           case 0:
00273             p1.x = _near_plane; p1.y =  xn/2; p1.z = -yn/2;
00274             p2.x = _near_plane; p2.y = -xn/2; p2.z =  yn/2;
00275             p3.x = _near_plane; p3.y = -xn/2; p3.z = -yn/2;
00276             break;
00277           case 1:
00278             p1.x = _near_plane; p1.y =  xn/2; p1.z =  yn/2;
00279             p2.x = _far_plane;  p2.y =  xf/2; p2.z =  yf/2;
00280             p3.x = _near_plane; p3.y = -xn/2; p3.z =  yn/2;
00281             break;
00282           case 2:
00283             p1.x = _near_plane; p1.y =  xn/2; p1.z = -yn/2;
00284             p2.x = _far_plane;  p2.y =  xf/2; p2.z = -yf/2;
00285             p3.x = _near_plane; p3.y =  xn/2; p3.z =  yn/2;
00286             break;
00287           case 3:
00288             p1.x = _near_plane; p1.y = -xn/2; p1.z = -yn/2;
00289             p2.x = _far_plane;  p2.y = -xf/2; p2.z = -yf/2;
00290             p3.x = _near_plane; p3.y =  xn/2; p3.z = -yn/2;
00291             break;
00292           case 4:
00293             p1.x = _near_plane; p1.y = -xn/2; p1.z = -yn/2;
00294             p2.x = _near_plane; p2.y = -xn/2; p2.z =  yn/2;
00295             p3.x = _far_plane;  p3.y = -xf/2; p3.z = -yf/2;
00296             break;
00297           case 5:
00298             p1.x = _far_plane;  p1.y = -xf/2; p1.z =  yf/2;
00299             p2.x = _far_plane;  p2.y =  xf/2; p2.z = -yf/2;
00300             p3.x = _far_plane;  p3.y = -xf/2; p3.z = -yf/2;
00301             break;
00302           default: break;
00303         }
00304         p1 = R * p1;
00305         p2 = R * p2;
00306         p3 = R * p3;
00307 
00308         normales_planos[i] = ((p2 - p1).producto_cruz(p3 - p1));
00309         normales_planos[i].normalizar();
00310         puntos_planos[i] = p1;
00311     }
00312 
00313     //- A partir de las ecuaciones de planos determino si esta afuera... ----
00314     int j;
00315     BOOLEAN fuera;
00316     VECTOR p;
00317 
00318     for ( i = 0; i < 6; i++ ) {
00319         fuera = TRUE;
00320         for ( j = 0; j < 8; j++ ) {
00321             p = esquinas[j] - puntos_planos[i];
00322             if ( p.producto_punto(normales_planos[i]) > 0 ) {
00323                 fuera = FALSE;
00324                 break;
00325             }
00326         }
00327         if ( fuera ) return FALSE;
00328     }
00329 
00330     return TRUE;
00331 }
00332 
00333 BOOLEAN
00334 CAMARA::proyectar_punto(VECTOR *in_P, double *out_U, double *out_V)
00374 {
00375     //- 1. Preprocesar vista ------------------------------------------------
00376     preprocesar_vista();
00377     (*out_U) = 0;
00378     (*out_V) = 0;
00379 
00380     double factor_fov = ((double)_ventana_xtam/(double)_ventana_ytam);
00381     double machete = 1/tan(DEG2RAD(_fov/2));
00382 
00383     _up.normalizar();
00384     _up = _up * machete;
00385     _right.normalizar();
00386     _right = _right * machete / factor_fov;
00387 
00388     //- 2. Calcular el proyector que pasa por `*in_P` -----------------------
00389     RAYO r;
00390 
00391     r.origen = _pos;
00392     r.direccion = ((*in_P) - _pos);
00393     if ( r.direccion.norma() < EPSILON ) {
00394     return FALSE;
00395     }
00396     r.direccion.normalizar();
00397 
00398     //- 3. Calcular el plano de proyeccion ----------------------------------
00399     double A, B, C, D;
00400     VECTOR normal = _dir*(-1);
00401 
00402     normal.normalizar();
00403     A = normal.x;
00404     B = normal.y;
00405     C = normal.z;
00406     D = -A*(_pos.x+A/2) - B*(_pos.y+B/2) - C*(_pos.z+C/2);
00407 
00408     // El plano es: Ax + By + Cz + D = 0
00409 
00410     //- 4. Calcular P' en coordenadas globales XYZ --------------------------
00411     VECTOR p_prima;
00412     double t;
00413 
00414     t = (A*r.origen.x + B*r.origen.y + C*r.origen.z + D) / 
00415      (A*r.direccion.x + B*r.direccion.y + C*r.direccion.z);
00416 
00417     if ( t < EPSILON ) {
00418     return FALSE;
00419     }
00420 
00421     p_prima = r.origen + r.direccion*t; // Hasta aqui, p_prima esta OK
00422 
00423     //- 5. ------------------------------------------------------------------
00424     VECTOR centro;
00425 
00426     centro = _dir;
00427     centro.normalizar();
00428     centro = centro*_near_plane + _pos;
00429     p_prima = p_prima - centro;
00430 
00431     // Notese que la base u,v es _right,_up
00432     (*out_U) = (p_prima.producto_punto(_right)+0.5);
00433     (*out_V) = (-p_prima.producto_punto(_up)+0.5);
00434 
00435     // OJO: Esta manera de hacer recorte de lineas seguramente es
00436     //      incorrecta!
00437     if ( (*out_U) < -1 || (*out_U) > 2 || 
00438          (*out_V) < -1 || (*out_V) > 2 ) {
00439     return FALSE;
00440     }
00441 
00442     (*out_U) *= _ventana_xtam;
00443     (*out_V) *= _ventana_ytam;
00444 
00445     //-----------------------------------------------------------------------
00446 
00447     return TRUE;
00448 }
00449 
00450 void
00451 CAMARA::preprocesar_vista(void)
00459 {
00460     //- Actualice la posicion y orientacion de la camara --------------------
00461     MATRIZ_4x4 R, T1, T2, R1, R2;
00462     QUATERNION p_ori;
00463     VECTOR p_pos(0, 0, 0);
00464     void *interfaz;
00465     int tipo;
00466 
00467     if ( _Padre && _Padre->consultar_variable("posicion", tipo, &interfaz) &&
00468          _con_posicion ) {
00469         if ( tipo == T_VECTOR ) p_pos = (*(VECTOR *)interfaz);
00470     }
00471 
00472     // OJO:  Sera posible mejorar esto? (i.e. usar menos transformaciones o
00473     //       usar directamente quaternions?)
00474     T1.translacion(-_posicion.x, -_posicion.y, -_posicion.z);
00475     T2.translacion(-p_pos.x, -p_pos.y, -p_pos.z);
00476 
00477     R1.importar_quaternion(_orientacion);
00478 
00479     if ( _Padre &&
00480          _Padre->consultar_variable("orientacion_absoluta", tipo, &interfaz) &&
00481          tipo == T_QUATERNION ) {
00482         p_ori = (*(QUATERNION *)interfaz);
00483         R2.importar_quaternion(p_ori);
00484         R = R1.inversa() * (T1 * (R2.inversa() * T2));
00485       }
00486       else {
00487         R = R1.inversa() * (T1 * T2);
00488     }
00489 
00490     //----------------------------------------------------------------------
00491     MATRIZ_4x4 R_i = R.inversa();
00492     double factor_fov = ((double)_ventana_xtam/(double)_ventana_ytam);
00493 
00494     _right.x = _right.z = 0;
00495     _right.y = -factor_fov * tan(DEG2RAD(_fov/2));
00496     _up.x = _up.y = 0;
00497     _up.z = tan(DEG2RAD(_fov/2));
00498     _dir.x = 0.5; // OJO: Porque 0.5 y no 1.0?
00499     _dir.y = _dir.z = 0;
00500     _pos = _posicion + p_pos;
00501     _dir = R_i * _dir;
00502     _up = R_i * _up;
00503     _right = R_i * _right;
00504 }
00505 
00506 MATRIZ_4x4
00507 CAMARA::calcular_matriz_de_proyeccion(int modo_stereo)
00514 {
00515     //- Actualice la proyeccion ---------------------------------------------
00516     // OJO: Toca entender bien como belcebures es que funciona la matriz de
00517     //      proyeccion en OpenGL! Debe repasarse el esquema de transformacion
00518     //      de vertices (i.e. el capitulo 2.10 de la especificacion de
00519     //      OpenGL 1.1)... y por supuesto... lo basico de esas matrices!
00520     // No sera bueno especificar directamente el glDepthRange y jugar de
00521     // alguna otra manera mas directa con la matriz de proyeccion?
00522     // Tenga en cuenta que _near_plane y _far_plane deben estar entre 0 y 1 (?)
00523     double izq, der, arr, aba, aspecto;
00524     MATRIZ_4x4 P;
00525 
00526     switch ( _modo_proyeccion ) {
00527       case CAM_PARALELA:
00528         P.ortho(-1, 1, -1, 1, _near_plane, _far_plane);
00529         break;
00530       case CAM_PERSPECTIVA: default:
00531         // Equivale a gluPerspective(_fov,
00532         //     (double)_ventana_xtam/(double)_ventana_ytam, 
00533         //     _near_plane, _far_plane);
00534         aspecto = (double)_ventana_xtam/(double)_ventana_ytam;
00535         arr = _near_plane * tan(_fov * PI / 360.0);
00536         aba = -arr;
00537         izq = aspecto * aba;
00538         der = aspecto * arr;
00539         P.frustum(izq, der, aba, arr, _near_plane, _far_plane);
00540         break;
00541     }
00542 
00543     //- Actualice la posicion y orientacion de la camara --------------------
00544     MATRIZ_4x4 R, T1, T2, R1, R_adic2, R_adic1, R2, Tstereo;
00545     QUATERNION p_ori;
00546     VECTOR p_pos(0, 0, 0), pstereo;
00547     void *interfaz;
00548     int tipo;
00549     double factor_distancia_entre_ojos = 0.04;
00550 
00551     if ( _Padre && _Padre->consultar_variable("posicion", tipo, &interfaz) &&
00552          _con_posicion ) {
00553         if ( tipo == T_VECTOR ) p_pos = (*(VECTOR *)interfaz);
00554     }
00555 
00556     // Nota: la rotacion adicional `R_adic1*R_adic2` convierte la orientacion
00557     //       por defecto AQUYNZA (una camara en el origen mirando en la
00558     //       direccion <1, 0, 0> con vector arriba <0, 0, 1>) a la orientacion
00559     //       por defecto OpenGL (una camara mirando hacia el origen, desde
00560     //       <0, 0, 1> con arriba <0, 1, 0>).
00561     // OJO:  Sera posible mejorar esto? (i.e. usar menos transformaciones o
00562     //       usar directamente quaternions?)
00563 
00564     R1.importar_quaternion(_orientacion);
00565 
00566     T1.translacion(-_posicion.x, -_posicion.y, -_posicion.z);
00567     T2.translacion(-p_pos.x, -p_pos.y, -p_pos.z);
00568 
00569     R_adic2.rotacion_eje(DEG2RAD(90), 0, 0, 1);
00570     R_adic1.rotacion_eje(DEG2RAD(-90), 1, 0, 0);
00571 
00572     if ( _Padre &&
00573          _Padre->consultar_variable("orientacion_absoluta", tipo, &interfaz) &&
00574          tipo == T_QUATERNION ) {
00575         p_ori = (*(QUATERNION *)interfaz);
00576         R2.importar_quaternion(p_ori);
00577         R = R1.inversa() * (T1 * (R2.inversa() * T2));
00578       }
00579       else {
00580         R = R1.inversa() * (T1 * T2);
00581     }
00582 
00583     R = R_adic1 * (R_adic2 * R); // Rotacion adicional
00584 
00585     if ( modo_stereo == 1 ) {
00586         pstereo.x = -R.M[0][0] * factor_distancia_entre_ojos;
00587         pstereo.y = -R.M[0][1] * factor_distancia_entre_ojos;
00588         pstereo.z = -R.M[0][2] * factor_distancia_entre_ojos;
00589         Tstereo.translacion(pstereo.x, pstereo.y, pstereo.z);
00590         R = R * Tstereo;
00591     }
00592     if ( modo_stereo == 2 ) {
00593         pstereo.x = R.M[0][0] * factor_distancia_entre_ojos;
00594         pstereo.y = R.M[0][1] * factor_distancia_entre_ojos;
00595         pstereo.z = R.M[0][2] * factor_distancia_entre_ojos;
00596         Tstereo.translacion(pstereo.x, pstereo.y, pstereo.z);
00597         R = R * Tstereo;
00598     }
00599 
00600     R = P * R;
00601     return R;
00602 }
00603 
00604 //= OPERACIONES DE VISUALIZACION (REPRESENTACION GEOMETRICA) ================
00605 
00606 #ifdef GL_ENABLED
00607 
00608 void
00609 CAMARA::pintar_base_gl(void)
00610 {
00611     VECTOR o(0, 0, 0);
00612     VECTOR i(1, 0, 0);
00613     VECTOR j(0, 1, 0);
00614     VECTOR k(0, 0, 1);
00615 
00616     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00617     glDisable(GL_LIGHTING);
00618     glDisable(GL_TEXTURE_2D);
00619     glShadeModel(GL_FLAT);
00620     glColor3f(1, 0, 0);    PINTAR_VECTOR_GL(o, i, 0.05, 0.3, 0.1);
00621     glColor3f(0, 1, 0);    PINTAR_VECTOR_GL(o, j, 0.05, 0.3, 0.1);
00622     glColor3f(0, 0, 1);    PINTAR_VECTOR_GL(o, k, 0.05, 0.3, 0.1);
00623 }
00624 
00625 void
00626 CAMARA::pintar_volumen_gl(void)
00627 {
00628 //    printf("[!]"); fflush(stdout);
00629 
00630     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00631     glDisable(GL_LIGHTING);
00632     glDisable(GL_TEXTURE_2D);
00633     glShadeModel(GL_FLAT);
00634 
00635     //- Calcule los extremos del volumen de visualizacion -------------------
00636     double xn = 1, yn = 1;
00637     double xf = 1, yf = 1;
00638 
00639     if ( _modo_proyeccion != CAM_PARALELA ) {
00640         yn = 2 * _near_plane * tan(DEG2RAD(_fov) / 2);
00641         xn = yn * ((double)_ventana_xtam/(double)_ventana_ytam);
00642     }
00643     else {
00644         if ( _ventana_xtam > _ventana_ytam ) {
00645             xn = 1;
00646             yn = (double)_ventana_ytam / (double)_ventana_xtam;
00647           }
00648           else {
00649             xn = (double)_ventana_xtam / (double)_ventana_ytam;
00650             yn = 1;
00651         }
00652     }
00653 
00654     xf = xn;
00655     yf = yn;
00656     if ( _modo_proyeccion != CAM_PARALELA ) {
00657         yf = 2 * _far_plane * tan(DEG2RAD(_fov) / 2);
00658         xf = yf * ((double)_ventana_xtam/(double)_ventana_ytam);
00659     }
00660 
00661     //- Genere las primitivas que muestran el volumen de visualizacion ------
00662     glColor3f(1, 0.5, 0.5);   // Origen de la camara
00663     glBegin(GL_POINTS);
00664         glVertex3d(0, 0, 0);
00665     glEnd();
00666 
00667     glDisable(GL_LIGHTING);
00668     glColor3f(0, 1, 1);       // Plano de proyeccion
00669     glBegin(GL_LINE_LOOP);
00670         glVertex3d(_near_plane, -xn/2, -yn/2);
00671         glVertex3d(_near_plane, xn/2, -yn/2);
00672         glVertex3d(_near_plane, xn/2, yn/2);
00673         glVertex3d(_near_plane, -xn/2, yn/2);
00674     glEnd();
00675     glBegin(GL_LINES);
00676         glVertex3d(_near_plane, -xn/10, -yn/10);
00677         glVertex3d(_near_plane, xn/10, yn/10);
00678         glVertex3d(_near_plane, xn/10, -yn/10);
00679         glVertex3d(_near_plane, -xn/10, yn/10);
00680         glVertex3d(_near_plane, -xn/10, yn/2);
00681         glVertex3d(_near_plane, 0, yn/2+yn/10);
00682         glVertex3d(_near_plane, 0, yn/2+yn/10);
00683         glVertex3d(_near_plane, xn/10, yn/2);
00684     glEnd();
00685 
00686     glColor3f(0, 1, 1);       // Plano lejano
00687     glBegin(GL_LINE_LOOP);
00688         glVertex3d(_far_plane, -xf/2, -yf/2);
00689         glVertex3d(_far_plane, xf/2, -yf/2);
00690         glVertex3d(_far_plane, xf/2, yf/2);
00691         glVertex3d(_far_plane, -xf/2, yf/2);
00692     glEnd();
00693     glBegin(GL_LINES);
00694         glVertex3d(_far_plane, -xf/10, -yf/10);
00695         glVertex3d(_far_plane, xf/10, yf/10);
00696         glVertex3d(_far_plane, xf/10, -yf/10);
00697         glVertex3d(_far_plane, -xf/10, yf/10);
00698         glVertex3d(_far_plane, -xf/10, yf/2);
00699         glVertex3d(_far_plane, 0, yf/2+yf/10);
00700         glVertex3d(_far_plane, 0, yf/2+yf/10);
00701         glVertex3d(_far_plane, xf/10, yf/2);
00702     glEnd();
00703 
00704     glBegin(GL_LINES);  // Lineas de los bordes
00705         glVertex3d(_near_plane, -xn/2, -yn/2);
00706         glVertex3d(_far_plane, -xf/2, -yf/2);
00707         glVertex3d(_near_plane, xn/2, -yn/2);
00708         glVertex3d(_far_plane, xf/2, -yf/2);
00709         glVertex3d(_near_plane, xn/2, yn/2);
00710         glVertex3d(_far_plane, xf/2, yf/2);
00711         glVertex3d(_near_plane, -xn/2, yn/2);
00712         glVertex3d(_far_plane, -xf/2, yf/2);
00713     glEnd();
00714 }
00715 
00716 void
00717 CAMARA::set_modelo(int val)
00724 {
00725     tipo_modelo = val;
00726 }
00727 
00728 int
00729 CAMARA::modelo(void)
00730 {
00731     return tipo_modelo;
00732 }
00733 
00734 void
00735 CAMARA::pintar_gl(void)
00742 {
00743     if ( !tipo_modelo ) return;
00744 
00745     //- Actualice la posicion y orientacion de la camara --------------------
00746     MATRIZ_4x4 R, T1, T2, R1, R2;
00747     QUATERNION p_ori;
00748     VECTOR p_pos(0, 0, 0);
00749     void *interfaz;
00750     int tipo;
00751 
00752     if ( _Padre && _Padre->consultar_variable("posicion", tipo, &interfaz) &&
00753          _con_posicion ) {
00754         if ( tipo == T_VECTOR ) p_pos = (*(VECTOR *)interfaz);
00755     }
00756 
00757     T1.translacion(_posicion.x, _posicion.y, _posicion.z);
00758     T2.translacion(p_pos.x, p_pos.y, p_pos.z);
00759 
00760     R1.importar_quaternion(_orientacion);
00761 
00762     if ( _Padre &&
00763          _Padre->consultar_variable("orientacion_absoluta", tipo, &interfaz) &&
00764          tipo == T_QUATERNION ) {
00765         p_ori = (*(QUATERNION *)interfaz);
00766         R2.importar_quaternion(p_ori);
00767         R = T2 * (R2 * (T1 * R1));
00768       }
00769       else {
00770         R = T2 * (T1 * R1);
00771     }
00772 
00773     //-----------------------------------------------------------------------
00774     glPushMatrix();
00775     R.cargar_gl(); 
00776     switch ( tipo_modelo ) {
00777       case 1: pintar_base_gl(); break;
00778       case 2: default: pintar_volumen_gl();
00779     }
00780     glPopMatrix();
00781 }
00782 
00783 #endif // GL_ENABLED
00784 
00785 //= OPERACIONES DE VISUALIZACION (ACTIVACION) ===============================
00786 
00787 #ifdef GL_ENABLED
00788 
00789 void
00790 CAMARA::activar_gl(int modo_stereo)
00807 {
00808     MATRIZ_4x4 R;
00809 
00810     //- En esta funcion se altera la projeccion OpenGL... -------------------
00811     glMatrixMode(GL_PROJECTION);
00812     glLoadIdentity();
00813 
00814     R = calcular_matriz_de_proyeccion(modo_stereo);
00815     R.cargar_gl(); // Notese que NO se usa gluLookat, pero se hace lo mismo!
00816 
00817 //#define TEMPORAL 1
00818 #ifdef TEMPORAL
00819     MATRIZ_4x4 T;
00820 
00821     T.importar_gl();
00822     T.imprimir();
00823 #endif
00824 
00825     //- ... y el resto de AQUYNZA solo toca el modelo! ----------------------
00826     glMatrixMode(GL_MODELVIEW);
00827 }
00828 
00829 void
00830 CAMARA::activar_centro_gl(void)
00837 {
00838     VECTOR p = _posicion;
00839 
00840     _posicion.x = _posicion.y = _posicion.z = 0;
00841     _con_posicion = FALSE;
00842     activar_gl();
00843     _con_posicion = TRUE;
00844     _posicion = p;
00845 }
00846 
00847 void
00848 CAMARA::subbillboard_gl(int tam, int x, int y, int dx, int dy, int cuadre)
00863 {
00864     int x_tam, y_tam, delta_x = 0, delta_y = 0, ancho_cuadrito, alto_cuadrito;
00865 
00866     if ( _ventana_xtam < _ventana_ytam ) {
00867         if ( cuadre == 0 ) delta_y = (_ventana_ytam - _ventana_xtam)/2;
00868         if ( cuadre > 0 ) delta_y = _ventana_ytam - _ventana_xtam;
00869         x_tam = y_tam = _ventana_xtam;
00870       }
00871       else {
00872         if ( cuadre == 0 ) delta_x = (_ventana_xtam - _ventana_ytam)/2;
00873         if ( cuadre > 0 ) delta_x = _ventana_xtam - _ventana_ytam;
00874         x_tam = y_tam = _ventana_ytam;
00875     }
00876     ancho_cuadrito = x_tam/tam;
00877     alto_cuadrito = y_tam/tam;
00878 
00879     glViewport(delta_x + x*ancho_cuadrito, delta_y + y*alto_cuadrito,
00880                dx*ancho_cuadrito - 1, dy*alto_cuadrito - 1);
00881 
00882     glMatrixMode(GL_PROJECTION);
00883     glLoadIdentity();
00884     glMatrixMode(GL_MODELVIEW);
00885     glLoadIdentity();
00886 }
00887 
00888 double
00889 CAMARA::factor_font(void)
00890 {
00891     return 1/(6.25*_ventana_xtam);
00892 }
00893 
00894 void
00895 CAMARA::billboard_gl(int tipo)
00916 {
00917     //- Pinte la etiqueta en el billboard -----------------------------------
00918   #ifndef GLTT_ENABLED
00919     static BOOLEAN advertido = FALSE;
00920     if ( mostrar_etiqueta && !advertido ) {
00921         fprintf(stderr, "<CAMARA> Warning: tengo la etiqueta %s\n"
00922                "pero no se puede mostrar por que AQUYNZA se compilo sin la\n"
00923                "libreria libgltt.\n", nombre());
00924         fflush(stderr);
00925         advertido = TRUE;
00926     }
00927   #endif
00928   #ifdef GLTT_ENABLED
00929     static FTFace *font = NULL;
00930     static GLTTFont* vector_font = NULL;
00931     int llx, lly, urx, ury;
00932     float factor = (float)(factor_font());
00933 
00934     if ( mostrar_etiqueta ) {
00935         //- Preparativos OpenGL -
00936         glViewport(0, _ventana_ytam - _ventana_xtam, _ventana_xtam, _ventana_xtam);
00937         glMatrixMode(GL_PROJECTION);    glLoadIdentity();
00938         glMatrixMode(GL_MODELVIEW);     glLoadIdentity();
00939         glDisable(GL_LIGHTING);         glDisable(GL_DEPTH_TEST);
00940 
00941         //- Inicializacion del raster de letras -
00942         font = chequear_fuente("./etc/fonts/crystal.ttf");
00943         if ( !font ) {
00944             fprintf(stderr,
00945                 "<CAMARA> - Error fatal: No encuentro una truetype font!\n");
00946             fflush(stderr);
00947             exit(1);
00948         }
00949         if ( !vector_font ) {
00950             vector_font = new GLTTFont(font);
00951         }
00952         // OJO: Esto deberia hacerce una vez por vista?
00953         static int num_vistas = 2;
00954         if ( num_vistas > 0 ) {
00955             if ( !vector_font->create(150) ) {
00956                 fprintf(stderr,"<CAMARA> ERROR fatal: "
00957                     "no puedo crear una fuente GLTT");
00958                 fflush(stderr);
00959                 exit(1);
00960             }
00961             num_vistas--;
00962         }
00963 
00964         //---
00965         ACTIVAR_TRANSPARENCIA(transparencia_etiqueta);
00966 
00967         //- Generacion de primitivas para la letra y el cuadro -
00968         vector_font->getBBox(nombre(), llx, lly, urx, ury);
00969         double dy = ((double)ury) * factor;
00970 
00971         glColor4d(color_etiqueta.r, color_etiqueta.g, color_etiqueta.b,
00972                   (double)transparencia_etiqueta);
00973         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Pinta borde
00974         glRectd(-0.99, 0.99 - 60*factor - dy*1.2, 0.99, 0.99);
00975 
00976         glTranslatef(-((float)urx/2)*factor,
00977                      0.99f - 40*factor - (float)dy, 0.0f);
00978         glScalef(factor, factor, factor);
00979 
00980         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Pinta etiqueta
00981         vector_font->output(nombre());
00982 
00983         glDisable(GL_BLEND);
00984     }
00985   #endif
00986 
00987     //- Programe el estado descrito en la documentacion del metodo ----------
00988     int delta;
00989 
00990     switch ( tipo ) {
00991       case CAM_NO_CUADRAR:
00992         glViewport(0, 0, _ventana_xtam, _ventana_ytam);
00993         break;
00994       case CAM_CUADRAR_X:
00995         delta = (_ventana_ytam - _ventana_xtam)/2;
00996         glViewport(0, delta, _ventana_xtam, _ventana_xtam);
00997         break;
00998       case CAM_CUADRAR_Y:
00999         delta = (_ventana_xtam - _ventana_ytam)/2;
01000         glViewport(delta, 0, _ventana_ytam, _ventana_ytam);
01001         break;
01002       case CAM_CUADRAR_MENOR: default:
01003         if ( _ventana_xtam < _ventana_ytam ) {
01004             delta = (_ventana_ytam - _ventana_xtam)/2;
01005             glViewport(0, delta, _ventana_xtam, _ventana_xtam);
01006           }
01007           else {
01008             delta = (_ventana_xtam - _ventana_ytam)/2;
01009             glViewport(delta, 0, _ventana_ytam, _ventana_ytam);
01010         }
01011         break;
01012     }
01013     glMatrixMode(GL_PROJECTION);    glLoadIdentity();
01014     glMatrixMode(GL_MODELVIEW);     glLoadIdentity();
01015 }
01016 #endif // GL_ENABLED
01017 
01018 void
01019 CAMARA::activar_povray(FILE *fd)
01027 {
01028     preprocesar_vista();
01029 
01030     // OJO: El orden es importante, NO reorganice los parametros!
01031     fprintf(fd,
01032 "\n//- Especificacion de la camara ----------------------------------------\n"
01033         "camera {\n"
01034         "    location <%f, %f, %f>\n"
01035         "    direction <%f, %f, %f>\n"
01036         "    up <%f, %f, %f>\n"
01037         "    right <%f, %f, %f>\n"
01038         "}\n",
01039         _pos.x, _pos.y, _pos.z,
01040         _dir.x, _dir.y, _dir.z,
01041         _up.x, _up.y, _up.z,
01042         _right.x, _right.y, _right.z // OJO: .y negado!
01043     );
01044 
01045 }
01046 
01047 //= OPERACIONES DE SOPORTE AL MANEJO GUI ====================================
01048 
01049 void
01050 CAMARA::imprimir(void)
01051 {
01052     double yaw, pitch, roll;
01053     MATRIZ_4x4 R;
01054     float h, m, s, gg, mm, ss;
01055 
01056     R.importar_quaternion(_orientacion);
01057     R.exportar_angulos_euler(&yaw, &pitch, &roll);
01058     clrscr();
01059 
01060 
01061     printf("<CAMARA \"%s\">:\n", nombre());
01062 
01063     if ( _modo_proyeccion == CAM_PERSPECTIVA ) {
01064         printf("  - Camara en modo de proyeccion PERSPECTIVA\n");
01065       }
01066       else if ( _modo_proyeccion == CAM_PARALELA ) {
01067         printf("  - Camara en modo de proyeccion PARALELA\n");
01068       }
01069       else {
01070         printf("  - Camara en modo de proyeccion DESCONOCIDO\n");
01071       }
01072     ;
01073 
01074     printf("  - posision(x, y, z) = <%.2f, %.2f, %.2f>\n"
01075            "  - orientacion(yaw, pitch, roll) = <%.2f, %.2f, %.2f> (en grados)\n",
01076     _posicion.x, _posicion.y, _posicion.z,
01077         RAD2DEG(yaw), RAD2DEG(pitch), RAD2DEG(roll));
01078 
01079     //if ( _fov <= 10 ) {
01080         DEG2hms(RAD2DEG(yaw), &h, &m, &s);
01081         DEG2gms(RAD2DEG(pitch), &gg, &mm, &ss);
01082         printf(
01083          "    . Orientacion precisa: RA<%2.0f:%2.0f:%.2f> DEC<%3.0f:%2.0f:%.2f>\n",
01084             h, m, s, gg, mm, ss);
01085     //}
01086 
01087     preprocesar_vista();
01088     printf("    . Vector UP = <%.2f, %.2f, %.2f>\n", 
01089        _up.x, _up.y, _up.z);
01090 
01091     printf("  - fov = %.2f\n"
01092        "  - _near_plane = %.4f\n"
01093        "  - _far_plane = %.4f\n",
01094         _fov, _near_plane, _far_plane);
01095 
01096     fflush(stdout);
01097 }
01098 
01099 BOOLEAN
01100 CAMARA::procesar_teclado(EVENTO_GUI *e)
01111 {
01112     double yaw, pitch, roll;
01113     double inc;
01114     MATRIZ_4x4 R;
01115 
01116 #define INICIO_EULER() \
01117     R.importar_quaternion(_orientacion); \
01118     R.exportar_angulos_euler(&yaw, &pitch, &roll);
01119 
01120 #define FIN_EULER() \
01121     R.rotacion_angulos_euler(yaw, pitch, roll); \
01122     _orientacion = R.exportar_quaternion(); \
01123     break;
01124 
01125     // Defino el incremento angular en funcion del fov
01126     if ( _fov > 90 ) inc = DEG2RAD(10);
01127     else if ( _fov > 45 ) inc = DEG2RAD(5);
01128     else if ( _fov > 15 ) inc = DEG2RAD(2.5);
01129     else if ( _fov > 5 ) inc = DEG2RAD(1);
01130     else inc = DEG2RAD(0.1);
01131 
01132     switch( e->key_code ) {
01133 //- Comportamiento pseudo-avion (modificacion por angulos Euler) ------------
01134   case JK_RIGHT:    INICIO_EULER();
01135     yaw -= inc;
01136     while ( yaw < DEG2RAD(0) ) yaw += DEG2RAD(360);
01137     FIN_EULER();
01138   case JK_LEFT:    INICIO_EULER();
01139     yaw += inc;
01140     while ( yaw >= DEG2RAD(360) ) yaw -= DEG2RAD(360);
01141     FIN_EULER();
01142   case JK_s:    INICIO_EULER();
01143     roll += DEG2RAD(5);
01144     while ( roll > DEG2RAD(360) ) roll -= DEG2RAD(360);
01145     FIN_EULER();
01146   case JK_S:    INICIO_EULER();
01147     roll -= DEG2RAD(5);
01148     while ( roll < 0 ) roll += DEG2RAD(360);
01149     FIN_EULER();
01150   case JK_UP:    INICIO_EULER();
01151     pitch -= inc;
01152     if ( pitch < DEG2RAD(-90) ) pitch = DEG2RAD(-90);
01153     FIN_EULER();
01154   case JK_DOWN:    INICIO_EULER();
01155     pitch += inc;
01156     if ( pitch > DEG2RAD(90) ) pitch = DEG2RAD(90);
01157     FIN_EULER();
01158 
01159 //---------------------------------------------------------------------------
01160   case JK_x:        _posicion.x -= 0.25; break;
01161   case JK_X:        _posicion.x += 0.25; break;
01162   case JK_y:        _posicion.y -= 0.25; break;
01163   case JK_Y:        _posicion.y += 0.25; break;
01164   case JK_z:        _posicion.z -= 0.25; break;
01165   case JK_Z:        _posicion.z += 0.25; break;
01166 
01167   case JK_A:
01168     if ( _fov < 0.1 - EPSILON ) _fov += 0.1;
01169     else if ( _fov < 1 - EPSILON ) _fov++;
01170     else if ( _fov < 175 - EPSILON ) _fov += 5;
01171     break;
01172   case JK_a:
01173     if ( _fov > 5 + EPSILON ) _fov -= 5;
01174     else if ( _fov > 1 + EPSILON  ) _fov--;
01175     else if ( _fov > 0.1 + EPSILON  ) _fov -= 0.1;
01176     break;
01177 
01178   case JK_p: // Rote el modo de proyeccion
01179     switch ( _modo_proyeccion ) {
01180       case CAM_PERSPECTIVA: _modo_proyeccion = CAM_PARALELA; break;
01181       default: _modo_proyeccion = CAM_PERSPECTIVA; break;
01182     }
01183     break;
01184 
01185   case JK_e: // Active/desactive las etiquetas
01186     if ( mostrar_etiqueta ) {
01187         mostrar_etiqueta = FALSE; 
01188       }
01189       else {
01190         mostrar_etiqueta = TRUE;
01191     }
01192     break;
01193 
01194   case JK_m: // Rote el modo de control de camara
01195     switch ( modo_control ) {
01196       case CAM_STANDARD: modo_control = CAM_VUELO; break;
01197       default: modo_control = CAM_STANDARD; break;
01198     }
01199     break;
01200 
01201   case JK_i: // Imprime el estado de la camara :-)
01202     imprimir();
01203     break;
01204 
01205   case JK_N:    AUMENTAR(_near_plane);    imprimir();    break;
01206   case JK_n:    DISMINUIR(_near_plane);   imprimir();    break;
01207   case JK_F:    AUMENTAR(_far_plane);    imprimir();    break;
01208   case JK_f:    DISMINUIR(_far_plane);   imprimir();    break;
01209 
01210 //---------------------------------------------------------------------------
01211   default:  return FALSE;
01212     }
01213     return TRUE;
01214 }
01215 
01216 BOOLEAN
01217 CAMARA::procesar_mouse(EVENTO_GUI *e)
01220 {
01221     static BOOLEAN mover_plano_viz = FALSE;
01222     static BOOLEAN girar_plano_viz = FALSE;
01223     static BOOLEAN avanzar = FALSE;
01224     MATRIZ_4x4 R, S;
01225     VECTOR u, v, w;
01226     double ax, ay;
01227 
01228     if ( e->mouse_delta_x > 5 ) e->mouse_delta_x = 5;
01229     if ( e->mouse_delta_x < -5 ) e->mouse_delta_x = -5;
01230     if ( e->mouse_delta_y > 5 ) e->mouse_delta_y = 5;
01231     if ( e->mouse_delta_y < -5 ) e->mouse_delta_y = -5;
01232     if ( e->tipo_de_evento == ETYPE_BUTTON_DOWN ) {
01233         mover_plano_viz = FALSE;
01234         girar_plano_viz = FALSE;
01235         avanzar = FALSE;
01236         if ( e->mouse_button_mask & 0x01 ) girar_plano_viz = TRUE;
01237         if ( e->mouse_button_mask & 0x02 ) mover_plano_viz = TRUE;
01238         if ( e->mouse_button_mask & 0x04 ||
01239              e->mouse_button_mask == 0x03 ) avanzar = TRUE;
01240       }
01241       else if ( e->tipo_de_evento == ETYPE_BUTTON_UP ) {
01242         mover_plano_viz = FALSE;
01243         girar_plano_viz = FALSE;
01244         avanzar = FALSE;
01245       }
01246       else {
01247         R.importar_quaternion(_orientacion);
01248         u.x = R.M[0][0];    u.y = R.M[1][0];    u.z = R.M[2][0];
01249         v.x = R.M[0][1];    v.y = R.M[1][1];    v.z = R.M[2][1];
01250         w.x = R.M[0][2];    w.y = R.M[1][2];    w.z = R.M[2][2];
01251         if ( mover_plano_viz ) {
01252             _posicion = _posicion - v * (0.1*((double)e->mouse_delta_x));
01253             _posicion = _posicion - w * (0.1*((double)e->mouse_delta_y));
01254         }
01255         if ( avanzar ) {
01256             //_posicion = _posicion - v * (0.1*((double)e->mouse_delta_x));
01257             _posicion = _posicion - u * (0.1*((double)e->mouse_delta_y));
01258         }
01259         if ( girar_plano_viz ) {
01260             ax = MINIMO(-(0.01*((double)e->mouse_delta_x)), 2);
01261             ay = MINIMO((0.01*((double)e->mouse_delta_y)), 2);
01262 
01263             S.rotacion_eje(ay, v.x, v.y, v.z);
01264             R = S * R;
01265 
01266             S.rotacion_eje(ax, 0, 0, 1);
01267             R = S * R;
01268 
01269             _orientacion = R.exportar_quaternion();
01270             _orientacion.normalizar();
01271             //imprimir();
01272         }
01273     }
01274     ;
01275     return TRUE;
01276 }
01277 
01278 void
01279 CAMARA::procesar_resize(int xtam, int ytam)
01280 {
01281     _ventana_xtam = xtam;
01282     _ventana_ytam = ytam;
01283 }
01284 
01285 //= SERVICIOS DE PERSISTENCIA ===============================================
01286 
01287 BOOLEAN
01288 CAMARA::leer(TOKENIZADOR *Sabiondo)
01289 {
01290     char cad[1000];
01291     int tipo_token = TK_DESCONOCIDO, pos;
01292     VECTOR direccion;
01293     double magnitud, yaw, pitch, roll;
01294     MATRIZ_4x4 R;
01295 
01296     //- Ejecute el parser especifico de la COSA_RIGIDA -----------------
01297     pos = 1;
01298     while ( tipo_token != TK_CERRAR) {
01299         tipo_token = Sabiondo->siguiente_token(cad);
01300         switch ( pos ) {
01301             case 1:
01302               ESPERO(TK_CADENA, "una cadena");
01303               if ( strlen(cad) > MAX_CAD-1 ) cad[MAX_CAD-1] = '\0'; 
01304               des_comille(cad);
01305               set_nombre(cad);
01306               pos++;
01307               break;
01308             case 2:  ESPERO(TK_ABRIR, "\"{\"");  pos++; break;
01309             default:
01310               if ( tipo_token == TK_CERRAR ) break;
01311               ESPERO(TK_IDENTIFICADOR, "un identificador (3)");
01312               if ( strcmp(cad, "posicion") == 0 ) {
01313                   tipo_token = Sabiondo->siguiente_token(cad);
01314                   ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
01315                   _posicion.x = atof(&cad[1]);
01316                   tipo_token = Sabiondo->siguiente_token(cad);
01317                   ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
01318                   _posicion.y = atof(cad);
01319                   tipo_token = Sabiondo->siguiente_token(cad);
01320                   ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
01321                   cad[strlen(cad) - 1] = '\0';
01322                   _posicion.z = atof(cad);
01323                 }
01324                 else if ( strcmp(cad, "orientacion") == 0 ) {
01325                   tipo_token = Sabiondo->siguiente_token(cad);
01326                   ESPERO(TK_NUMERO, "un numero (magnitud de rotacion)");
01327                   magnitud = DEG2RAD(atof(cad));  // OJO: Y este signo que?
01328                   tipo_token = Sabiondo->siguiente_token(cad);
01329                   ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
01330                   direccion.x = atof(&(cad[1]));
01331                   tipo_token = Sabiondo->siguiente_token(cad);
01332                   ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
01333                   direccion.y = atof(cad);
01334                   tipo_token = Sabiondo->siguiente_token(cad);
01335                   ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
01336                   cad[strlen(cad) - 1] = '\0';
01337                   direccion.z = atof(cad);
01338                   direccion.normalizar();
01339                   _orientacion.importar_angulo_eje(magnitud, direccion);
01340                 }
01341                 else if ( strcmp(cad, "orientacion_euler") == 0 ) {
01342                   tipo_token = Sabiondo->siguiente_token(cad);
01343                   ESPERO(TK_VECTOR_INICIO, "el inicio de un VECTOR");
01344                   yaw = DEG2RAD(atof(&(cad[1])));
01345                   tipo_token = Sabiondo->siguiente_token(cad);
01346                   ESPERO(TK_NUMERO, "un numero (dato 2 de un VECTOR)");
01347                   pitch = DEG2RAD(atof(cad));
01348                   tipo_token = Sabiondo->siguiente_token(cad);
01349                   ESPERO(TK_VECTOR_FIN, "el final de un VECTOR");
01350                   cad[strlen(cad) - 1] = '\0';
01351                   roll = DEG2RAD(atof(cad));
01352                   R.rotacion_angulos_euler(yaw, pitch, roll);
01353                   _orientacion = R.exportar_quaternion();
01354                 }
01355                 else if ( strcmp(cad, "fov") == 0 ) {
01356                     tipo_token = Sabiondo->siguiente_token(cad);
01357                     ESPERO(TK_NUMERO, "un numero");
01358                     _fov = atof(cad);
01359                 }
01360                 else if ( strcmp(cad, "far_plane") == 0 ) {
01361                     tipo_token = Sabiondo->siguiente_token(cad);
01362                     ESPERO(TK_NUMERO, "un numero");
01363                     _far_plane = atof(cad);
01364                 }
01365                 else if ( strcmp(cad, "near_plane") == 0 ) {
01366                     tipo_token = Sabiondo->siguiente_token(cad);
01367                     ESPERO(TK_NUMERO, "un numero");
01368                     _near_plane = atof(cad);
01369                 }
01370                 else if ( strcmp(cad, "tipo_modelo") == 0 ) {
01371                     tipo_token = Sabiondo->siguiente_token(cad);
01372                     ESPERO(TK_NUMERO, "un numero");
01373                     tipo_modelo = (int)floor(atof(cad));
01374                 }
01375                 else if ( strcmp(cad, "mostrar_etiqueta") == 0 ) {
01376                     tipo_token = Sabiondo->siguiente_token(cad);
01377                     ESPERO(TK_IDENTIFICADOR, "TRUE o FALSE");
01378                     if ( strcmp(cad, "TRUE") == 0 ) mostrar_etiqueta = TRUE;
01379                     else mostrar_etiqueta = FALSE;
01380                 }
01381                 else if ( strcmp(cad, "proyeccion") == 0 ) {
01382                     tipo_token = Sabiondo->siguiente_token(cad);
01383                     ESPERO(TK_IDENTIFICADOR, "PERSPECTIVA o PARALELA");
01384                     if ( strcmp(cad, "PARALELA") == 0 )
01385                         _modo_proyeccion = CAM_PARALELA;
01386                     else _modo_proyeccion = CAM_PERSPECTIVA;
01387                 }
01388                 else if ( strcmp(cad, "transparencia_etiqueta") == 0 ) {
01389                     tipo_token = Sabiondo->siguiente_token(cad);
01390                     ESPERO(TK_NUMERO, "un numero entre 0 y 1");
01391                     transparencia_etiqueta = atof(cad);
01392                 }
01393                 else if ( strcmp(cad, "color_etiqueta") == 0 ) {
01394                   tipo_token = Sabiondo->siguiente_token(cad);
01395                   ESPERO(TK_VECTOR_INICIO, "el inicio de un COLOR");
01396                   color_etiqueta.r = (float)atof(&cad[1]);
01397                   tipo_token = Sabiondo->siguiente_token(cad);
01398                   ESPERO(TK_NUMERO, "un numero (dato 2 de un COLOR)");
01399                   color_etiqueta.g = (float)atof(cad);
01400                   tipo_token = Sabiondo->siguiente_token(cad);
01401                   ESPERO(TK_VECTOR_FIN, "el final de un COLOR");
01402                   cad[strlen(cad) - 1] = '\0';
01403                   color_etiqueta.b = (float)atof(cad);
01404                 }
01405                 else if ( strcmp(cad, "padre") == 0 ) {
01406                     tipo_token = Sabiondo->siguiente_token(cad);
01407                     ESPERO(TK_CADENA, "el nombre de una cosa padre");
01408                     des_comille(cad);
01409                     _nombre_padre = new char[strlen(cad) + 1];
01410                     if ( !_nombre_padre ) {
01411                         fprintf(stderr, "<CAMARA> - ERROR: No hay memoria!\n");
01412                         fflush(stderr);
01413                         return FALSE;
01414                     }
01415                     strcpy(_nombre_padre, cad);
01416                 }
01417               ;
01418               break;
01419         }
01420     }
01421 
01422     return TRUE;
01423 }
01424 
01425 //===========================================================================
01426 //= EOF                                                                     =
01427 //===========================================================================
01428 

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.