2
* 3-D gear wheels. This program is in the public domain.
7
/* Conversion to GLUT by Mark J. Kilgard */
9
/* Conversion to GtkGLExt by Naofumi Yasufuku */
16
#include <gdk/gdkkeysyms.h>
18
#include <gtk/gtkgl.h>
21
#define WIN32_LEAN_AND_MEAN 1
29
* Draw a gear wheel. You'll probably want to call this function when
30
* building a display list since we do a lot of trig here.
32
* Input: inner_radius - radius of hole at center
33
* outer_radius - radius at center of teeth
34
* width - width of gear
35
* teeth - number of teeth
36
* tooth_depth - depth of tooth
40
gear(GLfloat inner_radius,
52
r1 = outer_radius - tooth_depth / 2.0;
53
r2 = outer_radius + tooth_depth / 2.0;
55
da = 2.0 * G_PI / teeth / 4.0;
57
glShadeModel(GL_FLAT);
59
glNormal3f(0.0, 0.0, 1.0);
62
glBegin(GL_QUAD_STRIP);
63
for (i = 0; i <= teeth; i++) {
64
angle = i * 2.0 * G_PI / teeth;
65
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
66
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
68
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
69
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
74
/* draw front sides of teeth */
76
da = 2.0 * G_PI / teeth / 4.0;
77
for (i = 0; i < teeth; i++) {
78
angle = i * 2.0 * G_PI / teeth;
80
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
81
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
82
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
83
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
87
glNormal3f(0.0, 0.0, -1.0);
90
glBegin(GL_QUAD_STRIP);
91
for (i = 0; i <= teeth; i++) {
92
angle = i * 2.0 * G_PI / teeth;
93
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
94
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
96
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
97
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
102
/* draw back sides of teeth */
104
da = 2.0 * G_PI / teeth / 4.0;
105
for (i = 0; i < teeth; i++) {
106
angle = i * 2.0 * G_PI / teeth;
108
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
109
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
110
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
111
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
115
/* draw outward faces of teeth */
116
glBegin(GL_QUAD_STRIP);
117
for (i = 0; i < teeth; i++) {
118
angle = i * 2.0 * G_PI / teeth;
120
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
121
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
122
u = r2 * cos(angle + da) - r1 * cos(angle);
123
v = r2 * sin(angle + da) - r1 * sin(angle);
124
len = sqrt(u * u + v * v);
127
glNormal3f(v, -u, 0.0);
128
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
129
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
130
glNormal3f(cos(angle), sin(angle), 0.0);
131
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
132
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
133
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
134
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
135
glNormal3f(v, -u, 0.0);
136
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
137
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
138
glNormal3f(cos(angle), sin(angle), 0.0);
141
glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
142
glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
146
glShadeModel(GL_SMOOTH);
148
/* draw inside radius cylinder */
149
glBegin(GL_QUAD_STRIP);
150
for (i = 0; i <= teeth; i++) {
151
angle = i * 2.0 * G_PI / teeth;
152
glNormal3f(-cos(angle), -sin(angle), 0.0);
153
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
154
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
160
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
161
static GLint gear1, gear2, gear3;
162
static GLfloat angle = 0.0;
164
static GTimer *timer = NULL;
165
static gint frames = 0;
167
static gboolean is_sync = TRUE;
170
draw (GtkWidget *widget,
171
GdkEventExpose *event,
174
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
175
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
177
/*** OpenGL BEGIN ***/
178
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
181
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
184
glRotatef (view_rotx, 1.0, 0.0, 0.0);
185
glRotatef (view_roty, 0.0, 1.0, 0.0);
186
glRotatef (view_rotz, 0.0, 0.0, 1.0);
189
glTranslatef (-3.0, -2.0, 0.0);
190
glRotatef (angle, 0.0, 0.0, 1.0);
195
glTranslatef (3.1, -2.0, 0.0);
196
glRotatef (-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
201
glTranslatef (-3.1, 4.2, 0.0);
202
glRotatef (-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
208
if (gdk_gl_drawable_is_double_buffered (gldrawable))
209
gdk_gl_drawable_swap_buffers (gldrawable);
213
gdk_gl_drawable_gl_end (gldrawable);
219
gdouble seconds = g_timer_elapsed (timer, NULL);
220
if (seconds >= 5.0) {
221
gdouble fps = frames / seconds;
222
g_print ("%d frames in %6.3f seconds = %6.3f FPS\n", frames, seconds, fps);
223
g_timer_reset (timer);
231
/* new window size or exposure */
233
reshape (GtkWidget *widget,
234
GdkEventConfigure *event,
237
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
238
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
240
GLfloat h = (GLfloat) (widget->allocation.height) / (GLfloat) (widget->allocation.width);
242
/*** OpenGL BEGIN ***/
243
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
246
glViewport (0, 0, widget->allocation.width, widget->allocation.height);
247
glMatrixMode (GL_PROJECTION);
249
glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
250
glMatrixMode (GL_MODELVIEW);
252
glTranslatef (0.0, 0.0, -40.0);
254
gdk_gl_drawable_gl_end (gldrawable);
261
init(GtkWidget *widget,
264
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
265
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
267
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
268
static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
269
static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
270
static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
272
/*** OpenGL BEGIN ***/
273
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
276
glLightfv (GL_LIGHT0, GL_POSITION, pos);
277
glEnable (GL_CULL_FACE);
278
glEnable (GL_LIGHTING);
279
glEnable (GL_LIGHT0);
280
glEnable (GL_DEPTH_TEST);
283
gear1 = glGenLists (1);
284
glNewList (gear1, GL_COMPILE);
285
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
286
gear (1.0, 4.0, 1.0, 20, 0.7);
289
gear2 = glGenLists (1);
290
glNewList (gear2, GL_COMPILE);
291
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
292
gear (0.5, 2.0, 2.0, 10, 0.7);
295
gear3 = glGenLists (1);
296
glNewList (gear3, GL_COMPILE);
297
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
298
gear (1.3, 2.0, 0.5, 10, 0.7);
301
glEnable (GL_NORMALIZE);
304
g_print ("GL_RENDERER = %s\n", (char *) glGetString (GL_RENDERER));
305
g_print ("GL_VERSION = %s\n", (char *) glGetString (GL_VERSION));
306
g_print ("GL_VENDOR = %s\n", (char *) glGetString (GL_VENDOR));
307
g_print ("GL_EXTENSIONS = %s\n", (char *) glGetString (GL_EXTENSIONS));
310
gdk_gl_drawable_gl_end (gldrawable);
315
timer = g_timer_new ();
317
g_timer_start (timer);
321
idle (GtkWidget *widget)
325
/* Invalidate the whole window. */
326
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
328
/* Update synchronously (fast). */
330
gdk_window_process_updates (widget->window, FALSE);
335
static guint idle_id = 0;
338
idle_add (GtkWidget *widget)
342
idle_id = g_idle_add_full (GDK_PRIORITY_REDRAW,
350
idle_remove (GtkWidget *widget)
354
g_source_remove (idle_id);
360
map (GtkWidget *widget,
370
unmap (GtkWidget *widget,
374
idle_remove (widget);
380
visible (GtkWidget *widget,
381
GdkEventVisibility *event,
384
if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
385
idle_remove (widget);
392
/* change view angle, exit upon ESC */
394
key (GtkWidget *widget,
398
switch (event->keyval)
425
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
434
GdkGLConfig *glconfig;
437
GtkWidget *drawing_area;
445
gtk_init (&argc, &argv);
451
gtk_gl_init (&argc, &argv);
454
* Command line options.
457
for (i = 0; i < argc; i++)
459
if (strcmp (argv[i], "--async") == 0)
464
* Configure OpenGL-capable visual.
467
/* Try double-buffered visual */
468
glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
471
if (glconfig == NULL)
473
g_print ("*** Cannot find the double-buffered visual.\n");
474
g_print ("*** Trying single-buffered visual.\n");
476
/* Try single-buffered visual */
477
glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
479
if (glconfig == NULL)
481
g_print ("*** No appropriate OpenGL-capable visual found.\n");
490
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
491
gtk_window_set_title (GTK_WINDOW (window), "gears");
493
/* Get automatically redrawn if any of their children changed allocation. */
494
gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
496
g_signal_connect (G_OBJECT (window), "delete_event",
497
G_CALLBACK (gtk_main_quit), NULL);
503
vbox = gtk_vbox_new (FALSE, 0);
504
gtk_container_add (GTK_CONTAINER (window), vbox);
505
gtk_widget_show (vbox);
508
* Drawing area for drawing OpenGL scene.
511
drawing_area = gtk_drawing_area_new ();
512
gtk_widget_set_size_request (drawing_area, 300, 300);
514
/* Set OpenGL-capability to the widget. */
515
gtk_widget_set_gl_capability (drawing_area,
521
gtk_widget_add_events (drawing_area,
522
GDK_VISIBILITY_NOTIFY_MASK);
524
g_signal_connect_after (G_OBJECT (drawing_area), "realize",
525
G_CALLBACK (init), NULL);
526
g_signal_connect (G_OBJECT (drawing_area), "configure_event",
527
G_CALLBACK (reshape), NULL);
528
g_signal_connect (G_OBJECT (drawing_area), "expose_event",
529
G_CALLBACK (draw), NULL);
530
g_signal_connect (G_OBJECT (drawing_area), "map_event",
531
G_CALLBACK (map), NULL);
532
g_signal_connect (G_OBJECT (drawing_area), "unmap_event",
533
G_CALLBACK (unmap), NULL);
534
g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event",
535
G_CALLBACK (visible), NULL);
537
g_signal_connect_swapped (G_OBJECT (window), "key_press_event",
538
G_CALLBACK (key), drawing_area);
540
gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
542
gtk_widget_show (drawing_area);
545
* Simple quit button.
548
button = gtk_button_new_with_label ("Quit");
550
g_signal_connect (G_OBJECT (button), "clicked",
551
G_CALLBACK (gtk_main_quit), NULL);
553
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
555
gtk_widget_show (button);
561
gtk_widget_show (window);