source: GTP/branches/IllumWPdeliver2008dec/IlluminationWP/demos/Standalone/Hierarchical Systems Demo [OpenGL]/RESOURCES/include/glh/glh_glut2.h @ 3255

Revision 3255, 16.6 KB checked in by szirmay, 15 years ago (diff)
Line 
1/*
2    glh - is a platform-indepenedent C++ OpenGL helper library
3
4
5    Copyright (c) 2000 Cass Everitt
6        Copyright (c) 2000 NVIDIA Corporation
7    All rights reserved.
8
9    Redistribution and use in source and binary forms, with or
10        without modification, are permitted provided that the following
11        conditions are met:
12
13     * Redistributions of source code must retain the above
14           copyright notice, this list of conditions and the following
15           disclaimer.
16
17     * Redistributions in binary form must reproduce the above
18           copyright notice, this list of conditions and the following
19           disclaimer in the documentation and/or other materials
20           provided with the distribution.
21
22     * The names of contributors to this software may not be used
23           to endorse or promote products derived from this software
24           without specific prior written permission.
25
26       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27           ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28           LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29           FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30           REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31           INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32           BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33           LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34           CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35           LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36           ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37           POSSIBILITY OF SUCH DAMAGE.
38
39
40    Cass Everitt - cass@r3.nu
41*/
42
43#ifndef GLH_GLUT_H
44#define GLH_GLUT_H
45
46// some helper functions and objects to
47// make writing simple glut programs even easier! :-)
48#ifndef _WIN32
49#include <string.h>
50#endif
51#include <algorithm>
52#include <list>
53
54#ifdef MACOS
55#include <GLUT/glut.h>
56#else
57#include <GL/glut.h>
58#endif
59
60#include <glh/glh_interactors.h>
61#include <glh/glh_convenience.h>
62
63namespace glh
64{
65
66  class glut_interactor
67  {
68  public:
69        glut_interactor() { enabled = true; }
70
71        virtual void display() {}
72        virtual void idle() {}
73        virtual void keyboard(unsigned char key, int x, int y) {}
74        virtual void menu_status(int status, int x, int y) {}
75        virtual void motion(int x, int y) {}
76        virtual void mouse(int button, int state, int x, int y) {}
77        virtual void passive_motion(int x, int y) {}
78        virtual void reshape(int w, int h) {}
79        virtual void special(int  key, int x, int y) {}
80        virtual void timer(int value) {}
81        virtual void visibility(int v) {}
82
83        virtual void enable()  { enabled = true; }
84        virtual void disable() { enabled = false; }
85
86        bool enabled;
87  };
88
89  std::list<glut_interactor *> interactors;
90  bool propagate;
91
92  void glut_display_function()
93  {
94        propagate = true;
95        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
96                (*it)->display();
97  }
98
99  void glut_idle_function()
100  {
101        propagate = true;
102        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
103                (*it)->idle();
104  }
105
106  void glut_keyboard_function(unsigned char k, int x, int y)
107  {
108        propagate = true;
109        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
110          (*it)->keyboard(k, x, y);
111  }
112
113  void glut_menu_status_function(int status, int x, int y)
114  {
115        propagate = true;
116        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
117                (*it)->menu_status(status, x, y);
118  }
119
120  void glut_motion_function(int x, int y)
121  {
122        propagate = true;
123        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
124                (*it)->motion(x, y);
125  }
126
127  void glut_mouse_function(int button, int state, int x, int y)
128  {
129        propagate = true;
130        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
131          (*it)->mouse(button, state, x, y);
132  }
133 
134  void glut_passive_motion_function(int x, int y)
135  {
136        propagate = true;
137        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
138                (*it)->passive_motion(x, y);
139  }
140
141  void glut_reshape_function(int w, int h)
142  {
143        propagate = true;
144        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
145          (*it)->reshape(w,h);
146  }
147
148  void glut_special_function(int k, int x, int y)
149  {
150        propagate = true;
151        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
152          (*it)->special(k, x, y);
153  }
154
155  void glut_timer_function(int v)
156  {
157        propagate = true;
158        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
159          (*it)->timer(v);
160  }
161
162  void glut_visibility_function(int v)
163  {
164        propagate = true;
165        for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
166          (*it)->visibility(v);
167  }
168
169  // stop processing the current event
170  inline void glut_event_processed()
171  {
172          propagate = false;
173  }
174
175  inline void glut_helpers_initialize()
176  {
177        glutDisplayFunc(glut_display_function);
178        glutIdleFunc(0);
179        glutKeyboardFunc(glut_keyboard_function);
180        glutMenuStatusFunc(glut_menu_status_function);
181        glutMotionFunc(glut_motion_function);
182        glutMouseFunc(glut_mouse_function);
183        glutPassiveMotionFunc(glut_passive_motion_function);
184        glutReshapeFunc(glut_reshape_function);
185        glutSpecialFunc(glut_special_function);
186        glutVisibilityFunc(glut_visibility_function);
187  }
188
189  inline void glut_remove_interactor(glut_interactor *gi)
190  {
191      if (interactors.empty())
192          return;
193          std::list<glut_interactor *>::iterator it =
194                  std::find(interactors.begin(), interactors.end(), gi);
195        if(it != interactors.end())
196          interactors.erase(it);
197  }
198
199  inline void glut_add_interactor(glut_interactor *gi, bool append=true)
200  {
201        glut_remove_interactor(gi);
202        if(append)
203                interactors.push_back(gi);
204        else
205                interactors.push_front(gi);
206  }
207
208  inline void glut_timer(int msec, int value)
209  {
210        glutTimerFunc(msec, glut_timer_function, value);
211  }
212
213  inline void glut_idle(bool do_idle)
214  {
215        glutIdleFunc(do_idle ? glut_idle_function : 0);
216  }
217
218  class glut_callbacks : public glut_interactor
219  {
220  public:
221        glut_callbacks() :
222                display_function(0),
223                idle_function(0),
224                keyboard_function(0),
225                menu_status_function(0),
226                motion_function(0),
227                mouse_function(0),
228                passive_motion_function(0),
229                reshape_function(0),
230                special_function(0),
231                timer_function(0),
232                visibility_function()
233        {}
234
235        virtual void display()
236        { if(display_function) display_function(); }
237
238        virtual void idle()
239        { if(idle_function) idle_function(); }
240
241        virtual void keyboard(unsigned char k, int x, int y)
242        { if(keyboard_function) keyboard_function(k, x, y); }
243
244        virtual void menu_status(int status, int x, int y)
245        { if(menu_status_function) menu_status_function(status, x, y); }
246
247        virtual void motion(int x, int y)
248        { if(motion_function) motion_function(x,y); }
249
250        virtual void mouse(int button, int state, int x, int y)
251        { if(mouse_function) mouse_function(button, state, x, y); }
252
253        virtual void passive_motion(int x, int y)
254        { if(passive_motion_function) passive_motion_function(x, y); }
255
256        virtual void reshape(int w, int h)
257        { if(reshape_function) reshape_function(w, h); }
258
259        virtual void special(int key, int x, int y)
260        { if(special_function) special_function(key, x, y); }
261
262        virtual void timer(int value)
263        { if(timer_function) timer_function(value); }
264
265        virtual void visibility(int v)
266        { if(visibility_function) visibility_function(v); }
267
268        void (* display_function) ();
269        void (* idle_function) ();
270        void (* keyboard_function) (unsigned char, int, int);
271        void (* menu_status_function) (int, int, int);
272        void (* motion_function) (int, int);
273        void (* mouse_function) (int, int, int, int);
274        void (* passive_motion_function) (int, int);
275        void (* reshape_function) (int, int);
276        void (* special_function) (int, int, int);
277        void (* timer_function) (int);
278        void (* visibility_function) (int);
279
280  };
281
282
283
284  class glut_perspective_reshaper : public glut_interactor
285  {
286  public:
287          glut_perspective_reshaper(float infovy = 60.f, float inzNear = .1f, float inzFar = 10.f)
288                  : fovy(infovy), zNear(inzNear), zFar(inzFar), aspect_factor(1) {}
289         
290          void reshape(int w, int h)
291          {
292                  width = w; height = h;
293
294                  if(enabled) apply();
295          }
296
297          void apply()
298          {
299                  glViewport(0,0,width,height);
300                  glMatrixMode(GL_PROJECTION);
301                  glLoadIdentity();
302                  apply_projection();
303                  glMatrixMode(GL_MODELVIEW);
304          }
305
306          matrix4f get_projection()
307          {
308                  aspect = aspect_factor * float(width)/float(height);
309          if ( aspect < 1 )
310                  {
311                          // fovy is a misnomer.. we really mean the fov applies to the
312                          // smaller dimension
313                          float fovx = fovy;
314                          float real_fov = to_degrees(2 * atan(tan(to_radians(fovx/2))/aspect));
315              return perspective(real_fov, aspect, zNear, zFar);
316                  }
317          else
318                    return perspective(fovy, aspect, zNear, zFar);
319          }
320
321          void apply_projection()
322          {
323                glMultMatrixf(get_projection().m);
324          }
325
326          matrix4f get_projection_inverse()
327          {
328                  aspect = aspect_factor * float(width)/float(height);
329          if ( aspect < 1 )
330                  {
331                          // fovy is a misnomer.. we really mean the fov applies to the
332                          // smaller dimension
333                          float fovx = fovy;
334                          float real_fov = to_degrees(2 * atan(tan(to_radians(fovx/2))/aspect));
335              return perspective_inverse(real_fov, aspect, zNear, zFar);
336                  }
337          else
338                    return perspective_inverse(fovy, aspect, zNear, zFar);
339          }
340
341          void apply_projection_inverse()
342          {
343                  glMultMatrixf(get_projection_inverse().m);
344          }
345
346          int width, height;
347          float fovy, aspect, zNear, zFar;
348          float aspect_factor;
349  };
350
351
352  // activates/deactivates on particular mouse button/modifier combinations
353  // and calculates deltas while active
354  class glut_simple_interactor : public glut_interactor
355  {
356  public:
357        glut_simple_interactor()
358        {
359          num_modes = 0;
360          active = false;
361          width = height = 0;
362          x0 = y0 = x = y = dx = dy = 0;
363        }
364
365        virtual void mouse(int button, int state, int X, int Y)
366        {
367                for(int i=0; i < num_modes; i++)
368                {
369                        if(enabled && button == cond[i].activate_on && state == GLUT_DOWN &&
370                                (! cond[i].use_modifiers || (cond[i].modifiers == glutGetModifiers())) )
371                        {
372                                mode = i;
373                                active = true;
374                                x = x0 = X;
375                                y = y0 = height - Y;
376                                dx = dy = 0;
377                                break;
378                        }
379                        else if (enabled && button == cond[i].activate_on && state == GLUT_UP)
380                        {
381                                if(dx == 0 && dy == 0)
382                                        update();
383                                active = false;
384                                dx = dy = 0;
385                                mode = -1;
386                                break;
387                        }
388                }
389        }
390
391        virtual void motion(int X, int Y)
392        {
393          if(enabled && active)
394          {
395                dx = X - x;   dy = (height - Y) - y;
396                x = X;   y = height - Y;
397                update();
398          }
399        }
400
401        void reshape(int w, int h)
402        {
403                  width = w; height = h;
404        }
405
406        virtual void apply_transform() = 0;
407        virtual void apply_inverse_transform() = 0;
408        virtual matrix4f get_transform() = 0;
409        virtual matrix4f get_inverse_transform() = 0;
410
411        virtual void update() {}
412
413        struct activate_condition
414        {
415                activate_condition()
416                {
417                        activate_on = GLUT_LEFT_BUTTON;
418                        use_modifiers = true;
419                        modifiers = 0;
420                }
421                int activate_on;
422                bool use_modifiers;
423                int modifiers;
424        };
425
426        activate_condition cond[2];
427        bool active;
428        int x0, y0;
429        int x, y;
430        int dx, dy;
431        int width, height;
432        int num_modes;
433        int mode;
434  };
435
436
437  class glut_translator : public translator, public glut_simple_interactor
438  {
439  public:
440
441        void update()
442        {
443          if(mode == 0)
444                  pan(dx, dy);
445          else if(mode == 1)
446                  dolly(-dy);
447          glutPostRedisplay();
448        }
449
450        void apply_transform()
451        {
452          //cerr << "Applying transform: " << (x - x0) << ", " << (y - y0) << endl;
453          glTranslatef(t[0], t[1], t[2]);
454        }
455
456        void apply_inverse_transform()
457        {
458          //cerr << "Applying transform: " << (x - x0) << ", " << (y - y0) << endl;
459          glTranslatef(-t[0], -t[1], -t[2]);
460        }
461
462        matrix4f get_transform()
463        {
464                return translator::get_transform();
465        }
466
467        matrix4f get_inverse_transform()
468        {
469                return translator::get_inverse_transform();
470        }
471
472  };
473
474
475  class glut_trackball : public glut_simple_interactor, public trackball
476  {
477  public:
478
479        void update()
480        {
481                radius = width < height ? width : height;
482                radius /= 2.f;
483                offset = vec3f(width/2.f, height/2.f, 0);
484                rotate(x-dx, y-dy, x, y);
485                glutPostRedisplay();
486        }
487
488        void apply_transform()
489        {
490                glTranslatef(centroid[0], centroid[1], centroid[2]);
491                glh_rotate(r);
492                glTranslatef(-centroid[0], -centroid[1], -centroid[2]);
493        }
494
495        void apply_inverse_transform()
496        {
497                glTranslatef(centroid[0], centroid[1], centroid[2]);
498                glh_rotate(r.inverse());
499                glTranslatef(-centroid[0], -centroid[1], -centroid[2]);
500        }
501
502        matrix4f get_transform()
503        {
504                return trackball::get_transform();
505        }
506
507        matrix4f get_inverse_transform()
508        {
509                return trackball::get_inverse_transform();
510        }
511
512  };
513
514  inline void glut_exit_on_escape(unsigned char k, int x = 0, int y = 0)
515  { if(k==27) exit(0); }
516
517  struct glut_simple_mouse_interactor : public glut_interactor
518  {
519
520  public:
521        glut_simple_mouse_interactor(int num_buttons_to_use=3)
522        {
523          configure_buttons(num_buttons_to_use);
524          camera_mode = false;
525        }
526
527        void enable()
528        {
529                trackball.enable();
530                translator.enable();
531        }
532
533        void disable()
534        {
535                trackball.disable();
536                translator.disable();
537        }
538
539        void set_camera_mode(bool cam)
540        {
541                camera_mode = cam;
542                if(camera_mode)
543                {
544                        trackball.invert_increment = true;
545                        translator.invert_increment = true;
546                        translator.parent_rotation = & trackball.r;
547                }
548                else
549                {
550                        trackball.invert_increment = false;
551                        translator.invert_increment = false;
552                        if(translator.parent_rotation == &trackball.r) translator.parent_rotation = 0;
553                }
554        }
555        void configure_buttons(int num_buttons_to_use = 3)
556        {
557          switch(num_buttons_to_use)
558          {
559          case 1:
560
561                trackball.num_modes = 1;
562                trackball.cond[0].activate_on = GLUT_LEFT_BUTTON;
563                trackball.cond[0].modifiers = 0;
564                trackball.cond[0].use_modifiers = true;
565
566                translator.num_modes = 2;
567                translator.cond[0].activate_on = GLUT_LEFT_BUTTON;
568                translator.cond[0].modifiers = GLUT_ACTIVE_SHIFT;
569                translator.cond[0].use_modifiers = true;
570                translator.cond[1].activate_on = GLUT_LEFT_BUTTON;
571                translator.cond[1].modifiers = GLUT_ACTIVE_CTRL;
572                translator.cond[1].use_modifiers = true;
573                break;
574
575          case 2:
576
577                trackball.num_modes = 1;
578                trackball.cond[0].activate_on = GLUT_LEFT_BUTTON;
579                trackball.cond[0].modifiers = 0;
580                trackball.cond[0].use_modifiers = true;
581
582                translator.num_modes = 2;
583                translator.cond[0].activate_on = GLUT_MIDDLE_BUTTON;
584                translator.cond[0].modifiers = 0;
585                translator.cond[0].use_modifiers = true;
586                translator.cond[1].activate_on = GLUT_LEFT_BUTTON;
587                translator.cond[1].modifiers = GLUT_ACTIVE_CTRL;
588                translator.cond[1].use_modifiers = true;
589
590                break;
591
592          case 3:
593          default:
594
595                trackball.num_modes = 1;
596                trackball.cond[0].activate_on = GLUT_LEFT_BUTTON;
597                trackball.cond[0].modifiers = 0;
598                trackball.cond[0].use_modifiers = true;
599
600                translator.num_modes = 2;
601                translator.cond[0].activate_on = GLUT_MIDDLE_BUTTON;
602                translator.cond[0].modifiers = 0;
603                translator.cond[0].use_modifiers = true;
604                translator.cond[1].activate_on = GLUT_RIGHT_BUTTON;
605                translator.cond[1].modifiers = 0;
606                translator.cond[1].use_modifiers = true;
607
608                break;
609          }
610        }
611
612        virtual void motion(int x, int y)
613        {
614                trackball.motion(x,y);
615                translator.motion(x,y);
616        }
617
618        virtual void mouse(int button, int state, int x, int y)
619        {
620          trackball.mouse(button, state, x, y);
621          translator.mouse(button, state, x, y);
622        }
623
624        virtual void reshape(int x, int y)
625        {
626                trackball.reshape(x,y);
627                translator.reshape(x,y);
628        }
629
630        void apply_transform()
631        {
632          translator.apply_transform();
633          trackball.apply_transform();
634        }
635
636        void apply_inverse_transform()
637        {
638          trackball.apply_inverse_transform();
639          translator.apply_inverse_transform();
640        }
641
642        matrix4f get_transform()
643        {
644          return ( translator.get_transform()       *
645                           trackball.get_transform() );
646        }
647
648        matrix4f get_inverse_transform()
649        {
650          return ( trackball.get_inverse_transform() *
651                           translator.get_inverse_transform()       );
652        }
653
654        void set_parent_rotation(rotationf *rp)
655        {
656                trackball.parent_rotation = rp;
657                translator.parent_rotation = rp;
658        }
659
660        bool camera_mode;
661        glut_trackball trackball;
662        glut_translator  translator;
663  };
664
665}
666
667#endif
Note: See TracBrowser for help on using the repository browser.