Toolkits – RVA Solución 4: /******************************************************** * * Este programa permite visualizar ficheros iv (vrml) * ********************************************************/ //Según el sistema operativo en el que compilemos el código //utilizaremos una librería de componentes u otra #ifdef WIN32 //WINDOWS #include <Inventor/Win/SoWin.h> #include <Inventor/Win/viewers/SoWinExaminerViewer.h> #else //LINUX #include <Inventor/Xt/SoXt.h> #include <Inventor/Xt/viewers/SoXtExaminerViewer.h> #endif #include <Inventor/nodes/SoSeparator.h> #include <Inventor/nodes/SoSwitch.h> #include <Inventor/draggers/SoTrackballDragger.h> #include <Inventor/draggers/SoTranslate1Dragger.h> #include <Inventor/nodes/SoPerspectiveCamera.h> #include <Inventor/nodes/SoDirectionalLight.h> #include <Inventor/nodes/SoTransform.h> #include <Inventor/nodes/SoEventCallback.h> #include <Inventor/events/SoKeyboardEvent.h> #include <Inventor/sensors/SoTimerSensor.h> #include <Inventor/actions/SoGLRenderAction.h> #include <Inventor/engines/SoCalculator.h> //Constantes #define FPS 1.0f/25.0f //Frames por segundo //Esta función es llamada cuando se produce un evento //de teclado void keyCallBack (void *userData, SoEventCallback *eventoTeclado) { const SoEvent *event = eventoTeclado->getEvent (); Toolkits – RVA //Se selecciona un dragger según la tecla que se pulse if ((SO_KEY_PRESS_EVENT (event, Q))||(SO_KEY_PRESS_EVENT (event, ESCAPE))) exit(0); else if (SO_KEY_PRESS_EVENT (event, N)) ((SoSwitch *)userData)->whichChild=-1; else if (SO_KEY_PRESS_EVENT (event, R)) ((SoSwitch *)userData)->whichChild=0; else if (SO_KEY_PRESS_EVENT (event, T)) ((SoSwitch *)userData)->whichChild=1; eventoTeclado->setHandled (); } //Esta función es llamada para realizar cada renderizado void renderCallback (void *userData, SoSensor * sensor) { #ifdef WIN32 //WINDOWS SoWinExaminerViewer * viewer=(SoWinExaminerViewer *) userData; #else //LINUX SoXtExaminerViewer * viewer=(SoXtExaminerViewer *) userData; #endif viewer->render(); } //MAIN int main(int argc, char ** argv) { SoInput * LeeFich; //Inicialización de la librería de componentes #ifdef WIN32 //WINDOWS HWND mainwin = SoWin::init(argc, argv, argv[0]); if (mainwin==NULL) exit (1); SoWinExaminerViewer *viewer = new SoWinExaminerViewer(mainwin); #else //LINUX Widget mainwin = SoXt::init(argc, argv, argv[0]); if (mainwin==NULL) exit (1); SoXtExaminerViewer *viewer = new SoXtExaminerViewer(mainwin); #endif //Comprobamos el número de argumentos if (argc != 2) Toolkits – RVA { fprintf (stderr, " Uso: %s nombre_fichero.iv\n", argv[0]); exit(1); } else { printf ("Abriendo %s\n", argv[1]); LeeFich = new SoInput(); if (!LeeFich->openFile (argv[1])) { perror (argv[1]); exit (-1); } //Comprobamos que es un fichero válido if (!LeeFich->isValidFile ()) { fprintf (stderr, "No puedo cargar este formato de datos\n"); exit (-1); } } //Creamos el nodo raíz SoSeparator * root = new SoSeparator; root->ref(); //De este separador colgará la escena que se carga de //fichero, así como las cámaras y luces encargadas de //mostrarla SoSeparator *s_fich= new SoSeparator; //Introducimos la cámara que renderiza los datos del //fichero. SoPerspectiveCamera *cam = new SoPerspectiveCamera(); SoDirectionalLight *light= new SoDirectionalLight(); s_fich->addChild(cam); s_fich->addChild(light); //Esta es la transformación a la que se ven sometidos //los datos del fichero SoTransform *t_fich = new SoTransform; s_fich->addChild(t_fich); //Colgamos el fichero del nodo s_fich SoSeparator *fich=SoDB::readAll (LeeFich); Toolkits – RVA s_fich->addChild (fich); root->addChild (s_fich); //Colocamos la camara de modo que pueda ver toda la escena cam->viewAll(fich,viewer->getViewportRegion()); //Cerramos el fichero LeeFich->closeFile (); //De este separador colgarán los dragger encargados //de mover la escena. SoSeparator *s_drag= new SoSeparator; //Introducimos una nueva cámara. Esta cámara pintará //los draggers siempre en la misma posición SoPerspectiveCamera *o_cam = new SoPerspectiveCamera(); SoDirectionalLight *o_light= new SoDirectionalLight(); o_cam->position = SbVec3f(0, 0, 10); o_cam->nearDistance=8; o_cam->farDistance=50; s_drag->addChild(o_cam); s_drag->addChild(o_light); //Colgamos del árbol los draggers que nos permitirán //modificar la escena SoSwitch *ss_drag=new SoSwitch (); SoTrackballDragger *rot_drag= new SoTrackballDragger; SoTranslate1Dragger *tras_drag = new SoTranslate1Dragger; ss_drag->addChild(rot_drag); ss_drag->addChild(tras_drag); ss_drag->whichChild=0; s_drag->addChild(ss_drag); root->addChild(s_drag); //Creamos un evento asociado con cualquier tecla SoEventCallback *eventoTeclado =new SoEventCallback; eventoTeclado->addEventCallback (SoKeyboardEvent::getClassTypeId (), keyCallBack, ss_drag); root->addChild (eventoTeclado); Toolkits – RVA //Una vez construida la escena conectamos los draggers //con la transformación de la escena SoCalculator *tras_mot = new SoCalculator; tras_mot->ref(); tras_mot->expression= SbString("oA = A * B[2]/5"); tras_mot->A.connectFrom(&tras_drag->translation); tras_mot->B.connectFrom(&cam->position); t_fich->rotation.connectFrom(&rot_drag->rotation); t_fich->translation.connectFrom(&tras_mot->oA); //Creamos un sensor encargado del render SoTimerSensor* rendertimer = new SoTimerSensor(renderCallback,(void *)viewer); rendertimer->setInterval(FPS); rendertimer->schedule(); //Se le indica al visualizador que escena debe renderizar viewer->setSceneGraph(root); viewer->setAutoRedraw(FALSE); //Obligamos a que el renderizado sea bajo peticion viewer->show (); //En este bucle se tratan los eventos. #ifdef WIN32 SoWin::mainLoop(); #else SoXt::mainLoop(); #endif // Liberamos los recursos que hemos utilizado delete viewer; root->unref(); tras_mot->unref(); return 0; }