trackball_sdl.cpp
Go to the documentation of this file.
00001 /* 
00002 
00003 This extends the example in sample/trimesh_sdl.h.
00004 It loads the mesh specified in the command line and shows it. 
00005 
00006 Navigate around the object with WASD (doom-like) or arrow modes.
00007 (wheel, or PGUP, PGDOWN, moves vertically)
00008 
00009 [F1] changes rendering style.
00010 [SPACE] toggles trackball modes.
00011 
00012 
00013 This example shows:
00014   
00015 - the use of a trackball in
00016 a time-syncronized application like a game.
00017 (exactly FPS times every seconds, the trackball is animated,
00018 but rendering can occurs fewer times).
00019 
00020 - how to set a trackball
00021 with NavigatorAwsd mode, i.e. to NAVIGATE around or inside
00022 the object rather than rotate it in front of the camera.
00023 
00024 */
00025 
00026 #include <SDL/SDL.h>
00027 #include <gl/glew.h>
00028 #include <vector>
00029 
00030 /*include the base definition for the vertex, face, and meshes */
00031 #include <vcg/simplex/vertex/base.h>
00032 #include <vcg/simplex/face/base.h>
00033 #include <vcg/complex/complex.h>
00034 
00035 /*include the algorihm that update bounding box and normals*/
00036 #include <vcg/complex/algorithms/update/bounding.h>
00037 #include <vcg/complex/algorithms/update/normal.h>
00038 
00039 /*include the importer from disk*/
00040 #include <wrap/io_trimesh/import.h>
00041 
00042 /*include wrapping of the trimesh towards opengl*/
00043 #include <wrap/gl/trimesh.h>
00044 
00045 /*include the trackball: NOTE, you the implementation of the trackball is found in the files:
00046 wrap/gui/trackball.cpp and wrap/gui/trackmode.cpp. You should include these files in your solution
00047 otherwise you'll get linking errors */
00048 #include <wrap/gui/trackball.h>
00049 
00050 /* we define our own SDL_TIMER event */
00051 #define SDL_TIMER SDL_USEREVENT
00052 
00053 // How many FPS?
00054 const int FPS = 30; 
00055 
00056 using namespace vcg;
00057 using namespace std;
00058 
00059 /* Definition of our own types for Vertices, Faces, Meshes*/
00060 class CEdge;    // dummy prototype never used
00061 class CFace;
00062 class CVertex : public VertexSimp2< CVertex, CEdge, CFace, vertex::Coord3f, vertex::Normal3f >{};
00063 class CFace   : public FaceSimp2<   CVertex, CEdge, CFace, face::VertexRef, face::Normal3f > {};
00064 class CMesh   : public vcg::tri::TriMesh< vector<CVertex>, vector<CFace> > {};
00065 
00066 
00067 
00069 // Globals: the mesh, the OpenGL wrapper to draw the mesh and the trackball.
00070 CMesh mesh;
00071 vcg::GlTrimesh<CMesh> glWrap;
00072 vcg::Trackball track;
00073 
00074 /* Internal state of the application */
00075 int drawMode=2;
00076 int trackballMode=1;
00077 int width =800;
00078 int height = 600;
00079 vcg::Point3f observerPos(0,0.2,3); // (initial) point of view (object is in 0,0,0)
00080 vcg::Point3f objectPos(0,0,0); // (initial) point of view (object is in 0,0,0)
00081 
00082 
00083 /* Simple function that renders a floor */
00084 void RenderFloor(){
00085   glHint(GL_FOG_HINT, GL_NICEST);       
00086   glDisable(GL_LIGHTING);
00087   double K = 500, c=0.7;
00088   glBegin(GL_QUADS);
00089   glColor3f(c,c,c);
00090   glNormal3f(0,1,0);
00091   glVertex3d(+K,0,+K);
00092   glVertex3d(+K,0,-K);
00093   glVertex3d(-K,0,-K);
00094   glVertex3d(-K,0,+K);
00095   glEnd();
00096   glHint(GL_FOG_HINT, GL_FASTEST);      
00097   glEnable(GL_LIGHTING);
00098 }
00099 
00100 /* Sets the trackball in a new mode: 
00101   standard mode (rotate object in front of camera) 
00102   or Navigation mode (navigate around/inside object)
00103 */
00104 void SetTrackball(int mode){
00105   // we define all possible trackModes that we could be using (static)
00106         static vcg::PolarMode polarMode;
00107         static vcg::SphereMode sphereMode;
00108         static vcg::NavigatorWasdMode navigatorMode;
00109         static vcg::InactiveMode inactiveMode;
00110         static vcg::ScaleMode scaleMode;
00111         static vcg::PanMode panMode;    
00112         static vcg::ZMode zMode;        
00113         
00114         // customize navigation mode... 
00115         navigatorMode.SetTopSpeedsAndAcc(1.2f,0.6f,6);
00116         // this adds a neat human stepping effect
00117         navigatorMode.SetStepOnWalk(0.5f,0.015f);
00118         
00119         track.modes.clear();
00120         track.Reset();
00121         
00122   switch (mode) {
00123   case  1:
00124     // switch to navigator mode
00125           track.modes[vcg::Trackball::BUTTON_NONE] = NULL;
00126           track.modes[vcg::Trackball::WHEEL] = 
00127           track.modes[vcg::Trackball::BUTTON_LEFT] = 
00128           track.idle_and_keys_mode = &navigatorMode;
00129 
00130     track.inactive_mode = NULL; // nothing to draw when inactive
00131     track.SetPosition( observerPos );
00132     break;
00133   default:
00134     // sweitch to default trackmode -- this is equivalent to a call to track->SetDefault()
00135     track.modes[vcg::Trackball::BUTTON_NONE] = NULL;
00136     track.modes[vcg::Trackball::BUTTON_LEFT] = &sphereMode;
00137     track.modes[vcg::Trackball::BUTTON_LEFT | vcg::Trackball::KEY_CTRL] = 
00138     track.modes[vcg::Trackball::BUTTON_MIDDLE] = &panMode;
00139     track.modes[vcg::Trackball::WHEEL] = 
00140     track.modes[vcg::Trackball::BUTTON_LEFT | vcg::Trackball::KEY_SHIFT] = &scaleMode;
00141     track.modes[vcg::Trackball::BUTTON_LEFT | vcg::Trackball::KEY_ALT] = &zMode;
00142     track.modes[vcg::Trackball::BUTTON_MIDDLE | vcg::Trackball::KEY_ALT] = 
00143           track.idle_and_keys_mode = &sphereMode;
00144           
00145     track.inactive_mode = &inactiveMode; // draw a sphere when inactive
00146     track.SetPosition( objectPos );
00147   }
00148 }
00149 
00150 /* Sets up OpenGL state */
00151 void initGL()
00152 {
00153   glClearColor(0, 0, 0, 0); 
00154   glEnable(GL_LIGHTING);
00155   glEnable(GL_LIGHT0);
00156   glEnable(GL_NORMALIZE);
00157   glEnable(GL_FOG);
00158   glEnable(GL_COLOR_MATERIAL);
00159   glColorMaterial(GL_FRONT, GL_AMBIENT);
00160   glDisable(GL_CULL_FACE);
00161   glEnable(GL_DEPTH_TEST);
00162 }
00163 
00164 /* Response to a window resize event. */
00165 void myReshapeFunc(GLsizei w, GLsizei h)
00166 {
00167   SDL_SetVideoMode(w, h, 0, SDL_OPENGL|SDL_RESIZABLE|SDL_DOUBLEBUF);
00168         width=w;
00169   height=h;
00170   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
00171   initGL();
00172 }
00173 
00174 /* sends a SDL_TIMER event to self (timer callback) */
00175 Uint32 timerCallback(Uint32 interval, void *param){ 
00176   static SDL_Event e; // the msg
00177   e.type = SDL_TIMER; // its content
00178   SDL_PushEvent(&e);
00179   return interval;
00180 }
00181  
00182 /* sends a redraw event to self */
00183 void sendRedraw() {
00184   static SDL_Event e; // the msg
00185   e.type = SDL_VIDEOEXPOSE; // its content
00186   SDL_PushEvent(&e);
00187 }
00188 
00189 /* clears any "redraw" even still in the event queue */
00190 void drainRedrawEvents(){
00191   static SDL_Event tmp[200];
00192   int eventRemoved = SDL_PeepEvents(tmp,200,SDL_GETEVENT, SDL_EVENTMASK(SDL_VIDEOEXPOSE));
00193 }
00194 
00195 /* Response to a redraw event: renders the scene */
00196 void display(){
00197     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00198     glMatrixMode(GL_PROJECTION);
00199     glLoadIdentity();
00200     gluPerspective(40, width/(float)height, 0.01, 10);
00201     glMatrixMode(GL_MODELVIEW);
00202     glLoadIdentity();
00203     glTranslate( -observerPos );
00204 
00205                 track.GetView();
00206         track.Apply();
00207     glPushMatrix();
00208     float d=mesh.bbox.Diag();
00209     glScale(1.5f/d);
00210     Point3f p = glWrap.m->bbox.Center();
00211     p[1] = glWrap.m->bbox.min[1];
00212                 glTranslate(-p);        
00213 
00214                 // the trimesh drawing calls
00215                 switch(drawMode)
00216                 {
00217                   case 0: glWrap.Draw<vcg::GLW::DMSmooth,   vcg::GLW::CMNone,vcg::GLW::TMNone> ();break;
00218                   case 1: glWrap.Draw<vcg::GLW::DMWire,     vcg::GLW::CMNone,vcg::GLW::TMNone> ();break;
00219                   case 2: glWrap.Draw<vcg::GLW::DMFlatWire, vcg::GLW::CMNone,vcg::GLW::TMNone> ();break;
00220                   case 3: glWrap.Draw<vcg::GLW::DMHidden,   vcg::GLW::CMNone,vcg::GLW::TMNone> ();break;
00221                   case 4: glWrap.Draw<vcg::GLW::DMFlat,     vcg::GLW::CMNone,vcg::GLW::TMNone> ();break;
00222                   default: break;
00223                 }
00224     glPopMatrix();
00225     RenderFloor();
00226     track.DrawPostApply();
00227     SDL_GL_SwapBuffers();
00228 }
00229 
00230 /* Response to a timer event: animates the status of the game (and the trackball) */
00231 // - retunrs true if anything changed.
00232 bool onTimer(){
00233   int res = false;
00234   if ( track.IsAnimating() ) {
00235     track.Animate(1000/FPS);
00236     res = true;
00237   }
00238   // insert any other animation processing here
00239   return res;
00240 }
00241 
00242 
00243 /* Helper function: translates SDL codes into VCG codes */
00244 vcg::Trackball::Button SDL2VCG(int code){
00245   switch (code) {
00246     case SDL_BUTTON_LEFT: return vcg::Trackball::BUTTON_LEFT;
00247     case SDL_BUTTON_MIDDLE: return vcg::Trackball::BUTTON_MIDDLE;
00248     case SDL_BUTTON_RIGHT: return vcg::Trackball::BUTTON_RIGHT;
00249                 case SDLK_RCTRL:
00250                 case SDLK_LCTRL:  return vcg::Trackball::KEY_CTRL;
00251                 case SDLK_RALT:
00252                 case SDLK_LALT:  return vcg::Trackball::KEY_ALT;
00253                 case SDLK_LSHIFT:
00254                 case SDLK_RSHIFT:  return vcg::Trackball::KEY_SHIFT; 
00255                 case SDLK_LEFT:
00256     case SDLK_a:  return vcg::Trackball::KEY_LEFT;
00257                 case SDLK_RIGHT:
00258     case SDLK_d:  return vcg::Trackball::KEY_RIGHT;
00259                 case SDLK_UP:
00260     case SDLK_w:  return vcg::Trackball::KEY_UP;
00261                 case SDLK_DOWN:
00262     case SDLK_s:  return vcg::Trackball::KEY_DOWN;
00263                 case SDLK_PAGEUP:
00264     case SDLK_r:  return vcg::Trackball::KEY_PGUP;
00265                 case SDLK_PAGEDOWN:
00266     case SDLK_f: return vcg::Trackball::KEY_PGDOWN;
00267     return vcg::Trackball::BUTTON_NONE;
00268   }
00269 }
00270 
00271 /* initializes SDL */
00272 bool initSDL(const std::string &str) {
00273   if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 ) {
00274     fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
00275     exit(1);
00276   }
00277   if ( SDL_SetVideoMode(width, height, 0, SDL_OPENGL|SDL_RESIZABLE) == NULL ) {
00278     fprintf(stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError());
00279     SDL_Quit();
00280     exit(2);
00281   }
00282   
00283   SDL_AddTimer(1000/FPS, timerCallback, NULL); 
00284   
00285   SDL_WM_SetCaption(str.c_str(), str.c_str());  
00286   myReshapeFunc(width, height);
00287   return true;
00288 }
00289 
00290 /* The main event Loop */
00291 int sdlLoop() {
00292   bool quit=false;
00293 
00294   bool redraw_needed = false; // true whan a scene needs a redraw
00295   
00296         SDL_Event event;
00297         while( !quit ) {
00298 
00299     SDL_WaitEvent(&event);
00300     switch( event.type ) {
00301       case SDL_QUIT:  quit = true; break; 
00302       case SDL_VIDEORESIZE : myReshapeFunc(event.resize.w,event.resize.h); break;
00303       case SDL_KEYDOWN: 
00304         switch (event.key.keysym.sym) {
00305                             case SDLK_ESCAPE: exit(0); break;   
00306                             case SDLK_F1: drawMode= (drawMode+1)%5; printf("Current Mode %i\n",drawMode); break;        
00307                             case SDLK_HOME: track.Reset(); break;
00308           case SDLK_SPACE: 
00309             trackballMode= (trackballMode+1)%2; printf("Trackball Mode %i\n",drawMode); 
00310             SetTrackball(trackballMode);
00311             break;      
00312           default: track.ButtonDown( SDL2VCG( event.key.keysym.sym) );
00313                           }
00314                           redraw_needed = true;
00315         break;
00316       case SDL_KEYUP: 
00317                           track.ButtonUp( SDL2VCG( event.key.keysym.sym) ); break;
00318       case SDL_MOUSEBUTTONDOWN:   
00319               switch(event.button.button) {
00320           case SDL_BUTTON_WHEELUP:    track.MouseWheel( 1); redraw_needed = true; break;
00321           case SDL_BUTTON_WHEELDOWN:  track.MouseWheel(-1); redraw_needed = true; break;
00322           default: track.MouseDown(event.button.x, (height - event.button.y), SDL2VCG(event.button.button) ); break;
00323         } break;
00324       case SDL_MOUSEBUTTONUP:   
00325         track.MouseUp(event.button.x, (height - event.button.y), SDL2VCG(event.button.button) ); break;       
00326         break;
00327       case SDL_MOUSEMOTION: 
00328               while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK));
00329               track.MouseMove(event.button.x, (height - event.button.y));
00330                           redraw_needed = true;
00331               break;
00332             case SDL_TIMER:
00333         if (onTimer())  redraw_needed = true;
00334         if (redraw_needed) sendRedraw(); // justs sends a redraw event!
00335                           redraw_needed = false;
00336         break;
00337       case SDL_VIDEOEXPOSE:
00338         // any rendering is done ONLY here.
00339                     display();
00340                     drainRedrawEvents();
00341                     break;
00342       default: break;
00343       }
00344 
00345         }
00346 
00347   SDL_Quit();
00348   return -1;
00349 }
00350 
00351 
00352 int main(int argc, char *argv[]) {      
00353         // Generic loading of the mesh from disk
00354         if(vcg::tri::io::Importer<CMesh>::Open(mesh,argv[1])!=0) {
00355       fprintf(stderr,"Error reading file %s\n",argv[1]);
00356                         exit(0);
00357                 }
00358 
00359   // Initialize the mesh itself
00360         vcg::tri::UpdateBounding<CMesh>::Box(mesh);      // update bounding box
00361   //vcg::tri::UpdateNormals<CMesh>::PerVertexNormalizePerFaceNormalized(mesh); // update Normals
00362   vcg::tri::UpdateNormals<CMesh>::PerVertexPerFace(mesh); // update Normals
00363         
00364         // Initialize the wrapper
00365   glWrap.m = &mesh;
00366   glWrap.Update();
00367   
00368   SetTrackball(trackballMode);
00369   
00370   // we will do exaclty an animation step every 1000/FPS msecs.
00371   track.SetFixedTimesteps(true);
00372         
00373   initSDL("SDL_minimal_viewer");
00374   initGL();
00375   sdlLoop();
00376         exit(0);
00377 }
00378 
00379 
00380 


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:37:26