1
/**************************************************************************
4
* Copyright (c) 2002 Alif Wahid <awah005@users.sourceforge.net>
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.
11
* This program is in the public domain and you are using it at
14
**************************************************************************/
17
* Modified by Naofumi Yasufuku <naofumi@users.sourceforge.net>
20
/**************************************************************************
21
* Header file inclusions.
22
**************************************************************************/
29
#include <gdk/gdkkeysyms.h>
31
#include <gtk/gtkgl.h>
32
/*** Use OpenGL extensions. ***/
33
#include <gdk/gdkglglext.h>
36
#define WIN32_LEAN_AND_MEAN 1
44
/**************************************************************************
45
* The following section contains all the macro definitions.
46
**************************************************************************/
48
#define DEFAULT_WIDTH 300
49
#define DEFAULT_HEIGHT 200
50
#define DEFAULT_TITLE "CoolWave"
52
#define TIMEOUT_INTERVAL 10
55
#define SQRTOFTWOINV (1.0 / 1.414213562)
58
/**************************************************************************
59
* Global variable declarations.
60
**************************************************************************/
62
static gboolean animate = TRUE;
64
static int grid = (MAXGRID/2);
65
static int beginX, beginY;
67
static float force[MAXGRID][MAXGRID];
68
static float veloc[MAXGRID][MAXGRID];
69
static float posit[MAXGRID][MAXGRID];
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;
79
static float lightPosition[4] = {0.0, 0.0, 1.0, 1.0};
82
/**************************************************************************
83
* The following section contains the function prototype declarations.
84
**************************************************************************/
86
static void timeout_add (GtkWidget *widget);
87
static void timeout_remove (GtkWidget *widget);
89
static void toggle_animation (GtkWidget *widget);
90
static void init_wireframe (GtkWidget *widget);
92
static GdkGLConfig *configure_gl (void);
94
static GtkWidget *create_popup_menu (GtkWidget *drawing_area);
95
static GtkWidget *create_window (GdkGLConfig *glconfig);
98
/**************************************************************************
99
* The waving functions.
100
**************************************************************************/
115
for(i=2;i<grid-2;i++)
117
for(j=2;j<grid-2;j++)
119
d=posit[i][j]-posit[i][j-1];
123
d=posit[i][j]-posit[i-1][j];
127
d= (posit[i][j]-posit[i][j+1]);
131
d= (posit[i][j]-posit[i+1][j]);
135
d= (posit[i][j]-posit[i+1][j+1])*SQRTOFTWOINV;
137
force[i+1][j+1] += d;
139
d= (posit[i][j]-posit[i-1][j-1])*SQRTOFTWOINV;
141
force[i-1][j-1] += d;
143
d= (posit[i][j]-posit[i+1][j-1])*SQRTOFTWOINV;
145
force[i+1][j-1] += d;
147
d= (posit[i][j]-posit[i-1][j+1])*SQRTOFTWOINV;
149
force[i- 1][j+1] += d;
154
void getvelocity (void)
160
for(j=0;j<grid;j++) veloc[i][j]+=force[i][j] * dt;
164
void getposition (void)
170
for(j=0;j<grid;j++) posit[i][j]+=veloc[i][j];
174
void drawWireframe (void)
178
glColor3f(1.0, 1.0, 1.0);
182
glBegin(GL_LINE_STRIP);
183
for(j=0;j<grid;j++) glVertex3f((float)i,(float)j,(float)posit[i][j]);
189
glBegin(GL_LINE_STRIP);
190
for(j=0;j<grid;j++) glVertex3f((float)j,(float)i,(float)posit[j][i]);
195
void resetWireframe (void)
206
posit[i][j]= (sin(G_PI*2 * ((float)i/(float)grid)) +
207
sin(G_PI*2 * ((float)j/(float)grid)))* grid/6.0;
209
if (i==0||j==0||i==grid-1||j==grid-1) posit[i][j]=0.0;
215
/**************************************************************************
216
* The following section contains all the callback function definitions.
217
**************************************************************************/
220
*** The "realize" signal handler. All the OpenGL initialization
221
*** should be performed here, such as default background colour,
222
*** certain states etc.
225
realize (GtkWidget *widget,
228
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
229
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
231
GdkGLProc proc = NULL;
233
/*** OpenGL BEGIN ***/
234
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
237
/* glPolygonOffsetEXT */
238
proc = gdk_gl_get_glPolygonOffsetEXT ();
241
/* glPolygonOffset */
242
proc = gdk_gl_get_proc_address ("glPolygonOffset");
245
g_print ("Sorry, glPolygonOffset() is not supported by this renderer.\n");
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);
267
gdk_gl_drawable_gl_end (gldrawable);
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.
280
configure_event (GtkWidget *widget,
281
GdkEventConfigure *event,
284
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
285
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
287
GLfloat w = widget->allocation.width;
288
GLfloat h = widget->allocation.height;
290
/*** OpenGL BEGIN ***/
291
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
294
aspect = (float)w/(float)h;
295
glViewport (0, 0, w, h);
297
gdk_gl_drawable_gl_end (gldrawable);
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.
309
expose_event (GtkWidget *widget,
310
GdkEventExpose *event,
313
GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
314
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
316
/*** OpenGL BEGIN ***/
317
if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
320
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
322
glMatrixMode (GL_PROJECTION);
324
gluPerspective (64.0, aspect, zNear, zFar);
325
glMatrixMode (GL_MODELVIEW);
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);
336
if (gdk_gl_drawable_is_double_buffered (gldrawable))
337
gdk_gl_drawable_swap_buffers (gldrawable);
341
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
343
gdk_gl_drawable_gl_end (gldrawable);
350
*** The timeout function. Often in animations,
351
*** timeout functions are suitable for continous
355
timeout (GtkWidget *widget)
361
/* Invalidate the whole window. */
362
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
364
/* Update synchronously (fast). */
365
gdk_window_process_updates (widget->window, FALSE);
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.
375
motion_notify_event (GtkWidget *widget,
376
GdkEventMotion *event,
379
gboolean redraw = FALSE;
381
if (event->state & GDK_BUTTON1_MASK)
383
sphi += (float)(event->x - beginX) / 4.0;
384
stheta += (float)(beginY - event->y) / 4.0;
389
if (event->state & GDK_BUTTON2_MASK)
391
sdepth -= ((event->y - beginY)/(widget->allocation.height))*(MAXGRID/2);
399
if (redraw && !animate)
400
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
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.
411
button_press_event (GtkWidget *widget,
412
GdkEventButton *event,
415
if (event->button == 1)
422
if (event->button == 2)
432
/* For popup menu. */
434
button_press_event_popup_menu (GtkWidget *widget,
435
GdkEventButton *event,
438
if (event->button == 3)
441
gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
442
event->button, event->time);
450
*** The "key_press_event" signal handler. Any processing required when key
451
*** presses occur should be done here.
454
key_press_event (GtkWidget *widget,
458
switch (event->keyval)
461
init_wireframe (widget);
465
toggle_animation (widget);
490
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
496
*** The "unrealize" signal handler. Any processing required when
497
*** the OpenGL-capable window is unrealized should be done here.
500
unrealize (GtkWidget *widget,
503
/*** Fill in the details here ***/
508
/**************************************************************************
509
* The following section contains the timeout function management routines.
510
**************************************************************************/
513
*** Helper functions to add or remove the timeout function.
516
static guint timeout_id = 0;
519
timeout_add (GtkWidget *widget)
523
timeout_id = g_timeout_add (TIMEOUT_INTERVAL,
524
(GSourceFunc) timeout,
530
timeout_remove (GtkWidget *widget)
534
g_source_remove (timeout_id);
540
*** The "map_event" signal handler. Any processing required when the
541
*** OpenGL-capable drawing area is mapped should be done here.
544
map_event (GtkWidget *widget,
549
timeout_add (widget);
555
*** The "unmap_event" signal handler. Any processing required when the
556
*** OpenGL-capable drawing area is unmapped should be done here.
559
unmap_event (GtkWidget *widget,
563
timeout_remove (widget);
569
*** The "visibility_notify_event" signal handler. Any processing required
570
*** when the OpenGL-capable drawing area is visually obscured should be
574
visibility_notify_event (GtkWidget *widget,
575
GdkEventVisibility *event,
580
if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
581
timeout_remove (widget);
583
timeout_add (widget);
590
/**************************************************************************
591
* The following section contains some miscellaneous utility functions.
592
**************************************************************************/
595
*** Toggle animation.
598
toggle_animation (GtkWidget *widget)
604
timeout_add (widget);
608
timeout_remove (widget);
609
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
614
*** Init wireframe model.
617
init_wireframe (GtkWidget *widget)
620
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
624
/**************************************************************************
625
* The following section contains the GUI building function definitions.
626
**************************************************************************/
629
*** Creates the popup menu to be displayed.
632
create_popup_menu (GtkWidget *drawing_area)
635
GtkWidget *menu_item;
637
menu = gtk_menu_new ();
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);
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);
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);
664
*** Creates the simple application window with one
665
*** drawing area that has an OpenGL-capable visual.
668
create_window (GdkGLConfig *glconfig)
672
GtkWidget *drawing_area;
680
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
681
gtk_window_set_title (GTK_WINDOW (window), DEFAULT_TITLE);
683
/* Get automatically redrawn if any of their children changed allocation. */
684
gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
686
/* Connect signal handlers to the window */
687
g_signal_connect (G_OBJECT (window), "delete_event",
688
G_CALLBACK (gtk_main_quit), NULL);
694
vbox = gtk_vbox_new (FALSE, 0);
695
gtk_container_add (GTK_CONTAINER (window), vbox);
696
gtk_widget_show (vbox);
699
* Drawing area to draw OpenGL scene.
702
drawing_area = gtk_drawing_area_new ();
703
gtk_widget_set_size_request (drawing_area, DEFAULT_WIDTH, DEFAULT_HEIGHT);
705
/* Set OpenGL-capability to the widget */
706
gtk_widget_set_gl_capability (drawing_area,
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);
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);
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);
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);
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);
745
gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
747
gtk_widget_show (drawing_area);
753
menu = create_popup_menu (drawing_area);
755
g_signal_connect_swapped (G_OBJECT (drawing_area), "button_press_event",
756
G_CALLBACK (button_press_event_popup_menu), menu);
759
* Simple quit button.
762
button = gtk_button_new_with_label ("Quit");
764
g_signal_connect (G_OBJECT (button), "clicked",
765
G_CALLBACK (gtk_main_quit), NULL);
767
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
769
gtk_widget_show (button);
775
/**************************************************************************
776
* The following section contains utility function definitions.
777
**************************************************************************/
780
*** Configure the OpenGL framebuffer.
785
GdkGLConfig *glconfig;
787
/* Try double-buffered visual */
788
glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
791
if (glconfig == NULL)
793
g_print ("\n*** Cannot find the double-buffered visual.\n");
794
g_print ("\n*** Trying single-buffered visual.\n");
796
/* Try single-buffered visual */
797
glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
799
if (glconfig == NULL)
801
g_print ("*** No appropriate OpenGL-capable visual found.\n");
810
/**************************************************************************
811
* The main function is rather trivial.
812
**************************************************************************/
819
GdkGLConfig *glconfig;
821
/* Initialize GTK. */
822
gtk_init (&argc, &argv);
824
/* Initialize GtkGLExt. */
825
gtk_gl_init (&argc, &argv);
827
/* Configure OpenGL framebuffer. */
828
glconfig = configure_gl ();
830
/* Create and show the application window. */
831
window = create_window (glconfig);
832
gtk_widget_show (window);
840
/**************************************************************************
842
**************************************************************************/