Of course GL is no fun unless you can draw your own graphics. This is done with a subclass that you create:
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Hor_Slider.H>
#include <FL/math.h>
#include <FL/gl.h>
#include <FL/Fl_Gl_Window.H>
class shape_window : public Fl_Gl_Window {
void draw();
public:
int sides;
shape_window(int x,int y,int w,int h,const char *l=0);
};
shape_window::shape_window(int x,int y,int w,int h,const char *l) :
Fl_Gl_Window(x,y,w,h,l) {
sides = 3;
}
void shape_window::draw() {
// the valid() property may be used to avoid reinitializing your
// GL transformation for each redraw:
if (!valid()) {
valid(1);
glLoadIdentity();
glViewport(0,0,w(),h());
}
// draw an amazing graphic:
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(.5,.6,.7);
glBegin(GL_POLYGON);
for (int i=0; i<sides; i++) {
double ang = i*2*M_PI/sides;
glVertex3f(cos(ang),sin(ang),0);
}
glEnd();
}
// when you change the data, as in this callback, you must call redraw():
void sides_cb(Fl_Widget *o, void *p) {
shape_window *sw = (shape_window *)p;
sw->sides = int(((Fl_Slider *)o)->value());
sw->redraw();
}
int main(int argc, char **argv) {
Fl_Window window(300, 330);
shape_window sw(10, 10, 280, 280);
window.resizable(&sw);
Fl_Hor_Slider slider(50, 295, window.w()-60, 30, "Sides:");
slider.align(FL_ALIGN_LEFT);
slider.callback(sides_cb,&sw);
slider.value(sw.sides);
slider.step(1);
slider.bounds(3,40);
window.show(argc,argv);
sw.show();
return Fl::run();
}
To do your own drawing, you must subclass Fl_Gl_Window. The virtual method draw() is called when the window should update. You can only draw into the window inside a draw() method. You call the method redraw() on the window to indicate that draw() needs to be called. It won't actually be called until Fl::wait() is called.
One evil part of X is that you have to know a lot about how you are going to draw before you can create the window. I tried to hide this as much as possible, but you still need to use the correct base class for your window. This is why there is a Fl_Gl_Window class at all. The unmodified Fl_Gl_Window class provides an RGB buffer with a Z buffer and double buffering, to add or remove from these capabilites you must set the mode() property.
If you want to use X to draw (not as interesting, but portable to non-GL machines) you should subclass the basic Fl_Window. To draw in it, include <FL/x.H>, which will provide you with access to the current X display, gc, colormap, etc.
The window may be made a child of another window, as it is here. This is done by add()ing it to a parent before you show() it. If you don't want to make a child window, be sure to end() the previous window! The Fl_Gl_Window constructor automatically does end() so you don't accidentally add children to it. You must do show() on the child window immediately after doing show() on the parent.
The files <FL/math.h> and <FL/gl.h> are wrappers for the normal header files. You should use them to port to Windoze because the header files there have errors or ommisions in them.