~ubuntu-branches/ubuntu/gutsy/gtkglext/gutsy

« back to all changes in this revision

Viewing changes to examples/coolwave.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-04-03 17:43:17 UTC
  • Revision ID: james.westby@ubuntu.com-20040403174317-d5gb2d2gftaligp8
Tags: upstream-1.0.6
ImportĀ upstreamĀ versionĀ 1.0.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 * coolwave.c
 
3
 *
 
4
 * Copyright (c) 2002 Alif Wahid <awah005@users.sourceforge.net>
 
5
 *
 
6
 * A program to demonstrate GtkGLExt. It's a modified version
 
7
 * of the old IrisGL demo 'newave', first ported to OpenGL and
 
8
 * Glut by Erik Larsen. Now I have modified it to use Gtk and GtkGLExt
 
9
 * comprehensively along with ofcourse OpenGL.
 
10
 *
 
11
 * This program is in the public domain and you are using it at
 
12
 * your own risk.
 
13
 *
 
14
 **************************************************************************/
 
15
 
 
16
/* 
 
17
 * Modified by Naofumi Yasufuku  <naofumi@users.sourceforge.net>
 
18
 */
 
19
 
 
20
/**************************************************************************
 
21
 * Header file inclusions.
 
22
 **************************************************************************/
 
23
 
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <math.h>
 
27
 
 
28
#include <gtk/gtk.h>
 
29
#include <gdk/gdkkeysyms.h>
 
30
 
 
31
#include <gtk/gtkgl.h>
 
32
/*** Use OpenGL extensions. ***/
 
33
#include <gdk/gdkglglext.h>
 
34
 
 
35
#ifdef G_OS_WIN32
 
36
#define WIN32_LEAN_AND_MEAN 1
 
37
#include <windows.h>
 
38
#endif
 
39
 
 
40
#include <GL/gl.h>
 
41
#include <GL/glu.h>
 
42
 
 
43
 
 
44
/**************************************************************************
 
45
 * The following section contains all the macro definitions.
 
46
 **************************************************************************/
 
47
 
 
48
#define DEFAULT_WIDTH  300
 
49
#define DEFAULT_HEIGHT 200
 
50
#define DEFAULT_TITLE  "CoolWave"
 
51
 
 
52
#define TIMEOUT_INTERVAL 10
 
53
 
 
54
#define MAXGRID 63
 
55
#define SQRTOFTWOINV (1.0 / 1.414213562)
 
56
 
 
57
 
 
58
/**************************************************************************
 
59
 * Global variable declarations.
 
60
 **************************************************************************/
 
61
 
 
62
static gboolean animate = TRUE;
 
63
 
 
64
static int grid = (MAXGRID/2);
 
65
static int beginX, beginY;
 
66
 
 
67
static float force[MAXGRID][MAXGRID];
 
68
static float veloc[MAXGRID][MAXGRID];
 
69
static float posit[MAXGRID][MAXGRID];
 
70
 
 
71
static float dt = 0.008;
 
72
static float sphi = 90.0;
 
73
static float stheta = 45.0;
 
74
static float sdepth = 5.0/4.0 * (MAXGRID/2);
 
75
static float zNear = (MAXGRID/2)/10.0;
 
76
static float zFar = (MAXGRID/2)*3.0;
 
77
static float aspect = 5.0/4.0;
 
78
 
 
79
static float lightPosition[4] = {0.0, 0.0, 1.0, 1.0};
 
80
 
 
81
 
 
82
/**************************************************************************
 
83
 * The following section contains the function prototype declarations.
 
84
 **************************************************************************/
 
85
 
 
86
static void         timeout_add       (GtkWidget   *widget);
 
87
static void         timeout_remove    (GtkWidget   *widget);
 
88
 
 
89
static void         toggle_animation  (GtkWidget   *widget);
 
90
static void         init_wireframe    (GtkWidget   *widget);
 
91
 
 
92
static GdkGLConfig *configure_gl      (void);
 
93
 
 
94
static GtkWidget   *create_popup_menu (GtkWidget   *drawing_area);
 
95
static GtkWidget   *create_window     (GdkGLConfig *glconfig);
 
96
 
 
97
 
 
98
/**************************************************************************
 
99
 * The waving functions.
 
100
 **************************************************************************/
 
101
 
 
102
void getforce (void)
 
103
{
 
104
  int i=0, j=0;
 
105
  float d;
 
106
 
 
107
  for(i=0;i<grid;i++)
 
108
    {
 
109
      for(j=0;j<grid;j++)
 
110
        {
 
111
          force[i][j]=0.0;
 
112
        }
 
113
    }
 
114
 
 
115
  for(i=2;i<grid-2;i++)
 
116
    {
 
117
      for(j=2;j<grid-2;j++)
 
118
        {
 
119
          d=posit[i][j]-posit[i][j-1];
 
120
          force[i][j] -= d;
 
121
          force[i][j-1] += d;
 
122
 
 
123
          d=posit[i][j]-posit[i-1][j];
 
124
          force[i][j] -= d;
 
125
          force[i-1][j] += d;
 
126
 
 
127
          d= (posit[i][j]-posit[i][j+1]);
 
128
          force[i][j] -= d ;
 
129
          force[i][j+1] += d;
 
130
 
 
131
          d= (posit[i][j]-posit[i+1][j]);
 
132
          force[i][j] -= d ;
 
133
          force[i+1][j] += d;
 
134
 
 
135
          d= (posit[i][j]-posit[i+1][j+1])*SQRTOFTWOINV;
 
136
          force[i][j] -= d ;
 
137
          force[i+1][j+1] += d;
 
138
 
 
139
          d= (posit[i][j]-posit[i-1][j-1])*SQRTOFTWOINV;
 
140
          force[i][j] -= d ;
 
141
          force[i-1][j-1] += d;
 
142
 
 
143
          d= (posit[i][j]-posit[i+1][j-1])*SQRTOFTWOINV;
 
144
          force[i][j] -= d ;
 
145
          force[i+1][j-1] += d;
 
146
 
 
147
          d= (posit[i][j]-posit[i-1][j+1])*SQRTOFTWOINV;
 
148
          force[i][j] -= d ;
 
149
          force[i- 1][j+1] += d;
 
150
        }
 
151
    }
 
152
}
 
153
 
 
154
void getvelocity (void)
 
155
{
 
156
  int i=0, j=0;
 
157
 
 
158
  for(i=0;i<grid;i++)
 
159
    {
 
160
      for(j=0;j<grid;j++) veloc[i][j]+=force[i][j] * dt;
 
161
    }
 
162
}
 
163
 
 
164
void getposition (void)
 
165
{
 
166
  int i=0, j=0;
 
167
 
 
168
  for(i=0;i<grid;i++)
 
169
    {
 
170
      for(j=0;j<grid;j++) posit[i][j]+=veloc[i][j];
 
171
    }
 
172
}
 
173
 
 
174
void drawWireframe (void)
 
175
{
 
176
  int i=0, j=0;
 
177
 
 
178
  glColor3f(1.0, 1.0, 1.0);
 
179
 
 
180
  for(i=0;i<grid;i++)
 
181
    {
 
182
      glBegin(GL_LINE_STRIP);
 
183
      for(j=0;j<grid;j++) glVertex3f((float)i,(float)j,(float)posit[i][j]);
 
184
      glEnd();
 
185
    }
 
186
 
 
187
  for(i=0;i<grid;i++)
 
188
    {
 
189
      glBegin(GL_LINE_STRIP);
 
190
      for(j=0;j<grid;j++) glVertex3f((float)j,(float)i,(float)posit[j][i]);
 
191
      glEnd();
 
192
    }
 
193
}
 
194
 
 
195
void resetWireframe (void)
 
196
{
 
197
  int i=0, j=0;
 
198
 
 
199
  for(i=0;i<grid;i++)
 
200
    {
 
201
      for(j=0;j<grid;j++)
 
202
        {
 
203
          force[i][j]=0.0;
 
204
          veloc[i][j]=0.0;
 
205
 
 
206
          posit[i][j]=  (sin(G_PI*2 * ((float)i/(float)grid)) +
 
207
                         sin(G_PI*2 * ((float)j/(float)grid)))* grid/6.0;
 
208
 
 
209
          if (i==0||j==0||i==grid-1||j==grid-1) posit[i][j]=0.0;
 
210
        }
 
211
    }
 
212
}
 
213
 
 
214
 
 
215
/**************************************************************************
 
216
 * The following section contains all the callback function definitions.
 
217
 **************************************************************************/
 
218
 
 
219
/***
 
220
 *** The "realize" signal handler. All the OpenGL initialization
 
221
 *** should be performed here, such as default background colour,
 
222
 *** certain states etc.
 
223
 ***/
 
224
static void
 
225
realize (GtkWidget *widget,
 
226
         gpointer   data)
 
227
{
 
228
  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
 
229
  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
 
230
 
 
231
  GdkGLProc proc = NULL;
 
232
 
 
233
  /*** OpenGL BEGIN ***/
 
234
  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
 
235
    return;
 
236
 
 
237
  /* glPolygonOffsetEXT */
 
238
  proc = gdk_gl_get_glPolygonOffsetEXT ();
 
239
  if (proc == NULL)
 
240
    {
 
241
      /* glPolygonOffset */
 
242
      proc = gdk_gl_get_proc_address ("glPolygonOffset");
 
243
      if (proc == NULL)
 
244
        {
 
245
          g_print ("Sorry, glPolygonOffset() is not supported by this renderer.\n");
 
246
          exit (1);
 
247
        }
 
248
    }
 
249
 
 
250
  glEnable (GL_DEPTH_TEST);
 
251
  glDepthFunc (GL_LEQUAL);
 
252
  glClearColor (0.0, 0.0, 0.0, 0.0);
 
253
  gdk_gl_glPolygonOffsetEXT (proc, 1.0, 1.0);
 
254
  glEnable (GL_CULL_FACE);
 
255
  glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
 
256
  glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
 
257
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 
258
  glEnable (GL_COLOR_MATERIAL);
 
259
  glColorMaterial (GL_FRONT, GL_DIFFUSE);
 
260
  glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
 
261
  glEnable (GL_LIGHT0);
 
262
  glShadeModel (GL_FLAT);
 
263
  glDisable (GL_LIGHTING);
 
264
 
 
265
  resetWireframe ();
 
266
 
 
267
  gdk_gl_drawable_gl_end (gldrawable);
 
268
  /*** OpenGL END ***/
 
269
 
 
270
  return;
 
271
}
 
272
 
 
273
/***
 
274
 *** The "configure_event" signal handler. Any processing required when
 
275
 *** the OpenGL-capable drawing area is re-configured should be done here.
 
276
 *** Almost always it will be used to resize the OpenGL viewport when
 
277
 *** the window is resized.
 
278
 ***/
 
279
static gboolean
 
280
configure_event (GtkWidget         *widget,
 
281
                 GdkEventConfigure *event,
 
282
                 gpointer           data)
 
283
{
 
284
  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
 
285
  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
 
286
 
 
287
  GLfloat w = widget->allocation.width;
 
288
  GLfloat h = widget->allocation.height;
 
289
 
 
290
  /*** OpenGL BEGIN ***/
 
291
  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
 
292
    return FALSE;
 
293
 
 
294
  aspect = (float)w/(float)h;
 
295
  glViewport (0, 0, w, h);
 
296
 
 
297
  gdk_gl_drawable_gl_end (gldrawable);
 
298
  /*** OpenGL END ***/
 
299
 
 
300
  return TRUE;
 
301
}
 
302
 
 
303
/***
 
304
 *** The "expose_event" signal handler. All the OpenGL re-drawing should
 
305
 *** be done here. This is repeatedly called as the painting routine
 
306
 *** every time the 'expose'/'draw' event is signalled.
 
307
 ***/
 
308
static gboolean
 
309
expose_event (GtkWidget      *widget,
 
310
              GdkEventExpose *event,
 
311
              gpointer        data)
 
312
{
 
313
  GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
 
314
  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
 
315
 
 
316
  /*** OpenGL BEGIN ***/
 
317
  if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
 
318
    return FALSE;
 
319
 
 
320
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
321
 
 
322
  glMatrixMode (GL_PROJECTION);
 
323
  glLoadIdentity ();
 
324
  gluPerspective (64.0, aspect, zNear, zFar);
 
325
  glMatrixMode (GL_MODELVIEW);
 
326
  glLoadIdentity ();
 
327
 
 
328
  glTranslatef (0.0,0.0,-sdepth);
 
329
  glRotatef (-stheta, 1.0, 0.0, 0.0);
 
330
  glRotatef (sphi, 0.0, 0.0, 1.0);
 
331
  glTranslatef (-(float)((grid+1)/2-1), -(float)((grid+1)/2-1), 0.0);
 
332
 
 
333
  drawWireframe ();
 
334
 
 
335
  /* Swap buffers */
 
336
  if (gdk_gl_drawable_is_double_buffered (gldrawable))
 
337
    gdk_gl_drawable_swap_buffers (gldrawable);
 
338
  else
 
339
    glFlush ();
 
340
 
 
341
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
342
 
 
343
  gdk_gl_drawable_gl_end (gldrawable);
 
344
  /*** OpenGL END ***/
 
345
 
 
346
  return TRUE;
 
347
}
 
348
 
 
349
/***
 
350
 *** The timeout function. Often in animations,
 
351
 *** timeout functions are suitable for continous
 
352
 *** frame updates.
 
353
 ***/
 
354
static gboolean
 
355
timeout (GtkWidget *widget)
 
356
{
 
357
  getforce ();
 
358
  getvelocity ();
 
359
  getposition ();
 
360
 
 
361
  /* Invalidate the whole window. */
 
362
  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
 
363
 
 
364
  /* Update synchronously (fast). */
 
365
  gdk_window_process_updates (widget->window, FALSE);
 
366
 
 
367
  return TRUE;
 
368
}
 
369
 
 
370
/***
 
371
 *** The "motion_notify_event" signal handler. Any processing required when
 
372
 *** the OpenGL-capable drawing area is under drag motion should be done here.
 
373
 ***/
 
374
static gboolean
 
375
motion_notify_event (GtkWidget      *widget,
 
376
                     GdkEventMotion *event,
 
377
                     gpointer        data)
 
378
{
 
379
  gboolean redraw = FALSE;
 
380
 
 
381
  if (event->state & GDK_BUTTON1_MASK)
 
382
    {
 
383
      sphi += (float)(event->x - beginX) / 4.0;
 
384
      stheta += (float)(beginY - event->y) / 4.0;
 
385
 
 
386
      redraw = TRUE;
 
387
    }
 
388
 
 
389
  if (event->state & GDK_BUTTON2_MASK)
 
390
    {
 
391
      sdepth -= ((event->y - beginY)/(widget->allocation.height))*(MAXGRID/2);
 
392
 
 
393
      redraw = TRUE;
 
394
    }
 
395
 
 
396
  beginX = event->x;
 
397
  beginY = event->y;
 
398
 
 
399
  if (redraw && !animate)
 
400
    gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
 
401
 
 
402
  return TRUE;
 
403
}
 
404
 
 
405
/***
 
406
 *** The "button_press_event" signal handler. Any processing required when
 
407
 *** mouse buttons (only left and middle buttons) are pressed on the OpenGL-
 
408
 *** capable drawing area should be done here.
 
409
 ***/
 
410
static gboolean
 
411
button_press_event (GtkWidget      *widget,
 
412
                    GdkEventButton *event,
 
413
                    gpointer        data)
 
414
{
 
415
  if (event->button == 1)
 
416
    {
 
417
      beginX = event->x;
 
418
      beginY = event->y;
 
419
      return TRUE;
 
420
    }
 
421
 
 
422
  if (event->button == 2)
 
423
    {
 
424
      beginX = event->x;
 
425
      beginY = event->y;
 
426
      return TRUE;
 
427
    }
 
428
 
 
429
  return FALSE;
 
430
}
 
431
 
 
432
/* For popup menu. */
 
433
static gboolean
 
434
button_press_event_popup_menu (GtkWidget      *widget,
 
435
                               GdkEventButton *event,
 
436
                               gpointer        data)
 
437
{
 
438
  if (event->button == 3)
 
439
    {
 
440
      /* Popup menu. */
 
441
      gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
 
442
                      event->button, event->time);
 
443
      return TRUE;
 
444
    }
 
445
 
 
446
  return FALSE;
 
447
}
 
448
 
 
449
/***
 
450
 *** The "key_press_event" signal handler. Any processing required when key
 
451
 *** presses occur should be done here.
 
452
 ***/
 
453
static gboolean
 
454
key_press_event (GtkWidget   *widget,
 
455
                 GdkEventKey *event,
 
456
                 gpointer     data)
 
457
{
 
458
  switch (event->keyval)
 
459
    {
 
460
    case GDK_r:
 
461
      init_wireframe (widget);
 
462
      break;
 
463
 
 
464
    case GDK_a:
 
465
      toggle_animation (widget);
 
466
      break;
 
467
 
 
468
    case GDK_w:
 
469
      if (!animate)
 
470
        timeout (widget);
 
471
      break;
 
472
 
 
473
    case GDK_plus:
 
474
      sdepth -= 2.0;
 
475
      break;
 
476
 
 
477
    case GDK_minus:
 
478
      sdepth += 2.0;
 
479
      break;
 
480
 
 
481
    case GDK_Escape:
 
482
      gtk_main_quit ();
 
483
      break;
 
484
 
 
485
    default:
 
486
      return FALSE;
 
487
    }
 
488
 
 
489
  if (!animate)
 
490
    gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
 
491
 
 
492
  return TRUE;
 
493
}
 
494
 
 
495
/***
 
496
 *** The "unrealize" signal handler. Any processing required when
 
497
 *** the OpenGL-capable window is unrealized should be done here.
 
498
 ***/
 
499
static void
 
500
unrealize (GtkWidget *widget,
 
501
           gpointer   data)
 
502
{
 
503
  /*** Fill in the details here ***/
 
504
 
 
505
}
 
506
 
 
507
 
 
508
/**************************************************************************
 
509
 * The following section contains the timeout function management routines.
 
510
 **************************************************************************/
 
511
 
 
512
/***
 
513
 *** Helper functions to add or remove the timeout function.
 
514
 ***/
 
515
 
 
516
static guint timeout_id = 0;
 
517
 
 
518
static void
 
519
timeout_add (GtkWidget *widget)
 
520
{
 
521
  if (timeout_id == 0)
 
522
    {
 
523
      timeout_id = g_timeout_add (TIMEOUT_INTERVAL,
 
524
                                  (GSourceFunc) timeout,
 
525
                                  widget);
 
526
    }
 
527
}
 
528
 
 
529
static void
 
530
timeout_remove (GtkWidget *widget)
 
531
{
 
532
  if (timeout_id != 0)
 
533
    {
 
534
      g_source_remove (timeout_id);
 
535
      timeout_id = 0;
 
536
    }
 
537
}
 
538
 
 
539
/***
 
540
 *** The "map_event" signal handler. Any processing required when the
 
541
 *** OpenGL-capable drawing area is mapped should be done here.
 
542
 ***/
 
543
static gboolean
 
544
map_event (GtkWidget *widget,
 
545
           GdkEvent  *event,
 
546
           gpointer   data)
 
547
{
 
548
  if (animate)
 
549
    timeout_add (widget);
 
550
 
 
551
  return TRUE;
 
552
}
 
553
 
 
554
/***
 
555
 *** The "unmap_event" signal handler. Any processing required when the
 
556
 *** OpenGL-capable drawing area is unmapped should be done here.
 
557
 ***/
 
558
static gboolean
 
559
unmap_event (GtkWidget *widget,
 
560
             GdkEvent  *event,
 
561
             gpointer   data)
 
562
{
 
563
  timeout_remove (widget);
 
564
 
 
565
  return TRUE;
 
566
}
 
567
 
 
568
/***
 
569
 *** The "visibility_notify_event" signal handler. Any processing required
 
570
 *** when the OpenGL-capable drawing area is visually obscured should be
 
571
 *** done here.
 
572
 ***/
 
573
static gboolean
 
574
visibility_notify_event (GtkWidget          *widget,
 
575
                         GdkEventVisibility *event,
 
576
                         gpointer            data)
 
577
{
 
578
  if (animate)
 
579
    {
 
580
      if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
 
581
        timeout_remove (widget);
 
582
      else
 
583
        timeout_add (widget);
 
584
    }
 
585
 
 
586
  return TRUE;
 
587
}
 
588
 
 
589
 
 
590
/**************************************************************************
 
591
 * The following section contains some miscellaneous utility functions.
 
592
 **************************************************************************/
 
593
 
 
594
/***
 
595
 *** Toggle animation.
 
596
 ***/
 
597
static void
 
598
toggle_animation (GtkWidget *widget)
 
599
{
 
600
  animate = !animate;
 
601
 
 
602
  if (animate)
 
603
    {
 
604
      timeout_add (widget);
 
605
    }
 
606
  else
 
607
    {
 
608
      timeout_remove (widget);
 
609
      gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
 
610
    }
 
611
}
 
612
 
 
613
/***
 
614
 *** Init wireframe model.
 
615
 ***/
 
616
static void
 
617
init_wireframe (GtkWidget *widget)
 
618
{
 
619
  resetWireframe ();
 
620
  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
 
621
}
 
622
 
 
623
 
 
624
/**************************************************************************
 
625
 * The following section contains the GUI building function definitions.
 
626
 **************************************************************************/
 
627
 
 
628
/***
 
629
 *** Creates the popup menu to be displayed.
 
630
 ***/
 
631
static GtkWidget *
 
632
create_popup_menu (GtkWidget *drawing_area)
 
633
{
 
634
  GtkWidget *menu;
 
635
  GtkWidget *menu_item;
 
636
 
 
637
  menu = gtk_menu_new ();
 
638
 
 
639
  /* Toggle animation */
 
640
  menu_item = gtk_menu_item_new_with_label ("Toggle Animation");
 
641
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 
642
  g_signal_connect_swapped (G_OBJECT (menu_item), "activate",
 
643
                            G_CALLBACK (toggle_animation), drawing_area);
 
644
  gtk_widget_show (menu_item);
 
645
 
 
646
  /* Init wireframe model */
 
647
  menu_item = gtk_menu_item_new_with_label ("Initialize");
 
648
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 
649
  g_signal_connect_swapped (G_OBJECT (menu_item), "activate",
 
650
                            G_CALLBACK (init_wireframe), drawing_area);
 
651
  gtk_widget_show (menu_item);
 
652
 
 
653
  /* Quit */
 
654
  menu_item = gtk_menu_item_new_with_label ("Quit");
 
655
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 
656
  g_signal_connect (G_OBJECT (menu_item), "activate",
 
657
                    G_CALLBACK (gtk_main_quit), NULL);
 
658
  gtk_widget_show (menu_item);
 
659
        
 
660
  return menu;
 
661
}
 
662
 
 
663
/***
 
664
 *** Creates the simple application window with one
 
665
 *** drawing area that has an OpenGL-capable visual.
 
666
 ***/
 
667
static GtkWidget *
 
668
create_window (GdkGLConfig *glconfig)
 
669
{
 
670
  GtkWidget *window;
 
671
  GtkWidget *vbox;
 
672
  GtkWidget *drawing_area;
 
673
  GtkWidget *menu;
 
674
  GtkWidget *button;
 
675
 
 
676
  /*
 
677
   * Top-level window.
 
678
   */
 
679
 
 
680
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
681
  gtk_window_set_title (GTK_WINDOW (window), DEFAULT_TITLE);
 
682
 
 
683
  /* Get automatically redrawn if any of their children changed allocation. */
 
684
  gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
 
685
 
 
686
  /* Connect signal handlers to the window */
 
687
  g_signal_connect (G_OBJECT (window), "delete_event",
 
688
                    G_CALLBACK (gtk_main_quit), NULL);
 
689
 
 
690
  /*
 
691
   * VBox.
 
692
   */
 
693
 
 
694
  vbox = gtk_vbox_new (FALSE, 0);
 
695
  gtk_container_add (GTK_CONTAINER (window), vbox);
 
696
  gtk_widget_show (vbox);
 
697
 
 
698
  /*
 
699
   * Drawing area to draw OpenGL scene.
 
700
   */
 
701
 
 
702
  drawing_area = gtk_drawing_area_new ();
 
703
  gtk_widget_set_size_request (drawing_area, DEFAULT_WIDTH, DEFAULT_HEIGHT);
 
704
 
 
705
  /* Set OpenGL-capability to the widget */
 
706
  gtk_widget_set_gl_capability (drawing_area,
 
707
                                glconfig,
 
708
                                NULL,
 
709
                                TRUE,
 
710
                                GDK_GL_RGBA_TYPE);
 
711
 
 
712
  gtk_widget_add_events (drawing_area,
 
713
                         GDK_BUTTON1_MOTION_MASK    |
 
714
                         GDK_BUTTON2_MOTION_MASK    |
 
715
                         GDK_BUTTON_PRESS_MASK      |
 
716
                         GDK_VISIBILITY_NOTIFY_MASK);
 
717
 
 
718
  /* Connect signal handlers to the drawing area */
 
719
  g_signal_connect_after (G_OBJECT (drawing_area), "realize",
 
720
                          G_CALLBACK (realize), NULL);
 
721
  g_signal_connect (G_OBJECT (drawing_area), "configure_event",
 
722
                    G_CALLBACK (configure_event), NULL);
 
723
  g_signal_connect (G_OBJECT (drawing_area), "expose_event",
 
724
                    G_CALLBACK (expose_event), NULL);
 
725
 
 
726
  g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
 
727
                    G_CALLBACK (motion_notify_event), NULL);
 
728
  g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
 
729
                    G_CALLBACK (button_press_event), NULL);
 
730
  g_signal_connect (G_OBJECT (drawing_area), "unrealize",
 
731
                    G_CALLBACK (unrealize), NULL);
 
732
 
 
733
  /* key_press_event handler for top-level window */
 
734
  g_signal_connect_swapped (G_OBJECT (window), "key_press_event",
 
735
                            G_CALLBACK (key_press_event), drawing_area);
 
736
 
 
737
  /* For timeout function. */
 
738
  g_signal_connect (G_OBJECT (drawing_area), "map_event",
 
739
                    G_CALLBACK (map_event), NULL);
 
740
  g_signal_connect (G_OBJECT (drawing_area), "unmap_event",
 
741
                    G_CALLBACK (unmap_event), NULL);
 
742
  g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event",
 
743
                    G_CALLBACK (visibility_notify_event), NULL);
 
744
 
 
745
  gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
 
746
 
 
747
  gtk_widget_show (drawing_area);
 
748
 
 
749
  /*
 
750
   * Popup menu.
 
751
   */
 
752
 
 
753
  menu = create_popup_menu (drawing_area);
 
754
 
 
755
  g_signal_connect_swapped (G_OBJECT (drawing_area), "button_press_event",
 
756
                            G_CALLBACK (button_press_event_popup_menu), menu);
 
757
 
 
758
  /*
 
759
   * Simple quit button.
 
760
   */
 
761
 
 
762
  button = gtk_button_new_with_label ("Quit");
 
763
 
 
764
  g_signal_connect (G_OBJECT (button), "clicked",
 
765
                    G_CALLBACK (gtk_main_quit), NULL);
 
766
 
 
767
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
768
 
 
769
  gtk_widget_show (button);
 
770
 
 
771
  return window;
 
772
}
 
773
 
 
774
 
 
775
/**************************************************************************
 
776
 * The following section contains utility function definitions.
 
777
 **************************************************************************/
 
778
 
 
779
/***
 
780
 *** Configure the OpenGL framebuffer.
 
781
 ***/
 
782
static GdkGLConfig *
 
783
configure_gl (void)
 
784
{
 
785
  GdkGLConfig *glconfig;
 
786
 
 
787
  /* Try double-buffered visual */
 
788
  glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB    |
 
789
                                        GDK_GL_MODE_DEPTH  |
 
790
                                        GDK_GL_MODE_DOUBLE);
 
791
  if (glconfig == NULL)
 
792
    {
 
793
      g_print ("\n*** Cannot find the double-buffered visual.\n");
 
794
      g_print ("\n*** Trying single-buffered visual.\n");
 
795
 
 
796
      /* Try single-buffered visual */
 
797
      glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB   |
 
798
                                            GDK_GL_MODE_DEPTH);
 
799
      if (glconfig == NULL)
 
800
        {
 
801
          g_print ("*** No appropriate OpenGL-capable visual found.\n");
 
802
          exit (1);
 
803
        }
 
804
    }
 
805
 
 
806
  return glconfig;
 
807
}
 
808
 
 
809
 
 
810
/**************************************************************************
 
811
 * The main function is rather trivial.
 
812
 **************************************************************************/
 
813
 
 
814
int
 
815
main (int   argc,
 
816
      char *argv[])
 
817
{
 
818
  GtkWidget *window;
 
819
  GdkGLConfig *glconfig;
 
820
 
 
821
  /* Initialize GTK. */
 
822
  gtk_init (&argc, &argv);
 
823
 
 
824
  /* Initialize GtkGLExt. */
 
825
  gtk_gl_init (&argc, &argv);
 
826
 
 
827
  /* Configure OpenGL framebuffer. */
 
828
  glconfig = configure_gl ();
 
829
 
 
830
  /* Create and show the application window. */
 
831
  window = create_window (glconfig);
 
832
  gtk_widget_show (window);
 
833
 
 
834
  gtk_main ();
 
835
 
 
836
  return 0;
 
837
}
 
838
 
 
839
 
 
840
/**************************************************************************
 
841
 * End of file.
 
842
 **************************************************************************/