|
将gtkglext安装在默认的路径,即/usr/local。
请教如何编译自已的opengl程序。如:
[code:1]
/*
* 3-D gear wheels. This program is in the public domain.
*
* Brian Paul
*/
/* Conversion to GLUT by Mark J. Kilgard */
/* Conversion to GtkGLExt by Naofumi Yasufuku */
#include <stdlib.h>
#include <math.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkgl.h>
#ifdef G_OS_WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>
/*
* Draw a gear wheel. You'll probably want to call this function when
* building a display list since we do a lot of trig here.
*
* Input: inner_radius - radius of hole at center
* outer_radius - radius at center of teeth
* width - width of gear
* teeth - number of teeth
* tooth_depth - depth of tooth
*/
static void
gear(GLfloat inner_radius,
GLfloat outer_radius,
GLfloat width,
GLint teeth,
GLfloat tooth_depth)
{
GLint i;
GLfloat r0, r1, r2;
GLfloat angle, da;
GLfloat u, v, len;
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * G_PI / teeth / 4.0;
glShadeModel(GL_FLAT);
glNormal3f(0.0, 0.0, 1.0);
/* draw front face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * G_PI / teeth;
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
if (i < teeth) {
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
}
glEnd();
/* draw front sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * G_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * G_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
glEnd();
glNormal3f(0.0, 0.0, -1.0);
/* draw back face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * G_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
if (i < teeth) {
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
}
}
glEnd();
/* draw back sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * G_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * G_PI / teeth;
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
}
glEnd();
/* draw outward faces of teeth */
glBegin(GL_QUAD_STRIP);
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * G_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
u = r2 * cos(angle + da) - r1 * cos(angle);
v = r2 * sin(angle + da) - r1 * sin(angle);
len = sqrt(u * u + v * v);
u /= len;
v /= len;
glNormal3f(v, -u, 0.0);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
glNormal3f(v, -u, 0.0);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
}
glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
glEnd();
glShadeModel(GL_SMOOTH);
/* draw inside radius cylinder */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * G_PI / teeth;
glNormal3f(-cos(angle), -sin(angle), 0.0);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
}
glEnd();
}
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
static GLint gear1, gear2, gear3;
static GLfloat angle = 0.0;
static GTimer *timer = NULL;
static gint frames = 0;
static gboolean
draw (GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return FALSE;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix ();
glRotatef (view_rotx, 1.0, 0.0, 0.0);
glRotatef (view_roty, 0.0, 1.0, 0.0);
glRotatef (view_rotz, 0.0, 0.0, 1.0);
glPushMatrix ();
glTranslatef (-3.0, -2.0, 0.0);
glRotatef (angle, 0.0, 0.0, 1.0);
glCallList (gear1);
glPopMatrix ();
glPushMatrix ();
glTranslatef (3.1, -2.0, 0.0);
glRotatef (-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
glCallList (gear2);
glPopMatrix ();
glPushMatrix ();
glTranslatef (-3.1, 4.2, 0.0);
glRotatef (-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
glCallList (gear3);
glPopMatrix ();
glPopMatrix ();
if (gdk_gl_drawable_is_double_buffered (gldrawable))
gdk_gl_drawable_swap_buffers (gldrawable);
else
glFlush ();
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
frames++;
{
gdouble seconds = g_timer_elapsed (timer, NULL);
if (seconds >= 5.0) {
gdouble fps = frames / seconds;
g_print ("%d frames in %6.3f seconds = %6.3f FPS\n", frames, seconds, fps);
g_timer_reset (timer);
frames = 0;
}
}
return TRUE;
}
/* new window size or exposure */
static gboolean
reshape (GtkWidget *widget,
GdkEventConfigure *event,
gpointer data)
{
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
GLfloat h = (GLfloat) (widget->allocation.height) / (GLfloat) (widget->allocation.width);
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return FALSE;
glViewport (0, 0, widget->allocation.width, widget->allocation.height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (0.0, 0.0, -40.0);
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
return TRUE;
}
static void
init(GtkWidget *widget,
gpointer data)
{
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return;
glLightfv (GL_LIGHT0, GL_POSITION, pos);
glEnable (GL_CULL_FACE);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_DEPTH_TEST);
/* make the gears */
gear1 = glGenLists (1);
glNewList (gear1, GL_COMPILE);
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
gear (1.0, 4.0, 1.0, 20, 0.7);
glEndList ();
gear2 = glGenLists (1);
glNewList (gear2, GL_COMPILE);
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gear (0.5, 2.0, 2.0, 10, 0.7);
glEndList ();
gear3 = glGenLists (1);
glNewList (gear3, GL_COMPILE);
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
gear (1.3, 2.0, 0.5, 10, 0.7);
glEndList ();
glEnable (GL_NORMALIZE);
g_print ("\n");
g_print ("GL_RENDERER = %s\n", (char *) glGetString (GL_RENDERER));
g_print ("GL_VERSION = %s\n", (char *) glGetString (GL_VERSION));
g_print ("GL_VENDOR = %s\n", (char *) glGetString (GL_VENDOR));
g_print ("GL_EXTENSIONS = %s\n", (char *) glGetString (GL_EXTENSIONS));
g_print ("\n");
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
/* create timer */
if (timer == NULL)
timer = g_timer_new ();
g_timer_start (timer);
}
static gboolean
idle (GtkWidget *widget)
{
angle += 2.0;
gtk_widget_queue_draw (widget);
return TRUE;
}
static guint idle_id = 0;
static void
idle_add (GtkWidget *widget)
{
if (idle_id == 0)
{
idle_id = gtk_idle_add_priority (GDK_PRIORITY_REDRAW,
(GtkFunction) idle,
widget);
}
}
static void
idle_remove (GtkWidget *widget)
{
if (idle_id != 0)
{
gtk_idle_remove (idle_id);
idle_id = 0;
}
}
static gboolean
map (GtkWidget *widget,
GdkEventAny *event,
gpointer data)
{
idle_add (widget);
return TRUE;
}
static gboolean
unmap (GtkWidget *widget,
GdkEventAny *event,
gpointer data)
{
idle_remove (widget);
return TRUE;
}
static gboolean
visible (GtkWidget *widget,
GdkEventVisibility *event,
gpointer data)
{
if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
idle_remove (widget);
else
idle_add (widget);
return TRUE;
}
/* change view angle, exit upon ESC */
static gboolean
key (GtkWidget *widget,
GdkEventKey *event,
gpointer data)
{
switch (event->keyval)
{
case GDK_z:
view_rotz += 5.0;
break;
case GDK_Z:
view_rotz -= 5.0;
break;
case GDK_Up:
view_rotx += 5.0;
break;
case GDK_Down:
view_rotx -= 5.0;
break;
case GDK_Left:
view_roty += 5.0;
break;
case GDK_Right:
view_roty -= 5.0;
break;
case GDK_Escape:
gtk_main_quit ();
break;
default:
return FALSE;
}
gtk_widget_queue_draw (widget);
return TRUE;
}
int
main (int argc,
char *argv[])
{
GdkGLConfig *glconfig;
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *drawing_area;
GtkWidget *button;
/*
* Init GTK.
*/
gtk_init (&argc, &argv);
/*
* Init GtkGLExt.
*/
gtk_gl_init (&argc, &argv);
/*
* Configure OpenGL-capable visual.
*/
/* Try double-buffered visual */
glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
GDK_GL_MODE_DEPTH |
GDK_GL_MODE_DOUBLE);
if (glconfig == NULL)
{
g_print ("*** Cannot find the double-buffered visual.\n");
g_print ("*** Trying single-buffered visual.\n");
/* Try single-buffered visual */
glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
GDK_GL_MODE_DEPTH);
if (glconfig == NULL)
{
g_print ("*** No appropriate OpenGL-capable visual found.\n");
exit (1);
}
}
/*
* Top-level window.
*/
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "gears");
#ifndef G_OS_WIN32
/* Perform the resizes immediately */
gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_IMMEDIATE);
#endif
/* Get automatically redrawn if any of their children changed allocation. */
gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK (gtk_main_quit), NULL);
/*
* VBox.
*/
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show (vbox);
/*
* Drawing area for drawing OpenGL scene.
*/
drawing_area = gtk_drawing_area_new ();
gtk_widget_set_size_request (drawing_area, 300, 300);
/* Set OpenGL-capability to the widget. */
gtk_widget_set_gl_capability (drawing_area,
glconfig,
NULL,
TRUE,
GDK_GL_RGBA_TYPE);
gtk_widget_add_events (drawing_area,
GDK_VISIBILITY_NOTIFY_MASK);
g_signal_connect_after (G_OBJECT (drawing_area), "realize",
G_CALLBACK (init), NULL);
g_signal_connect (G_OBJECT (drawing_area), "configure_event",
G_CALLBACK (reshape), NULL);
g_signal_connect (G_OBJECT (drawing_area), "expose_event",
G_CALLBACK (draw), NULL);
g_signal_connect (G_OBJECT (drawing_area), "map_event",
G_CALLBACK (map), NULL);
g_signal_connect (G_OBJECT (drawing_area), "unmap_event",
G_CALLBACK (unmap), NULL);
g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event",
G_CALLBACK (visible), NULL);
g_signal_connect_swapped (G_OBJECT (window), "key_press_event",
G_CALLBACK (key), drawing_area);
gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
gtk_widget_show (drawing_area);
/*
* Simple quit button.
*/
button = gtk_button_new_with_label ("Quit");
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (gtk_main_quit), NULL);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
/*
* Show window.
*/
gtk_widget_show (window);
/*
* Main loop.
*/
gtk_main ();
return 0;
}
[/code:1] |
|