1 /****************************************************************************
2 
3   example3.cpp
4 
5   A GLUT program using all the features of the GLUI User Interface Library
6   (except columns, featured in example4.cpp)
7 
8   -----------------------------------------------------------------------
9 
10   9/9/98 Paul Rademacher (rademach@cs.unc.edu)
11 
12 ****************************************************************************/
13 
14 #include <string.h>
15 #include <GL/glui.h>
16 
17 float xy_aspect;
18 int   last_x, last_y;
19 float rotationX = 0.0, rotationY = 0.0;
20 
21 /** These are the live variables passed into GLUI ***/
22 int   wireframe = 0;
23 int   obj_type = 1;
24 int   segments = 8;
25 int   segments2 = 8;
26 std::string text = "Hello World!";
27 int   light0_enabled = 1;
28 int   light1_enabled = 0;
29 float light0_intensity = 1.0;
30 float light1_intensity = 1.0;
31 int   main_window;
32 int   counter = 0;
33 float scale = 1.0;
34 
35 /** Pointers to the windows and some of the controls we'll create **/
36 GLUI *cmd_line_glui=0, *glui;
37 GLUI_Checkbox    *checkbox;
38 GLUI_Spinner     *spinner, *light0_spinner, *light1_spinner, *scale_spinner;
39 GLUI_RadioGroup  *radio;
40 GLUI_EditText    *edittext;
41 GLUI_CommandLine *cmd_line;
42 GLUI_Panel       *obj_panel;
43 GLUI_Button      *open_console_btn;
44 
45 /********** User IDs for callbacks ********/
46 #define OPEN_CONSOLE_ID      100
47 #define CMD_HIST_RESET_ID    101
48 #define CMD_CLOSE_ID         102
49 #define LIGHT0_ENABLED_ID    200
50 #define LIGHT1_ENABLED_ID    201
51 #define LIGHT0_INTENSITY_ID  250
52 #define LIGHT1_INTENSITY_ID  251
53 
54 /********** Miscellaneous global variables **********/
55 
56 GLfloat light0_ambient[] =  {0.1f, 0.1f, 0.3f, 1.0f};
57 GLfloat light0_diffuse[] =  {.6f, .6f, 1.0f, 1.0f};
58 GLfloat light0_position[] = {.5f, .5f, 1.0f, 0.0f};
59 
60 GLfloat light1_ambient[] =  {0.1f, 0.1f, 0.3f, 1.0f};
61 GLfloat light1_diffuse[] =  {.9f, .6f, 0.0f, 1.0f};
62 GLfloat light1_position[] = {-1.0f, -1.0f, 1.0f, 0.0f};
63 
64 /**************************************** control_cb() *******************/
65 /* GLUI control callback                                                 */
66 
control_cb(int control)67 void control_cb( int control )
68 {
69   if ( control == LIGHT0_ENABLED_ID ) {
70     if ( light0_enabled ) {
71       glEnable( GL_LIGHT0 );
72       light0_spinner->enable();
73     }
74     else {
75       glDisable( GL_LIGHT0 );
76       light0_spinner->disable();
77     }
78   }
79   else if ( control == LIGHT1_ENABLED_ID ) {
80     if ( light1_enabled ) {
81       glEnable( GL_LIGHT1 );
82       light1_spinner->enable();
83     }
84     else {
85       glDisable( GL_LIGHT1 );
86       light1_spinner->disable();
87     }
88   }
89   else if ( control == LIGHT0_INTENSITY_ID ) {
90     float v[] = { light0_diffuse[0],  light0_diffuse[1],
91 		  light0_diffuse[2],  light0_diffuse[3] };
92 
93     v[0] *= light0_intensity;
94     v[1] *= light0_intensity;
95     v[2] *= light0_intensity;
96 
97     glLightfv(GL_LIGHT0, GL_DIFFUSE, v );
98   }
99   else if ( control == LIGHT1_INTENSITY_ID ) {
100     float v[] = { light1_diffuse[0],  light1_diffuse[1],
101 		  light1_diffuse[2],  light1_diffuse[3] };
102 
103     v[0] *= light1_intensity;
104     v[1] *= light1_intensity;
105     v[2] *= light1_intensity;
106 
107     glLightfv(GL_LIGHT1, GL_DIFFUSE, v );
108   }
109 }
110 
111 /**************************************** pointer_cb() *******************/
112 /* GLUI control pointer callback                                         */
113 /* You can also use a function that takes a GLUI_Control pointer  as its */
114 /* argument.  This can simplify things sometimes, and reduce the clutter */
115 /* of global variables by giving you the control pointer directly.       */
116 /* For instance here we didn't need an additional global ID for the      */
117 /* cmd_line because we can just compare pointers directly.               */
118 
pointer_cb(GLUI_Control * control)119 void pointer_cb( GLUI_Control* control )
120 {
121   if (control->get_id() == OPEN_CONSOLE_ID ) {
122     /****** Make command line window ******/
123     cmd_line_glui = GLUI_Master.create_glui( "Enter command:",
124       0, 50, 500 );
125 
126     cmd_line = new GLUI_CommandLine(
127       cmd_line_glui, "Command (try 'exit'):", NULL, -1, pointer_cb );
128     cmd_line->set_w( 400 );  /** Widen 'command line' control **/
129 
130     GLUI_Panel *panel = new GLUI_Panel(cmd_line_glui,"", GLUI_PANEL_NONE);
131     new GLUI_Button(panel, "Clear History", CMD_HIST_RESET_ID, pointer_cb);
132     new GLUI_Column(panel, false);
133     new GLUI_Button(panel, "Close", CMD_CLOSE_ID, pointer_cb);
134 
135     cmd_line_glui->set_main_gfx_window( main_window );
136 
137     control->disable();
138   }
139   else if ( control->get_id() == CMD_CLOSE_ID ) {
140     open_console_btn->enable();
141     control->glui->close();
142   }
143   else if ( control == cmd_line ) {
144     /*** User typed text into the 'command line' window ***/
145     printf( "Command (%d): %s\n", counter, cmd_line->get_text() );
146     std::string text = cmd_line->get_text();
147     if (text =="exit" || text == "quit")
148       exit(0);
149   }
150   else if ( control->get_id() == CMD_HIST_RESET_ID ) {
151     cmd_line->reset_history();
152   }
153 
154 }
155 
156 /**************************************** myGlutKeyboard() **********/
157 
myGlutKeyboard(unsigned char Key,int x,int y)158 void myGlutKeyboard(unsigned char Key, int x, int y)
159 {
160   switch(Key)
161   {
162     // A few keys here to test the sync_live capability.
163   case 'o':
164     // Cycle through object types
165     ++obj_type %= 3;
166     GLUI_Master.sync_live_all();
167     break;
168   case 'w':
169     // Toggle wireframe mode
170     wireframe = !wireframe;
171     GLUI_Master.sync_live_all();
172     break;
173   case 27:
174   case 'q':
175     exit(0);
176     break;
177   };
178 
179   glutPostRedisplay();
180 }
181 
182 
183 /***************************************** myGlutMenu() ***********/
184 
myGlutMenu(int value)185 void myGlutMenu( int value )
186 {
187   myGlutKeyboard( value, 0, 0 );
188 }
189 
190 
191 /***************************************** myGlutIdle() ***********/
192 
myGlutIdle(void)193 void myGlutIdle( void )
194 {
195   /* According to the GLUT specification, the current window is
196      undefined during an idle callback.  So we need to explicitly change
197      it if necessary */
198   if ( glutGetWindow() != main_window )
199     glutSetWindow(main_window);
200 
201 
202   glutPostRedisplay();
203 
204   /****************************************************************/
205   /*            This demonstrates GLUI::sync_live()               */
206   /*   We change the value of a variable that is 'live' to some   */
207   /*   control.  We then call sync_live, and the control          */
208   /*   associated with that variable is automatically updated     */
209   /*   with the new value.  This frees the programmer from having */
210   /*   to always remember which variables are used by controls -  */
211   /*   simply change whatever variables are necessary, then sync  */
212   /*   the live ones all at once with a single call to sync_live  */
213   /****************************************************************/
214 
215   counter++;
216 
217   glui->sync_live();
218 
219 }
220 
221 /***************************************** myGlutMouse() **********/
222 
myGlutMouse(int button,int button_state,int x,int y)223 void myGlutMouse(int button, int button_state, int x, int y )
224 {
225   if ( button == GLUT_LEFT_BUTTON && button_state == GLUT_DOWN ) {
226     last_x = x;
227     last_y = y;
228   }
229 }
230 
231 
232 /***************************************** myGlutMotion() **********/
233 
myGlutMotion(int x,int y)234 void myGlutMotion(int x, int y )
235 {
236   rotationX += (float) (y - last_y);
237   rotationY += (float) (x - last_x);
238 
239   last_x = x;
240   last_y = y;
241 
242   glutPostRedisplay();
243 }
244 
245 /**************************************** myGlutReshape() *************/
246 
myGlutReshape(int x,int y)247 void myGlutReshape( int x, int y )
248 {
249   xy_aspect = (float)x / (float)y;
250   glViewport( 0, 0, x, y );
251 
252   glutPostRedisplay();
253 }
254 
255 /***************************************** myGlutDisplay() *****************/
256 
myGlutDisplay(void)257 void myGlutDisplay( void )
258 {
259   glClearColor( .9f, .9f, .9f, 1.0f );
260   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
261 
262   glMatrixMode( GL_PROJECTION );
263   glLoadIdentity();
264   glFrustum( -xy_aspect*.08, xy_aspect*.08, -.08, .08, .1, 15.0 );
265 
266   glMatrixMode( GL_MODELVIEW );
267   glLoadIdentity();
268   glTranslatef( 0.0, 0.0, -1.2f );
269   glRotatef( rotationY, 0.0, 1.0, 0.0 );
270   glRotatef( rotationX, 1.0, 0.0, 0.0 );
271 
272   glScalef( scale, scale, scale );
273 
274   /*** Now we render object, using the variables 'obj_type', 'segments', and
275     'wireframe'.  These are _live_ variables, which are transparently
276     updated by GLUI ***/
277 
278   if ( obj_type == 0 ) {
279     if ( wireframe )
280       glutWireSphere( .6, segments, segments );
281     else
282       glutSolidSphere( .6, segments, segments );
283   }
284   else if ( obj_type == 1 ) {
285     if ( wireframe )
286       glutWireTorus( .2,.5,16,segments );
287     else
288       glutSolidTorus( .2,.5,16,segments );
289   }
290   else if ( obj_type == 2 ) {
291     if ( wireframe )
292       glutWireTeapot( .5 );
293     else
294       glutSolidTeapot( .5 );
295   }
296 
297   /* Disable lighting and set up ortho projection to render text */
298   glDisable( GL_LIGHTING );
299   glMatrixMode( GL_PROJECTION );
300   glLoadIdentity();
301   gluOrtho2D( 0.0, 100.0, 0.0, 100.0  );
302   glMatrixMode( GL_MODELVIEW );
303   glLoadIdentity();
304   glColor3ub( 0, 0, 0 );
305   glRasterPos2i( 10, 10 );
306 
307   /*** Render the live character array 'text' ***/
308   for (unsigned int i=0; i<text.length(); ++i)
309     glutBitmapCharacter( GLUT_BITMAP_HELVETICA_18, text[i] );
310 
311   glEnable( GL_LIGHTING );
312 
313   glutSwapBuffers();
314 }
315 
316 
317 /**************************************** main() ********************/
318 
main(int argc,char * argv[])319 int main(int argc, char* argv[])
320 {
321   /****************************************/
322   /*   Initialize GLUT and create window  */
323   /****************************************/
324 
325   glutInit(&argc, argv);
326   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
327   glutInitWindowPosition( 50, 50 );
328   glutInitWindowSize( 300, 300 );
329 
330   main_window = glutCreateWindow( "GLUI Example 3" );
331   glutDisplayFunc( myGlutDisplay );
332   glutReshapeFunc( myGlutReshape );
333   glutKeyboardFunc( myGlutKeyboard );
334   glutMotionFunc( myGlutMotion );
335   glutMouseFunc( myGlutMouse );
336 
337   /****************************************/
338   /*       Set up OpenGL lights           */
339   /****************************************/
340 
341   glEnable(GL_LIGHTING);
342   glEnable( GL_NORMALIZE );
343 
344   glEnable(GL_LIGHT0);
345   glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
346   glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
347   glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
348 
349   glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
350   glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
351   glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
352 
353   /****************************************/
354   /*          Enable z-buferring          */
355   /****************************************/
356 
357   glEnable(GL_DEPTH_TEST);
358 
359   /****************************************/
360   /*         Here's the GLUI code         */
361   /****************************************/
362 
363   printf( "GLUI version: %3.2f\n", GLUI_Master.get_version() );
364 
365   glui = GLUI_Master.create_glui( "GLUI", 0, 400, 50 ); /* name, flags,
366 							   x, and y */
367   new GLUI_StaticText( glui, "GLUI Example 3" );
368   obj_panel = new GLUI_Panel(glui, "Object" );
369 
370   /***** Control for the object type *****/
371 
372   GLUI_Panel *type_panel = new GLUI_Panel( obj_panel, "Type" );
373   radio = new GLUI_RadioGroup(type_panel,&obj_type,4,control_cb);
374   new GLUI_RadioButton( radio, "Sphere" );
375   new GLUI_RadioButton( radio, "Torus" );
376   new GLUI_RadioButton( radio, "Teapot" );
377 
378   checkbox =
379     new GLUI_Checkbox(obj_panel, "Wireframe", &wireframe, 1, control_cb );
380   spinner =
381     new GLUI_Spinner( obj_panel, "Segments:", &segments);
382   spinner->set_int_limits( 3, 60 );
383   spinner->set_alignment( GLUI_ALIGN_RIGHT );
384 
385   scale_spinner =
386     new GLUI_Spinner( obj_panel, "Scale:", &scale);
387   scale_spinner->set_float_limits( .2f, 4.0 );
388   scale_spinner->set_alignment( GLUI_ALIGN_RIGHT );
389 
390   new GLUI_Separator( obj_panel );
391   edittext = new GLUI_EditText( obj_panel, "Text:", text );
392   edittext->set_w( 150 );
393 
394   /******** Add some controls for lights ********/
395 
396   GLUI_Panel *light0 = new GLUI_Panel( glui, "Light 1" );
397   GLUI_Panel *light1 = new GLUI_Panel( glui, "Light 2" );
398 
399   new GLUI_Checkbox( light0, "Enabled", &light0_enabled,
400                      LIGHT0_ENABLED_ID, control_cb );
401   light0_spinner =
402     new GLUI_Spinner( light0, "Intensity:",
403                       &light0_intensity, LIGHT0_INTENSITY_ID,
404                       control_cb );
405   light0_spinner->set_float_limits( 0.0, 1.0 );
406 
407   new GLUI_Checkbox( light1, "Enabled", &light1_enabled,
408                      LIGHT1_ENABLED_ID, control_cb );
409   light1_spinner =
410     new GLUI_Spinner( light1, "Intensity:",
411                       &light1_intensity, LIGHT1_INTENSITY_ID,
412                       control_cb );
413   light1_spinner->set_float_limits( 0.0, 1.0 );
414   light1_spinner->disable();   /* Disable this light initially */
415 
416   /****** Add a grayed-out counter *****/
417 
418   GLUI_EditText *counter_edittext =
419     new GLUI_EditText( glui, "Count:", &counter );
420   counter_edittext->disable();
421 
422   /****** Button to Open Command Line Window ******/
423   open_console_btn =
424     new GLUI_Button(glui, "Open Console", OPEN_CONSOLE_ID, pointer_cb);
425 
426   /****** A 'quit' button *****/
427 
428   new GLUI_Button(glui, "Quit", 0,(GLUI_Update_CB)exit );
429 
430   /**** Link windows to GLUI, and register idle callback ******/
431 
432   glui->set_main_gfx_window( main_window );
433 
434   /* We register the idle callback with GLUI, not with GLUT */
435   GLUI_Master.set_glutIdleFunc( myGlutIdle );
436 
437   /**** Regular GLUT main loop ****/
438   glutMainLoop();
439 
440   return EXIT_SUCCESS;
441 }
442 
443