Gtkglext ?

Can someone help me to compile gtkglext example.
I install Gtkglext under RH linux8 for default path.(Just configure & make & make install without any options).
The examples given there are alredy compiled using “make examples”. But I want to compile just a one example(eg: rotating-square.c ). So can any one help me to compile this or just send me an Makefile to compile this.
thanks

 /**************************************************************************
 * rotatingSquare.c
 *
 * Copyright (c) 2002 Alif Wahid <awah005@users.sourceforge.net>
 *
 * A simple animation to demonstrate GtkGLExt.
 *
 * This program is in the public domain and you are using it at
 * your own risk.
 *
 **************************************************************************/

/* 
 * Modified by Naofumi Yasufuku  <naofumi@users.sourceforge.net>
 */

/**************************************************************************
 * Header file inclusions.
 **************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include <gtk/gtkgl.h>
/*** Use OpenGL extensions. ***/
/* #include <gdk/gdkglglext.h> */

#ifdef G_OS_WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glu.h>


/**************************************************************************
 * The following section contains all the macro definitions.
 **************************************************************************/

#define DEFAULT_WIDTH  200
#define DEFAULT_HEIGHT 200
#define DEFAULT_TITLE  "Rotating Square"


/**************************************************************************
 * Global variable declarations.
 **************************************************************************/

static gboolean animate = TRUE;

static float spin = 0.0;


/**************************************************************************
 * The following section contains the function prototype declarations.
 **************************************************************************/

static void         idle_add          (GtkWidget   *widget);
static void         idle_remove       (GtkWidget   *widget);

static void         toggle_animation  (GtkWidget   *widget);

static GdkGLConfig *configure_gl      (void);

static GtkWidget   *create_popup_menu (GtkWidget   *drawing_area);
static GtkWidget   *create_window     (GdkGLConfig *glconfig);


/**************************************************************************
 * The following section contains all the callback function definitions.
 **************************************************************************/

/***
 *** The "realize" signal handler. All the OpenGL initialization
 *** should be performed here, such as default background colour,
 *** certain states etc.
 ***/
static void
realize (GtkWidget *widget,
	 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;

  glClearColor (0.0, 0.0, 0.0, 0.0);
  glShadeModel (GL_FLAT);

  gdk_gl_drawable_gl_end (gldrawable);
  /*** OpenGL END ***/

  return;
}

/***
 *** The "configure_event" signal handler. Any processing required when
 *** the OpenGL-capable drawing area is re-configured should be done here.
 *** Almost always it will be used to resize the OpenGL viewport when
 *** the window is resized.
 ***/
static gboolean
configure_event (GtkWidget         *widget,
		 GdkEventConfigure *event,
		 gpointer           data)
{
  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);

  GLfloat w = widget->allocation.width;
  GLfloat h = widget->allocation.height;

  /*** OpenGL BEGIN ***/
  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
    return FALSE;

  glViewport (0, 0, (GLsizei) w, (GLsizei) h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  glOrtho (-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity ();

  gdk_gl_drawable_gl_end (gldrawable);
  /*** OpenGL END ***/

  return TRUE;
}

/***
 *** The "expose_event" signal handler. All the OpenGL re-drawing should
 *** be done here. This is repeatedly called as the painting routine
 *** every time the 'expose'/'draw' event is signalled.
 ***/
static gboolean
expose_event (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);

  glPushMatrix ();
    glRotatef (spin, 0.0, 0.0, 1.0);
    glColor3f (1.0, 1.0, 1.0);
    glRectf (-25.0, -25.0, 25.0, 25.0);
  glPopMatrix ();

  /* Swap buffers */
  if (gdk_gl_drawable_is_double_buffered (gldrawable))
    gdk_gl_drawable_swap_buffers (gldrawable);
  else
    glFlush ();

  gdk_gl_drawable_gl_end (gldrawable);
  /*** OpenGL END ***/

  return TRUE;
}

/***
 *** The idle function. Often in animations,
 *** idle functions are suitable for continous
 *** frame updates.
 ***/
static gboolean
idle (GtkWidget *widget)
{
  spin += 2.0;
  if (spin > 360.0) spin -= 360.0;

  /* Invalidate the whole window. */
  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);

  /* Update synchronously. */
  gdk_window_process_updates (widget->window, FALSE);

  return TRUE;
}

/***
 *** The "motion_notify_event" signal handler. Any processing required when
 *** the OpenGL-capable drawing area is under drag motion should be done here.
 ***/
static gboolean
motion_notify_event (GtkWidget      *widget,
		     GdkEventMotion *event,
		     gpointer        data)
{

  /*** Fill in the details here. ***/

  return FALSE;
}

/***
 *** The "button_press_event" signal handler. Any processing required when
 *** mouse buttons (only left and middle buttons) are pressed on the OpenGL-
 *** capable drawing area should be done here.
 ***/
static gboolean
button_press_event (GtkWidget      *widget,
		    GdkEventButton *event,
		    gpointer        data)
{
  /* Starts/Stops animation according mouse button clicks.*/
  if (event->button == 1)
    {
      toggle_animation (widget);
      return TRUE;
    }

  return FALSE;
}

/* For popup menu. */
static gboolean
button_press_event_popup_menu (GtkWidget      *widget,
			       GdkEventButton *event,
			       gpointer        data)
{
  if (event->button == 3)
    {
      /* Popup menu. */
      gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
		      event->button, event->time);
      return TRUE;
    }

  return FALSE;
}

/***
 *** The "key_press_event" signal handler. Any processing required when key
 *** presses occur should be done here.
 ***/
static gboolean
key_press_event (GtkWidget   *widget,
		 GdkEventKey *event,
		 gpointer     data)
{
  switch (event->keyval)
    {
    case GDK_Left:
      /* Rotate left. */
      if (!animate)
	{
	  spin += 2.0;
	  if (spin > 360.0) spin -= 360.0;
	  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
	}
      break;

    case GDK_Right:
      /* Rotate right. */
      if (!animate)
	{
	  spin -= 2.0;
	  if (spin < 360.0) spin += 360.0;
	  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
	}
      break;

    case GDK_a:
      /* Toggle animation. */
      toggle_animation (widget);
      break;

    case GDK_Escape:
      /* Quit. */
      gtk_main_quit ();
      break;

    default:
      return FALSE;
    }

  return TRUE;
}

/***
 *** The "unrealize" signal handler. Any processing required when
 *** the OpenGL-capable window is unrealized should be done here.
 ***/
static void
unrealize (GtkWidget *widget,
	   gpointer   data)
{

  /*** Fill in the details here ***/

}


/**************************************************************************
 * The following section contains the idle function management routines.
 **************************************************************************/

/***
 *** Helper functions to add or remove the idle function.
 ***/

static guint idle_id = 0;

static void
idle_add (GtkWidget *widget)
{
  if (idle_id == 0)
    {
      idle_id = g_idle_add_full (GDK_PRIORITY_REDRAW,
                                 (GSourceFunc) idle,
                                 widget,
                                 NULL);
    }
}

static void
idle_remove (GtkWidget *widget)
{
  if (idle_id != 0)
    {
      g_source_remove (idle_id);
      idle_id = 0;
    }
}

/***
 *** The "map_event" signal handler. Any processing required when the
 *** OpenGL-capable drawing area is mapped should be done here.
 ***/
static gboolean
map_event (GtkWidget *widget,
	   GdkEvent  *event,
	   gpointer   data)
{
  if (animate)
    idle_add (widget);

  return TRUE;
}

/***
 *** The "unmap_event" signal handler. Any processing required when the
 *** OpenGL-capable drawing area is unmapped should be done here.
 ***/
static gboolean
unmap_event (GtkWidget *widget,
	     GdkEvent  *event,
	     gpointer   data)
{
  idle_remove (widget);

  return TRUE;
}

/***
 *** The "visibility_notify_event" signal handler. Any processing required
 *** when the OpenGL-capable drawing area is visually obscured should be
 *** done here.
 ***/
static gboolean
visibility_notify_event (GtkWidget          *widget,
			 GdkEventVisibility *event,
			 gpointer            data)
{
  if (animate)
    {
      if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
	idle_remove (widget);
      else
	idle_add (widget);
    }

  return TRUE;
}


/**************************************************************************
 * The following section contains some miscellaneous utility functions.
 **************************************************************************/

/***
 *** Toggle animation.
 ***/
static void
toggle_animation (GtkWidget *widget)
{
  animate = !animate;

  if (animate)
    {
      idle_add (widget);
    }
  else
    {
      idle_remove (widget);
      gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
    }
}


/**************************************************************************
 * The following section contains the GUI building function definitions.
 **************************************************************************/

/***
 *** Creates the popup menu to be displayed.
 ***/
static GtkWidget *
create_popup_menu (GtkWidget *drawing_area)
{
  GtkWidget *menu;
  GtkWidget *menu_item;

  menu = gtk_menu_new ();

  /* Toggle animation */
  menu_item = gtk_menu_item_new_with_label ("Toggle Animation");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
  g_signal_connect_swapped (G_OBJECT (menu_item), "activate",
			    G_CALLBACK (toggle_animation), drawing_area);
  gtk_widget_show (menu_item);

  /* Quit */
  menu_item = gtk_menu_item_new_with_label ("Quit");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
  g_signal_connect (G_OBJECT (menu_item), "activate",
		    G_CALLBACK (gtk_main_quit), NULL);
  gtk_widget_show (menu_item);
	
  return menu;
}

/***
 *** Creates the simple application window with one
 *** drawing area that has an OpenGL-capable visual.
 ***/
static GtkWidget *
create_window (GdkGLConfig *glconfig)
{
  GtkWidget *window;
  GtkWidget *vbox;
  GtkWidget *drawing_area;
  GtkWidget *menu;
  GtkWidget *button;

  /*
   * Top-level window.
   */

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), DEFAULT_TITLE);

  /* Get automatically redrawn if any of their children changed allocation. */
  gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);

  /* Connect signal handlers to the window */
  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 to draw OpenGL scene.
   */

  drawing_area = gtk_drawing_area_new ();
  gtk_widget_set_size_request (drawing_area, DEFAULT_WIDTH, DEFAULT_HEIGHT);

  /* 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_BUTTON1_MOTION_MASK    |
			 GDK_BUTTON2_MOTION_MASK    |
			 GDK_BUTTON_PRESS_MASK      |
			 GDK_VISIBILITY_NOTIFY_MASK);

  /* Connect signal handlers to the drawing area */
  g_signal_connect_after (G_OBJECT (drawing_area), "realize",
                          G_CALLBACK (realize), NULL);
  g_signal_connect (G_OBJECT (drawing_area), "configure_event",
		    G_CALLBACK (configure_event), NULL);
  g_signal_connect (G_OBJECT (drawing_area), "expose_event",
		    G_CALLBACK (expose_event), NULL);

  g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
		    G_CALLBACK (motion_notify_event), NULL);
  g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
		    G_CALLBACK (button_press_event), NULL);
  g_signal_connect (G_OBJECT (drawing_area), "unrealize",
		    G_CALLBACK (unrealize), NULL);

  /* key_press_event handler for top-level window */
  g_signal_connect_swapped (G_OBJECT (window), "key_press_event",
			    G_CALLBACK (key_press_event), drawing_area);

  /* For idle function. */
  g_signal_connect (G_OBJECT (drawing_area), "map_event",
		    G_CALLBACK (map_event), NULL);
  g_signal_connect (G_OBJECT (drawing_area), "unmap_event",
		    G_CALLBACK (unmap_event), NULL);
  g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event",
		    G_CALLBACK (visibility_notify_event), NULL);

  gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);

  gtk_widget_show (drawing_area);

  /*
   * Popup menu.
   */

  menu = create_popup_menu (drawing_area);

  g_signal_connect_swapped (G_OBJECT (drawing_area), "button_press_event",
			    G_CALLBACK (button_press_event_popup_menu), menu);

  /*
   * 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);

  return window;
}


/**************************************************************************
 * The following section contains utility function definitions.
 **************************************************************************/

/***
 *** Configure the OpenGL framebuffer.
 ***/
static GdkGLConfig *
configure_gl (void)
{
  GdkGLConfig *glconfig;

  /* 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.
");
      g_print ("
*** Trying single-buffered visual.
");

      /* 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.
");
	  exit (1);
	}
    }

  return glconfig;
}


/**************************************************************************
 * The main function is rather trivial.
 **************************************************************************/

int
main (int   argc,
      char *argv[])
{
  GtkWidget *window;
  GdkGLConfig *glconfig;

  /* Initialize GTK. */
  gtk_init (&argc, &argv);

  /* Initialize GtkGLExt. */
  gtk_gl_init (&argc, &argv);

  /* Configure OpenGL framebuffer. */
  glconfig = configure_gl ();

  /* Create and show the application window. */
  window = create_window (glconfig);
  gtk_widget_show (window);

  gtk_main ();

  return 0;
}


/**************************************************************************
 * End of file.
 **************************************************************************/
 

I haven’t worked with GtkGlext at all yet, so I can’t tell you specifically. I can tell you some tricks to help you try and figure it out yourself, though…

You can start off with a simple command line like:

gcc -o gtktest gtktest.c

Take a look at what the first error is… if the first error says that there was a .h file not found, find out where that .h file is by using:

locate somefile.h

(Note: You may have to run updatedb as root before locate will work.)

Take for instance the program you posted: When I put that into gtktest.c and run

gcc -o gtktest gtktest.c

I get the following for my first error:

gtktest.c:25:21: gtk/gtk.h: No such file or directory
gtktest.c:26:28: gdk/gdkkeysyms.h: No such file or directory
gtktest.c:28:23: gtk/gtkgl.h: No such file or directory

So… I do the following:

$locate gtk/gtk.h
/usr/share/gtk-doc/html/gtk/gtk.html
/usr/include/gtk-1.2/gtk/gtk.h
/usr/include/gtk-2.0/gtk/gtk.h

$locate gdk/gdkkeysyms.h
/usr/include/gtk-1.2/gdk/gdkkeysyms.h
/usr/include/gtk-2.0/gdk/gdkkeysyms.h

$locate gtk/gtkgl.h

(Nothing, I don't have that installed, right now.)

You’ll notice that both the gtk directories and gdk directories are under /usr/include/gtk-2.0. So if that were part of the include path, both #include <gtk/gtk.h> and #include <gdk/gdkkeysyms.h> would probably work…

So… add -I/usr/include/gtk-2.0 to your command line, and see what new errors you get…

gcc -o gtktest gtktest.c -I/usr/include/gtk-2.0

Since I don’t have gtkgl.h installed yet, I can’t walk you through anymore specific examples like that, but I’ll try and give you some other ideas of what you might try for linker errors, if you get it that far.

If you get a linker error saying something like “undefined reference to blahblahblah”, you can try and find what library that function is in by doing something like:

grep blahblahblah /usr/lib/*

If you get a response back it will probably be in the general form:

libLibName.so.x.x

So now you know you need to add a library to your command line like so:

-lLibName (Note you drop the lib part of the name and everything from the first . on…)

You might run into libraries that you need that are not in /usr/lib… like possibly /usr/X11R6/lib… in that case, you may need to add that path to the library search path, but adding:

-L/usr/X11R6/lib

Take for instance if you got an undefined reference to XOpenDevice (That’s a common one people run into)… check wht library that is in like so:

$ grep XOpenDevice /usr/X11R6/lib/*
Binary file /usr/X11R6/lib/libXi.a matches
Binary file /usr/X11R6/lib/libXi.so matches
Binary file /usr/X11R6/lib/libXi.so.6 matches
Binary file /usr/X11R6/lib/libXi.so.6.0 matches

Notice it is in libXi… so I would add -lXi, and since it was found in /usr/XllR6/lib, I would also add -L/usr/X11R6/lib…

Anyway… hope that helps you get started. If I get bored, I may install the gtkglext stuff to play with and try and get that to compile for you. I’ve been meaning to look at GTK+ and how to use OpenGL with it sometime, anyway. :slight_smile:

I got your example to compile by using the following Makefile:

CFLAGS=-I/usr/include/gtk-2.0 -I/usr/local/include/gtkglext-1.0 \
       -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include \
       -I/usr/include/pango-1.0 -I/usr/lib/gtk-2.0/include \
       -I/usr/local/lib/gtkglext-1.0/include -I/usr/include/atk-1.0 \
       -Wall
LDFLAGS=-L/usr/X11R6/lib -lgtk -lgdk -lGL -lGLU \
        -lgdkglext-x11-1.0 -lgtkglext-x11-1.0

gtktest: gtktest.c
    g++ -o $@ $< ${CFLAGS} ${LDFLAGS}

Notice that I have many, many extra include directories because none of the headers needed were in my default include path… Your paths may differ.

And I also had to change the source code for one of the functions to this: (I added the casting for the 2 calls to gdk_gl_config_new_by_mode

static GdkGLConfig *
configure_gl (void)
{
  GdkGLConfig *glconfig;

  /* Try double-buffered visual */
  glconfig = gdk_gl_config_new_by_mode ((GdkGLConfigMode)(GDK_GL_MODE_RGB    |
GDK_GL_MODE_DEPTH  |
GDK_GL_MODE_DOUBLE));
  if (glconfig == NULL)
    {
      g_print ("
*** Cannot find the double-buffered visual.
");
      g_print ("
*** Trying single-buffered visual.
");

      /* Try single-buffered visual */
      glconfig = gdk_gl_config_new_by_mode ((GdkGLConfigMode)(GDK_GL_MODE_RGB
|
    GDK_GL_MODE_DEPTH));
      if (glconfig == NULL)
{
  g_print ("*** No appropriate OpenGL-capable visual found.
");
  exit (1);
}
    }

  return glconfig;
}

Edit:
Thought of a couple of other things to add. The changes I made can probably be skipped if you use the right parameter to disable casting errors, but I didn’t know what that was offhand.

Also, I looked at the examples folder of GtkGlExt, and there is a Makefile in there that you can also use as reference. They setup the CFLAGS much like I did above, with a few additional search paths.

Also, there is a tool for GTK called pkg-config that you can use to help find out what parameters are needed for compiling GTK apps. It’s used something like so:

pkg-config -cflags gtk±2.0

and

pgk-config -libs gtk±2.0