00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <SDL/SDL.h>
00027 #include <gl/glew.h>
00028 #include <vector>
00029
00030
00031 #include <vcg/simplex/vertex/base.h>
00032 #include <vcg/simplex/face/base.h>
00033 #include <vcg/complex/trimesh/base.h>
00034
00035
00036 #include <vcg/complex/trimesh/update/bounding.h>
00037 #include <vcg/complex/trimesh/update/normal.h>
00038
00039
00040 #include <wrap/io_trimesh/import.h>
00041
00042
00043 #include <wrap/gl/trimesh.h>
00044
00045
00046
00047
00048 #include <wrap/gui/trackball.h>
00049
00050
00051 #define SDL_TIMER SDL_USEREVENT
00052
00053
00054 const int FPS = 30;
00055
00056 using namespace vcg;
00057 using namespace std;
00058
00059
00060 class CEdge;
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
00070 CMesh mesh;
00071 vcg::GlTrimesh<CMesh> glWrap;
00072 vcg::Trackball track;
00073
00074
00075 int drawMode=2;
00076 int trackballMode=1;
00077 int width =800;
00078 int height = 600;
00079 vcg::Point3f observerPos(0,0.2,3);
00080 vcg::Point3f objectPos(0,0,0);
00081
00082
00083
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
00101
00102
00103
00104 void SetTrackball(int mode){
00105
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
00115 navigatorMode.SetTopSpeedsAndAcc(1.2f,0.6f,6);
00116
00117 navigatorMode.SetStepOnWalk(0.5f,0.015f);
00118
00119 track.modes.clear();
00120 track.Reset();
00121
00122 switch (mode) {
00123 case 1:
00124
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;
00131 track.SetPosition( observerPos );
00132 break;
00133 default:
00134
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;
00146 track.SetPosition( objectPos );
00147 }
00148 }
00149
00150
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
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
00175 Uint32 timerCallback(Uint32 interval, void *param){
00176 static SDL_Event e;
00177 e.type = SDL_TIMER;
00178 SDL_PushEvent(&e);
00179 return interval;
00180 }
00181
00182
00183 void sendRedraw() {
00184 static SDL_Event e;
00185 e.type = SDL_VIDEOEXPOSE;
00186 SDL_PushEvent(&e);
00187 }
00188
00189
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
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(false);
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
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
00231
00232 bool onTimer(){
00233 int res = false;
00234 if ( track.IsAnimating() ) {
00235 track.Animate(1000/FPS);
00236 res = true;
00237 }
00238
00239 return res;
00240 }
00241
00242
00243
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
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
00291 int sdlLoop() {
00292 bool quit=false;
00293
00294 bool redraw_needed = false;
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();
00335 redraw_needed = false;
00336 break;
00337 case SDL_VIDEOEXPOSE:
00338
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
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
00360 vcg::tri::UpdateBounding<CMesh>::Box(mesh);
00361
00362 vcg::tri::UpdateNormals<CMesh>::PerVertexPerFace(mesh);
00363
00364
00365 glWrap.m = &mesh;
00366 glWrap.Update();
00367
00368 SetTrackball(trackballMode);
00369
00370
00371 track.SetFixedTimesteps(true);
00372
00373 initSDL("SDL_minimal_viewer");
00374 initGL();
00375 sdlLoop();
00376 exit(0);
00377 }
00378
00379
00380