OK, I found my hacked-up gl_gears example - actually it's the glut one,
but anyway... converted to be fltk-ish.
It was originally meant to run on the idle loop, and with this WIN32 box
that runs about 3,000 FPS.
I've added an fl_timer aiming for 100 FPS, and on this box I get a
rock-solid 64 FPS... Hmm, 64 != 100, so that's odd.
I wonder if I'm hitting some issue with the resolution of the WIN32
timers or something, as the FPS I get is *exactly* 64, even though the
idle-loop version runs much, much faster...
Anyway, it is longer and messier than I'd like, sorry.
The conversion to/from using the idle or timer option should be
obvious...
----------------------------
/*
* 3-D gear wheels. This program is in the public domain.
*
* Command line options:
* -info print GL implementation information
* -exit automatically exit after 30 seconds
*
*
* Brian Paul
*/
/* Conversion to GLUT by Mark J. Kilgard */
/*
* Conversion to FLTK by IMM
* Compile as: fltk-config --use-gl --compile fl_gears.cxx
*/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
//#include <GL/glut.h>
#include <FL/glut.H>
#ifdef __APPLE__
# include <OpenGL/glu.h>
#else
# include <GL/glu.h> // added for FLTK
#endif
#include <FL/Fl_Window.H>
#include <FL/Fl_Value_Output.H>
static GLint T0 = 0;
static GLint Frames = 0;
static GLint autoexit = 0;
static Fl_Value_Output *fps_out = NULL;
static Fl_Value_Output *fps_max = NULL;
static Fl_Value_Output *fps_avg = NULL;
static float f_max = 0.0;
static float f_avg = 0.0;
static float desired_frame_rate = 100.0;
static float per_frame_time = 1.0 / desired_frame_rate;
/**
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 * M_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 * M_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 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_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 * M_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 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_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 * M_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 * M_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 void
draw(void)
{
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();
glutSwapBuffers();
Frames++;
}
static void idle_fl(void *)
{
static short fixed_angle = 0;
fixed_angle += 500;
angle = (double)(fixed_angle) * 180.0 / 32768.0;
glutPostRedisplay();
}
void fixed_fps(void *v)
{
Fl::repeat_timeout(per_frame_time, fixed_fps);
idle_fl(v);
}
void check_fps(void *)
{
static int first = 1;
float fps;
static time_t old_tod;
time_t delta_tod, new_tod = time(NULL);
if(first)
{
delta_tod = 5;
}
else
{
delta_tod = new_tod - old_tod;
}
fps = Frames / (float)delta_tod;
printf("%d frames in %d seconds = %6.3f FPS\n", Frames, delta_tod,
fps);
fflush(stdout);
Frames = 0;
if (fps > f_max)
{
f_max = fps;
fps_max->value(floor(f_max));
}
if (first)
{
f_avg = fps;
first = 0;
}
else
{
f_avg = (f_avg * 0.7) + (fps * 0.3);
}
old_tod = new_tod;
fps_avg->value(floor(f_avg));
fps_out->value(floor(fps));
if (autoexit)
{
autoexit = autoexit - (int)delta_tod;
if (autoexit <= 0) exit(0);
}
Fl::repeat_timeout(10.0, check_fps);
}
/* change view angle, exit upon ESC */
/* ARGSUSED1 */
static void
key(unsigned char k, int x, int y)
{
switch (k) {
case 'z':
view_rotz += 5.0;
break;
case 'Z':
view_rotz -= 5.0;
break;
case 27: /* Escape */
exit(0);
break;
default:
return;
}
glutPostRedisplay();
}
/* change view angle */
/* ARGSUSED1 */
static void
special(int k, int x, int y)
{
switch (k) {
case GLUT_KEY_UP:
view_rotx += 5.0;
break;
case GLUT_KEY_DOWN:
view_rotx -= 5.0;
break;
case GLUT_KEY_LEFT:
view_roty += 5.0;
break;
case GLUT_KEY_RIGHT:
view_roty -= 5.0;
break;
default:
return;
}
glutPostRedisplay();
}
/* new window size or exposure */
static void
reshape(int width, int height)
{
GLfloat h = (GLfloat) height / (GLfloat) width;
glViewport(0, 0, (GLint) width, (GLint) 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);
}
static void
init(int argc, char *argv[])
{
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};
GLint i;
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);
for ( i=1; i<argc; i++ ) {
if (strcmp(argv[i], "-info")==0) {
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
printf("GL_EXTENSIONS = %s\n", (char *)
glGetString(GL_EXTENSIONS));
fflush(stdout);
}
else if ( strcmp(argv[i], "-exit")==0) {
autoexit = 35;
printf("Auto Exit after approx. %i seconds.\n", autoexit );
fflush(stdout);
}
}
}
static void
visible(int vis)
{
if (vis == GLUT_VISIBLE)
//Fl::add_idle(idle_fl); // Takes the place of the glut idle loop
Fl::add_timeout(per_frame_time, fixed_fps);
else
//Fl::remove_idle(idle_fl); // Takes the place of the glut idle loop
Fl::remove_timeout(fixed_fps);
}
int main(int argc, char *argv[])
{
// glutInit(&argc, argv); // not needed by fltk
// create FLTK window instead
Fl::get_system_colors();
Fl_Window window(320, 350);
window.resizable(window);
window.label("FL Gears");
fps_out = new Fl_Value_Output(260, 318, 50, 25, "FPS:");
fps_max = new Fl_Value_Output(152, 318, 50, 25, "MAX:");
fps_avg = new Fl_Value_Output( 45, 318, 50, 25, "AVG:");
window.show(); // glut will die unless parent window visible
window.begin(); // this will cause Glut window to be a child
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowPosition(10, 10);
glutInitWindowSize(300, 300);
glutCreateWindow("flGears");
window.end();
init(argc, argv);
glutDisplayFunc(draw);
glutReshapeFunc(reshape);
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutVisibilityFunc(visible);
Fl::add_timeout(5.0, check_fps); // compute FPS without
GLUT_ELAPSED_TIME
// Fl::add_idle(idle_fl); // Takes the place of the glut idle loop
Fl::add_timeout(per_frame_time, fixed_fps); // draw at desired FPS
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
/* End of File */
SELEX Galileo Ltd
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14
3EL
A company registered in England & Wales. Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk