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