home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Magazin: Amiga-CD 2000 April & May
/
AMIGA_2000_04.iso
/
patches
/
mesa3.1
/
mesa-glut.lha
/
test
/
glut
/
bigtest.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-10-23
|
58KB
|
2,597 lines
/**
* My first GLUT prog.
* Uses most GLUT calls to prove it all works.
* G Edwards, 30 Aug 95.
*
* Notes:
* Display lists are not shared between windows, and there doesn't seem to be
* any provision for this in GLUT. See glxCreateContext.
*
* The windows are internally indexed 0,1,2,3,4,5,6. The actual window ids
* returned by glut are held in winId[0], ...
*
* Todo:
*
* Could reorder the windows so 0,1,2,3,4,5,6 are the gfx, 7,8 text.
*
* 30 Aug 95 GJE Created. Version 1.00
* 05 Sep 95 GJE Version 1.01.
* 07 Sep 95 GJE Version 1.02. More or less complete. All possible GLUT
* calls used, except dials/buttons/tablet/spaceball stuff.
* 15 Sep 95 GJE Add "trackball" code.
*
* Calls not used yet: these callbacks are registered but inactive.
*
* glutSpaceball<xxx>Func
* glutButtonBoxFunc
* glutDialsFunc
* glutTabletMotionFunc
* glutTabletButtonFunc
*
* Tested on:
* R3K Indigo Starter
* R4K Indigo Elan
* R4K Indy XZ
* R4K Indy XL
* R4K Indigo2 Extreme
*/
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/* Controls */
#define VERSION "1.00"
#define DATE "16Sep95"
#define DELAY 1000 /* delay for timer test */
#define MENUDELAY 200 /* hack to fix glutMenuStateFunc bug */
#define MAXWIN 9 /* max no. of windows */
unsigned int AUTODELAY = 1500; /* delay in demo mode */
#define VERSIONLONG "Version " VERSION "/" DATE ", compiled " __DATE__ ", " __TIME__ ", file " __FILE__
int pos[MAXWIN][2] =
{
{50, 150}, /* win 0 */
{450, 150}, /* win 1 */
{50, 600}, /* win 2 */
{450, 600}, /* win 3 */
{10, 10}, /* subwin 4 (relative to parent win 0) */
{300, 400}, /* help win 5 */
{850, 150}, /* cmap win 6 */
{850, 600}, /* cmap win 7 */
{250, 450} /* text win 8 */
};
int size[MAXWIN][2] =
{
{350, 350}, /* win 0 */
{350, 350}, /* win 1 */
{350, 350}, /* win 2 */
{350, 350}, /* win 3 */
{200, 200}, /* subwin 4 */
{700, 300}, /* help win 5 */
{350, 350}, /* cmap win 6 */
{350, 350}, /* cmap win 7 */
{800, 450} /* text win 8 */
};
/* Macros */
#define PR if(debug)printf
/* #define GLNEWLIST(a, b) glNewList(a, b), fprintf(stderr,
"creating list %d \n", a); */
/* #define GLCALLLIST(a) glCallList(a), fprintf(stderr,
"calling list %d \n", a); */
/* #define GLUTSETWINDOW(x) glutSetWindow(x), fprintf(stderr,
"gsw at %d\n", __LINE__) */
/* Globals */
int winId[MAXWIN] =
{0}; /* table of glut window id's */
GLboolean winVis[MAXWIN] =
{GL_FALSE}; /* is window visible */
GLboolean text[MAXWIN] =
{GL_FALSE}; /* is text on */
GLboolean winFreeze[MAXWIN] =
{GL_FALSE}; /* user requested menuFreeze */
GLboolean menuFreeze = GL_FALSE; /* menuFreeze while menus posted */
GLboolean timerOn = GL_FALSE; /* timer active */
GLboolean animation = GL_TRUE; /* idle func animation on */
GLboolean debug = GL_FALSE; /* dump all events */
GLboolean showKeys = GL_FALSE; /* dump key events */
GLboolean demoMode = GL_FALSE; /* run automatic demo */
GLboolean backdrop = GL_FALSE; /* use backdrop polygon */
GLboolean passive = GL_FALSE; /* report passive motions */
GLboolean leftDown = GL_FALSE; /* left button down ? */
GLboolean middleDown = GL_FALSE; /* middle button down ? */
int displayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
int currentShape = 0; /* current glut shape */
int scrollLine = 0, scrollCol = 0; /* help scrolling params */
int lineWidth = 1; /* line width */
int angle = 0; /* global rotation angle */
char *textPtr[1000] =
{0}; /* pointers to text window text */
int textCount = 0, helpCount = 0; /* text list indexes */
float scaleFactor = 0.0; /* window size scale factor */
#ifdef ALPHA
#undef ALPHA /* Avoid problems with DEC's ALPHA machines. */
#endif
int menu1, menu2, menu3, menu4, menu5, menu6 = 0, menu7, menu8;
enum {
RGBA, INDEX, SINGLE, DOUBLEBUFFER, DEPTH, ACCUM, ALPHA, STENCIL, MULTISAMPLE,
STEREO, MODES
};
char *modeNames[] =
{"RGBA", "INDEX", "SINGLE", "DOUBLE", "DEPTH", "ACCUM",
"ALPHA", "STENCIL", "MULTISAMPLE", "STEREO"};
int glutMode[] =
{GLUT_RGBA, GLUT_INDEX, GLUT_SINGLE, GLUT_DOUBLE, GLUT_DEPTH,
GLUT_ACCUM, GLUT_ALPHA, GLUT_STENCIL, GLUT_MULTISAMPLE, GLUT_STEREO};
int modes[MODES] =
{0};
GLboolean menuButton[3] =
{0, 0, 1};
enum {
MOUSEBUTTON, MOUSEMOTION, APPLY, RESET
};
/* Prototypes */
void gfxInit(int);
void drawScene(void);
void idleFunc(void);
void reshapeFunc(int width, int height);
void visible(int state);
void keyFunc(unsigned char key, int x, int y);
void mouseFunc(int button, int state, int x, int y);
void motionFunc(int x, int y);
void passiveMotionFunc(int x, int y);
void entryFunc(int state);
void specialFunc(int key, int x, int y);
void menuStateFunc(int state);
void timerFunc(int value);
#if 0
void delayedReinstateMenuStateCallback(int value);
#endif
void menuFunc(int value);
void showText(void);
void textString(int x, int y, char *str, void *font);
void strokeString(int x, int y, char *str, void *font);
void makeMenus(void);
int idToIndex(int id);
void setInitDisplayMode(void);
void createMenu6(void);
void removeCallbacks(void);
void addCallbacks(void);
void dumpIds(void);
void updateHelp(void);
void updateAll(void);
void killWindow(int index);
void makeWindow(int index);
void warning(char *msg);
void autoDemo(int);
void positionWindow(int index);
void reshapeWindow(int index);
void iconifyWindow(int index);
void showWindow(int index);
void hideWindow(int index);
void pushWindow(int index);
void popWindow(int index);
void attachMenus(void);
void killAllWindows(void);
void makeAllWindows(void);
void updateText(void);
void updateScrollWindow(int index, char **ptr);
void redefineShapes(int shape);
GLboolean match(char *, char *);
void checkArgs(int argc, char *argv[]);
void scaleWindows(float);
void commandLineHelp(void);
void trackBall(int mode, int button, int state, int x, int y);
void spaceballMotionCB(int, int, int);
void spaceballRotateCB(int, int, int);
void spaceballButtonCB(int, int);
void buttonBoxCB(int, int);
void dialsCB(int, int);
void tabletMotionCB(int, int);
void tabletButtonCB(int, int, int, int);
/* strdup is actually not a standard ANSI C or POSIX routine
so implement a private one. OpenVMS does not have a strdup; Linux's
standard libc doesn't declare strdup by default (unless BSD or SVID
interfaces are requested). */
static char *
stralloc(const char *string)
{
char *copy;
copy = malloc(strlen(string) + 1);
if (copy == NULL)
return NULL;
strcpy(copy, string);
return copy;
}
/* main */
int
main(int argc, char **argv)
{
/* General init */
glutInit(&argc, argv);
/* Check args */
checkArgs(argc, argv);
/* Scale window position/size if needed. Ignore aspect ratios. */
if (scaleFactor > 0.0)
scaleWindows(scaleFactor);
else
scaleWindows(glutGet(GLUT_SCREEN_WIDTH) / 1280.0);
/* Set initial display mode */
modes[RGBA] = 1;
modes[DOUBLEBUFFER] = 1;
modes[DEPTH] = 1;
setInitDisplayMode();
/* Set up menus */
makeMenus();
/* Make some windows */
makeWindow(0);
makeWindow(1);
/* Global callbacks */
glutIdleFunc(idleFunc);
glutMenuStateFunc(menuStateFunc);
/* Start demo if needed */
if (demoMode)
autoDemo(-2);
/* Fall into event loop */
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
/* gfxInit - Init opengl for each window */
void
gfxInit(int index)
{
GLfloat grey10[] =
{0.10, 0.10, 0.10, 1.0};
GLfloat grey20[] =
{0.2, 0.2, 0.2, 1.0};
GLfloat black[] =
{0.0, 0.0, 0.0, 0.0};
GLfloat diffuse0[] =
{1.0, 0.0, 0.0, 1.0};
GLfloat diffuse1[] =
{0.0, 1.0, 0.0, 1.0};
GLfloat diffuse2[] =
{1.0, 1.0, 0.0, 1.0};
GLfloat diffuse3[] =
{0.0, 1.0, 1.0, 1.0};
GLfloat diffuse4[] =
{1.0, 0.0, 1.0, 1.0};
#define XX 3
#define YY 3
#define ZZ -2.5
float vertex[][3] =
{
{-XX, -YY, ZZ},
{+XX, -YY, ZZ},
{+XX, +YY, ZZ},
{-XX, +YY, ZZ}
};
/* warning: This func mixes RGBA and CMAP calls in an ugly
fashion */
redefineShapes(currentShape); /* set up display lists */
glutSetWindow(winId[index]); /* hack - redefineShapes
changes glut win */
/* Shaded backdrop square (RGB or CMAP) */
glNewList(100, GL_COMPILE);
glPushAttrib(GL_LIGHTING);
glDisable(GL_LIGHTING);
glBegin(GL_POLYGON);
glColor4fv(black);
glIndexi(0);
glVertex3fv(vertex[0]);
glColor4fv(grey10);
glIndexi(3);
glVertex3fv(vertex[1]);
glColor4fv(grey20);
glIndexi(4);
glVertex3fv(vertex[2]);
glColor4fv(grey10);
glIndexi(7);
glVertex3fv(vertex[3]);
glEnd();
glPopAttrib();
glIndexi(9);
glEndList();
/* Set proj+view */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, 1.0, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.);
glTranslatef(0.0, 0.0, -1.0);
if (index == 6 || index == 7)
goto colorindex;
/* Set basic material, lighting for RGB windows */
if (index == 0)
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse0);
else if (index == 1)
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse1);
else if (index == 2)
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse2);
else if (index == 3)
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse3);
else if (index == 4)
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse4);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
if (index == 4)
glClearColor(0.15, 0.15, 0.15, 1);
else
glClearColor(0.1, 0.1, 0.1, 1.0);
return;
/* Set GL basics for CMAP windows 6,7 */
colorindex:
glEnable(GL_DEPTH_TEST);
if (glutGet(GLUT_WINDOW_COLORMAP_SIZE) < 16)
warning("Color map size too small for color index window");
/* Try to reuse an existing color map */
if ((index == 6) && (winId[7] != 0)) {
glutCopyColormap(winId[7]);
} else if ((index == 7) && (winId[6] != 0)) {
glutCopyColormap(winId[6]);
} else {
glutSetColor(8, 0.1, 0.1, 0.1);
glutSetColor(9, 1.0, 0.5, 0.0);
glutSetColor(10, 1.0, 0.6, 0.8);
}
glClearIndex(8);
glIndexi(index + 3);
}
/* makeMenus - Create popup menus */
void
makeMenus(void)
{
/* General control / debug */
menu2 = glutCreateMenu(menuFunc);
glutAddMenuEntry("toggle auto demo mode (a)", 312);
glutAddMenuEntry("toggle freezing in menus", 300);
glutAddMenuEntry("toggle text per window (t)", 301);
glutAddMenuEntry("toggle global timer", 302);
glutAddMenuEntry("toggle global animation", 303);
glutAddMenuEntry("toggle per window animation", 304);
glutAddMenuEntry("toggle debug prints (D)", 305);
glutAddMenuEntry("toggle shaded backdrop", 307);
glutAddMenuEntry("toggle passive motion callback", 308);
glutAddMenuEntry("increase line width (l)", 310);
glutAddMenuEntry("decrease line width (L)", 311);
/* Shapes */
menu3 = glutCreateMenu(menuFunc);
glutAddMenuEntry("sphere", 200);
glutAddMenuEntry("cube", 201);
glutAddMenuEntry("cone", 202);
glutAddMenuEntry("torus", 203);
glutAddMenuEntry("dodecahedron", 204);
glutAddMenuEntry("octahedron", 205);
glutAddMenuEntry("tetrahedron", 206);
glutAddMenuEntry("icosahedron", 207);
glutAddMenuEntry("teapot", 208);
/* Open/close windows */
menu4 = glutCreateMenu(menuFunc);
glutAddMenuEntry("open all windows", 450);
glutAddMenuEntry("close all windows", 451);
glutAddMenuEntry(" ", 9999);
glutAddMenuEntry("create win 0", 400);
glutAddMenuEntry("create win 1", 401);
glutAddMenuEntry("create win 2", 402);
glutAddMenuEntry("create win 3", 403);
glutAddMenuEntry("create sub window", 404);
glutAddMenuEntry("create color index win 6", 406);
glutAddMenuEntry("create color index win 7", 407);
glutAddMenuEntry(" ", 9999);
glutAddMenuEntry("destroy win 0", 410);
glutAddMenuEntry("destroy win 1", 411);
glutAddMenuEntry("destroy win 2", 412);
glutAddMenuEntry("destroy win 3", 413);
glutAddMenuEntry("destroy sub window", 414);
glutAddMenuEntry("destroy color index win 6", 416);
glutAddMenuEntry("destroy color index win 7", 417);
/* Window manager stuff */
menu5 = glutCreateMenu(menuFunc);
glutAddMenuEntry("move current win", 430);
glutAddMenuEntry("resize current win", 431);
glutAddMenuEntry("iconify current win", 432);
glutAddMenuEntry("show current win", 433);
glutAddMenuEntry("hide current win", 434);
glutAddMenuEntry("push current win", 435);
glutAddMenuEntry("pop current win", 436);
glutAddMenuEntry(" ", 9999);
glutAddMenuEntry("move win 1", 420);
glutAddMenuEntry("resize win 1", 421);
glutAddMenuEntry("iconify win 1", 422);
glutAddMenuEntry("show win 1", 423);
glutAddMenuEntry("hide win 1", 424);
glutAddMenuEntry("push win 1", 425);
glutAddMenuEntry("pop win 1", 426);
/* Gfx modes */
createMenu6(); /* build dynamically */
/* Texty reports */
menu7 = glutCreateMenu(menuFunc);
glutAddMenuEntry("report current win modes", 700);
glutAddMenuEntry("report current device data", 701);
glutAddMenuEntry("check OpenGL extensions", 702);
glutAddMenuEntry("dump internal data (d)", 703);
/* Play with menus */
menu8 = glutCreateMenu(menuFunc);
glutAddMenuEntry("toggle menus on left button", 805);
glutAddMenuEntry("toggle menus on middle button", 806);
glutAddMenuEntry("toggle menus on right button", 807);
glutAddMenuEntry("---------------------------", 9999);
glutAddMenuEntry("add plain items", 800);
glutAddMenuEntry("add submenu items", 801);
glutAddMenuEntry("change new entries to plain items", 802);
glutAddMenuEntry("change new entries to submenus", 803);
glutAddMenuEntry("remove all new items", 804);
glutAddMenuEntry("---------------------------", 9999);
/* Main menu */
menu1 = glutCreateMenu(menuFunc);
glutAddSubMenu("control", menu2);
glutAddSubMenu("shapes", menu3);
glutAddSubMenu("windows", menu4);
glutAddSubMenu("window ops", menu5);
glutAddSubMenu("gfx modes", menu6);
glutAddSubMenu("reports", menu7);
glutAddSubMenu("menus", menu8);
glutAddMenuEntry("help (h)", 101);
glutAddMenuEntry("quit (esc)", 100);
}
/* createMenu6 - Dynamically rebuild menu of display modes to
show current choices */
void
createMenu6(void)
{
char str[100];
int i;
if (menu6 != 0)
glutDestroyMenu(menu6);
menu6 = glutCreateMenu(menuFunc);
for (i = 0; i < MODES; i++) {
sprintf(str, "%srequest %s", (modes[i] ? "+ " : " "), modeNames[i]);
glutAddMenuEntry(str, 602 + i);
}
}
/* menuFunc - Process return codes from popup menus */
void
menuFunc(int value)
{
static int initItems = 10;
int items, m;
if (initItems == 0) {
glutSetMenu(menu8);
initItems = glutGet(GLUT_MENU_NUM_ITEMS);
}
PR("Menu returned value %d \n", value);
switch (value) {
/* GLUT shapes */
case 200:
case 201:
case 202:
case 203:
case 204:
case 205:
case 206:
case 207:
case 208:
redefineShapes(value - 200);
break;
/* Overall controls */
case 300:
menuFreeze = !menuFreeze;
break;
case 301:
text[idToIndex(glutGetWindow())] = !(text[idToIndex(glutGetWindow())]);
break;
case 302:
timerOn = !timerOn;
if (timerOn)
glutTimerFunc(DELAY, timerFunc, 1);
break;
case 303:
animation = !animation;
if (animation)
glutIdleFunc(idleFunc);
else
glutIdleFunc(NULL);
break;
case 304:
winFreeze[idToIndex(glutGetWindow())] = !(winFreeze[idToIndex(
glutGetWindow())]);
break;
case 305:
debug = !debug;
break;
case 307:
backdrop = !backdrop;
break;
case 308:
passive = !passive;
if (passive)
glutPassiveMotionFunc(passiveMotionFunc);
else
glutPassiveMotionFunc(NULL);
break;
case 310:
lineWidth += 1;
updateAll();
break;
case 311:
lineWidth -= 1;
if (lineWidth < 1)
lineWidth = 1;
updateAll();
break;
case 312:
demoMode = !demoMode;
if (demoMode)
autoDemo(-2);
break;
/* Window create/destroy. */
/* Creates */
case 400:
makeWindow(0);
break;
case 401:
makeWindow(1);
break;
case 402:
makeWindow(2);
break;
case 403:
makeWindow(3);
break;
case 404:
makeWindow(4);
break;
case 406:
makeWindow(6);
break;
case 407:
makeWindow(7);
break;
/* Destroys */
case 410:
killWindow(0);
break;
case 411:
killWindow(1);
break;
case 412:
killWindow(2);
break;
case 413:
killWindow(3);
break;
case 414:
killWindow(4);
break;
case 416:
killWindow(6);
break;
case 417:
killWindow(7);
break;
case 450:
makeAllWindows();
break;
case 451:
killAllWindows();
break;
/* Window movements etc. */
case 420:
positionWindow(1);
break;
case 421:
reshapeWindow(1);
break;
case 422:
iconifyWindow(1);
break;
case 423:
showWindow(1);
break;
case 424:
hideWindow(1);
break;
case 425:
pushWindow(1);
break;
case 426:
popWindow(1);
break;
case 430:
positionWindow(idToIndex(glutGetWindow()));
break;
case 431:
reshapeWindow(idToIndex(glutGetWindow()));
break;
case 432:
iconifyWindow(idToIndex(glutGetWindow()));
break;
case 433:
showWindow(idToIndex(glutGetWindow()));
break;
case 434:
hideWindow(idToIndex(glutGetWindow()));
break;
case 435:
pushWindow(idToIndex(glutGetWindow()));
break;
case 436:
popWindow(idToIndex(glutGetWindow()));
break;
/* Test gfx modes. */
case 600:
makeWindow(3);
break;
case 601:
killWindow(3);
break;
case 602:
case 603:
case 604:
case 605:
case 606:
case 607:
case 608:
case 609:
case 610:
case 611:
modes[value - 602] = !modes[value - 602];
setInitDisplayMode();
break;
/* Text reports */
/* This is pretty ugly. */
#define INDENT 30
#define REPORTSTART(text) \
printf("\n" text "\n"); \
textPtr[0] = (char *)malloc(strlen(text)+1); \
strcpy(textPtr[0], text); \
textCount = 1;
#define REPORTEND \
scrollLine = 0; \
textPtr[textCount] = NULL; \
makeWindow(8); \
updateText();
#define GLUTGET(name) \
{ \
char str[100], str2[100]; \
int s, len; \
sprintf(str, # name); \
len = (int) strlen(# name); \
for(s = 0 ; s < INDENT-len; s++) \
strcat(str, " "); \
sprintf(str2, ": %d\n",glutGet(name)); \
strcat(str, str2); \
printf(str); \
textPtr[textCount] = stralloc(str); \
textCount++; \
}
case 700:
printf("XXXXXX glutGetWindow = %d\n", glutGetWindow());
REPORTSTART("glutGet():");
GLUTGET(GLUT_WINDOW_X);
GLUTGET(GLUT_WINDOW_Y);
GLUTGET(GLUT_WINDOW_WIDTH);
GLUTGET(GLUT_WINDOW_HEIGHT);
GLUTGET(GLUT_WINDOW_BUFFER_SIZE);
GLUTGET(GLUT_WINDOW_STENCIL_SIZE);
GLUTGET(GLUT_WINDOW_DEPTH_SIZE);
GLUTGET(GLUT_WINDOW_RED_SIZE);
GLUTGET(GLUT_WINDOW_GREEN_SIZE);
GLUTGET(GLUT_WINDOW_BLUE_SIZE);
GLUTGET(GLUT_WINDOW_ALPHA_SIZE);
GLUTGET(GLUT_WINDOW_ACCUM_RED_SIZE);
GLUTGET(GLUT_WINDOW_ACCUM_GREEN_SIZE);
GLUTGET(GLUT_WINDOW_ACCUM_BLUE_SIZE);
GLUTGET(GLUT_WINDOW_ACCUM_ALPHA_SIZE);
GLUTGET(GLUT_WINDOW_DOUBLEBUFFER);
GLUTGET(GLUT_WINDOW_RGBA);
GLUTGET(GLUT_WINDOW_PARENT);
GLUTGET(GLUT_WINDOW_NUM_CHILDREN);
GLUTGET(GLUT_WINDOW_COLORMAP_SIZE);
GLUTGET(GLUT_WINDOW_NUM_SAMPLES);
GLUTGET(GLUT_STEREO);
GLUTGET(GLUT_SCREEN_WIDTH);
GLUTGET(GLUT_SCREEN_HEIGHT);
GLUTGET(GLUT_SCREEN_HEIGHT_MM);
GLUTGET(GLUT_SCREEN_WIDTH_MM);
GLUTGET(GLUT_MENU_NUM_ITEMS);
GLUTGET(GLUT_DISPLAY_MODE_POSSIBLE);
GLUTGET(GLUT_INIT_DISPLAY_MODE);
GLUTGET(GLUT_INIT_WINDOW_X);
GLUTGET(GLUT_INIT_WINDOW_Y);
GLUTGET(GLUT_INIT_WINDOW_WIDTH);
GLUTGET(GLUT_INIT_WINDOW_HEIGHT);
GLUTGET(GLUT_ELAPSED_TIME);
REPORTEND;
break;
#define GLUTDEVGET(name) \
{ \
char str[100], str2[100]; \
int len, s; \
sprintf(str, # name); \
len = (int) strlen(# name); \
for(s = 0 ; s < INDENT-len; s++) \
strcat(str, " "); \
sprintf(str2, ": %d\n", \
glutDeviceGet(name)); \
strcat(str, str2); \
printf(str); \
textPtr[textCount] = stralloc(str); \
textCount++; \
}
case 701:
REPORTSTART("glutDeviceGet():");
GLUTDEVGET(GLUT_HAS_KEYBOARD);
GLUTDEVGET(GLUT_HAS_MOUSE);
GLUTDEVGET(GLUT_HAS_SPACEBALL);
GLUTDEVGET(GLUT_HAS_DIAL_AND_BUTTON_BOX);
GLUTDEVGET(GLUT_HAS_TABLET);
GLUTDEVGET(GLUT_NUM_MOUSE_BUTTONS);
GLUTDEVGET(GLUT_NUM_SPACEBALL_BUTTONS);
GLUTDEVGET(GLUT_NUM_BUTTON_BOX_BUTTONS);
GLUTDEVGET(GLUT_NUM_DIALS);
GLUTDEVGET(GLUT_NUM_TABLET_BUTTONS);
REPORTEND;
break;
#define EXTCHECK(name) \
{ \
char str[100], str2[100]; \
int len, s; \
sprintf(str, # name); \
len = (int) strlen(# name); \
for(s = 0 ; s < INDENT-len; s++) \
strcat(str, " "); \
sprintf(str2, ": %s\n", \
glutExtensionSupported(# name)? \
"yes": "no"); \
strcat(str, str2); \
printf(str); \
textPtr[textCount] = stralloc(str); \
textCount++; \
}
case 702:
REPORTSTART("glutExtensionSupported():");
EXTCHECK(GL_EXT_abgr);
EXTCHECK(GL_EXT_blend_color);
EXTCHECK(GL_EXT_blend_minmax);
EXTCHECK(GL_EXT_blend_logic_op);
EXTCHECK(GL_EXT_blend_subtract);
EXTCHECK(GL_EXT_polygon_offset);
EXTCHECK(GL_EXT_texture);
EXTCHECK(GL_EXT_guaranteed_to_fail);
EXTCHECK(GLX_SGI_swap_control);
EXTCHECK(GLX_SGI_video_sync);
EXTCHECK(GLX_SGIS_multi_sample);
REPORTEND;
break;
case 703:
dumpIds();
break;
/* Mess around with menus */
case 800:
if (glutGetMenu() != menu8) /* just a test */
printf("glutGetMenu() returned unexpected value\n");
glutAddMenuEntry("help", 101);
glutAddMenuEntry("help", 101);
glutAddMenuEntry("help", 101);
glutAddMenuEntry("help", 101);
glutAddMenuEntry("help", 101);
break;
case 801:
glutAddSubMenu("shapes", menu3);
glutAddSubMenu("shapes", menu3);
glutAddSubMenu("shapes (a long string to break menus with)", menu3);
glutAddSubMenu("shapes", menu3);
glutAddSubMenu("shapes", menu3);
break;
case 802:
items = glutGet(GLUT_MENU_NUM_ITEMS);
for (m = initItems + 1; m <= items; m++) {
glutChangeToMenuEntry(m, "help", 101);
}
break;
case 803:
items = glutGet(GLUT_MENU_NUM_ITEMS);
for (m = initItems + 1; m <= items; m++) {
glutChangeToSubMenu(m, "shapes", menu3);
}
break;
case 804:
items = glutGet(GLUT_MENU_NUM_ITEMS);
/* reverse order so renumbering not aproblem */
for (m = items; m >= initItems + 1; m--) {
glutRemoveMenuItem(m);
}
break;
case 805:
menuButton[0] = !menuButton[0];
attachMenus();
break;
case 806:
menuButton[1] = !menuButton[1];
attachMenus();
break;
case 807:
menuButton[2] = !menuButton[2];
attachMenus();
break;
/* Direct menu items. */
case 100:
exit(0);
break;
case 101:
if (winId[5] == 0)
makeWindow(5);
else
killWindow(5);
break;
case 9999:
break;
default:
fprintf(stderr, "\007Unhandled case %d in menu callback\n", value);
}
}
/* redefineShapes - Remake the shapes display lists */
void
redefineShapes(int shape)
{
int i;
#define C3 \
switch(i) \
{ \
case 0: \
case 3: \
C1; \
break; \
\
case 1: \
case 2: \
case 4: \
case 6: \
case 7: \
C2; \
break; \
} \
currentShape = shape
for (i = 0; i < MAXWIN; i++) {
if (winId[i]) {
glutSetWindow(winId[i]);
if (glIsList(i + 1))
glDeleteLists(i + 1, 1);
glNewList(i + 1, GL_COMPILE);
switch (shape) {
#undef C1
#define C1 glutSolidSphere(1.5, 10, 10)
#undef C2
#define C2 glutWireSphere(1.5, 10, 10)
case 0:
C3;
break;
#undef C1
#define C1 glutSolidCube(2)
#undef C2
#define C2 glutWireCube(2)
case 1:
C3;
break;
#undef C1
#define C1 glutSolidCone(1.5, 1.75, 10, 10);
#undef C2
#define C2 glutWireCone(1.5, 1.75, 10, 10);
case 2:
C3;
break;
#undef C1
#define C1 glutSolidTorus(0.5, 1.1, 10, 10)
#undef C2
#define C2 glutWireTorus(0.5, 1.1, 10, 10)
case 3:
C3;
break;
#undef C1
#define C1 glScalef(.8, .8, .8);glutSolidDodecahedron()
#undef C2
#define C2 glScalef(.8, .8, .8);glutWireDodecahedron()
case 4:
C3;
break;
#undef C1
#define C1 glScalef(1.5, 1.5, 1.5);glutSolidOctahedron()
#undef C2
#define C2 glScalef(1.5, 1.5, 1.5);glutWireOctahedron()
case 5:
C3;
break;
#undef C1
#define C1 glScalef(1.8, 1.8, 1.8);glutSolidTetrahedron()
#undef C2
#define C2 glScalef(1.8, 1.8, 1.8);glutWireTetrahedron()
case 6:
C3;
break;
#undef C1
#define C1 glScalef(1.5, 1.5, 1.5);glutSolidIcosahedron()
#undef C2
#define C2 glScalef(1.5, 1.5, 1.5);glutWireIcosahedron()
case 7:
C3;
break;
#undef C1
#define C1 glutSolidTeapot(1.5);
#undef C2
#define C2 glutWireTeapot(1.5);
case 8:
C3;
break;
}
glEndList();
}
}
}
/* positionWindow - Shift a window */
void
positionWindow(int index)
{
int x, y;
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
x = glutGet(GLUT_WINDOW_X);
y = glutGet(GLUT_WINDOW_Y);
glutPositionWindow(x + 50, y + 50);
}
/* reshapeWindow - Change window size a little */
void
reshapeWindow(int index)
{
int x, y;
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
x = glutGet(GLUT_WINDOW_WIDTH);
y = glutGet(GLUT_WINDOW_HEIGHT);
/* glutReshapeWindow(x * (index % 2? 0.8: 1.2), y * (index % 2?
1.2: 0.8)); */
glutReshapeWindow((int) (x * 1.0), (int) (y * 0.8));
}
/* iconifyWindow - Iconify a window */
void
iconifyWindow(int index)
{
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
glutIconifyWindow();
}
/* showWindow - Show a window (map or uniconify it) */
void
showWindow(int index)
{
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
glutShowWindow();
}
/* hideWindow - Hide a window (unmap it) */
void
hideWindow(int index)
{
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
glutHideWindow();
}
/* pushWindow - Push a window */
void
pushWindow(int index)
{
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
glutPushWindow();
}
/* popWindow - Pop a window */
void
popWindow(int index)
{
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
glutPopWindow();
}
/* drawScene - Draw callback, triggered by expose events etc.
in GLUT. */
void
drawScene(void)
{
int winIndex;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
winIndex = idToIndex(glutGetWindow());
/* printf("drawScene for index %d, id %d\n", winIndex,
glutGetWindow()); */
glPushMatrix();
glLineWidth(lineWidth);
if (backdrop)
glCallList(100);
/* Left button spinning */
trackBall(APPLY, 0, 0, 0, 0);
/* Apply continuous spinning */
glRotatef(angle, 0, 1, 0);
glCallList(winIndex + 1);
glPopMatrix();
if (text[winIndex])
showText();
glutSwapBuffers();
}
/* showText - Render some text in the current GLUT window */
void
showText(void)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, 100, 0, 100);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3f(1.0, 1.0, 1.0);
glIndexi(7);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glLineWidth(lineWidth);
textString(1, 1, "GLUT_BITMAP_8_BY_13", GLUT_BITMAP_8_BY_13);
textString(1, 5, "GLUT_BITMAP_9_BY_15", GLUT_BITMAP_9_BY_15);
textString(1, 10, "GLUT_BITMAP_TIMES_ROMAN_10", GLUT_BITMAP_TIMES_ROMAN_10);
textString(1, 15, "GLUT_BITMAP_TIMES_ROMAN_24", GLUT_BITMAP_TIMES_ROMAN_24);
strokeString(1, 25, "GLUT_STROKE_ROMAN", GLUT_STROKE_ROMAN);
strokeString(1, 35, "GLUT_STROKE_MONO_ROMAN", GLUT_STROKE_MONO_ROMAN);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
/* textString - Bitmap font string */
void
textString(int x, int y, char *msg, void *font)
{
glRasterPos2f(x, y);
while (*msg) {
glutBitmapCharacter(font, *msg);
msg++;
}
}
/* strokeString - Stroke font string */
void
strokeString(int x, int y, char *msg, void *font)
{
glPushMatrix();
glTranslatef(x, y, 0);
glScalef(.04, .04, .04);
while (*msg) {
glutStrokeCharacter(font, *msg);
msg++;
}
glPopMatrix();
}
/* idleFunc - GLUT idle func callback - animates windows */
void
idleFunc(void)
{
int i;
if (!leftDown && !middleDown)
angle += 1;
angle = angle % 360;
for (i = 0; i < MAXWIN; i++) {
if (winId[i] && winVis[i] && !winFreeze[i]) {
glutSetWindow(winId[i]);
glutPostRedisplay();
}
}
}
/* reshapeFunc - Reshape callback. */
void
reshapeFunc(int width, int height)
{
int winId;
float aspect;
winId = glutGetWindow();
PR("reshape callback for window id %d \n", winId);
glViewport(0, 0, width, height);
aspect = (float) width / height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, aspect, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
}
/* visible - Visibility callback. Turn off rendering in
invisible windows */
void
visible(int state)
{
int winId;
static GLboolean someVisible = GL_TRUE;
winId = glutGetWindow();
/* printf("visible: state = %d \n", state); */
if (state == GLUT_VISIBLE) {
PR("Window id %d visible \n", winId);
winVis[idToIndex(winId)] = GL_TRUE;
} else {
PR("Window %d not visible \n", winId);
winVis[idToIndex(winId)] = GL_FALSE;
}
if ((winVis[0] == GL_FALSE) && (winVis[1] == GL_FALSE) && (winVis[2] == GL_FALSE)
&& (winVis[3] == GL_FALSE) && (winVis[6] == GL_FALSE) && (winVis[7] ==
GL_FALSE)) {
glutIdleFunc(NULL);
PR("All windows not visible; idle func disabled\n");
someVisible = GL_FALSE;
} else {
if (!someVisible) {
PR("Some windows now visible; idle func enabled\n");
someVisible = GL_TRUE;
if (animation)
glutIdleFunc(idleFunc);
}
}
}
/* keyFunc - Ascii key callback */
/* ARGSUSED1 */
void
keyFunc(unsigned char key, int x, int y)
{
int i, ii;
if (debug || showKeys)
printf("Ascii key '%c' 0x%02x\n", key, key);
switch (key) {
case 0x1b:
exit(0);
break;
case 'a':
demoMode = !demoMode;
if (demoMode)
autoDemo(-2);
break;
case 's':
AUTODELAY = AUTODELAY * 0.666;
break;
case 'S':
AUTODELAY = AUTODELAY * 1.5;
break;
case 'q':
killWindow(idToIndex(glutGetWindow()));
break;
case 'k':
showKeys = !showKeys;
break;
case 'p':
demoMode = !demoMode;
if (demoMode)
autoDemo(-999);
break;
case 'D':
debug = !debug;
break;
case 'd':
dumpIds();
break;
case 'h':
if (winId[5] == 0)
makeWindow(5);
else
killWindow(5);
break;
case 't':
ii = idToIndex(glutGetWindow());
text[ii] = !text[ii];
break;
case 'r':
trackBall(RESET, 0, 0, 0, 0);
break;
case 'l':
lineWidth += 1;
updateAll();
break;
case 'L':
lineWidth -= 1;
if (lineWidth < 1)
lineWidth = 1;
updateAll();
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '6':
i = key - '0';
winVis[i] = !winVis[i];
break;
case ')':
makeWindow(0);
break;
case '!':
makeWindow(1);
break;
case '@':
makeWindow(2);
break;
case '#':
makeWindow(3);
break;
}
}
/* specialFunc - Special keys callback (F keys, cursor keys
etc. */
/* ARGSUSED1 */
void
specialFunc(int key, int x, int y)
{
if (debug || showKeys)
printf("Special key %d\n", key);
switch (key) {
case GLUT_KEY_PAGE_DOWN:
scrollLine += 10;
updateHelp();
updateText();
break;
case GLUT_KEY_PAGE_UP:
scrollLine -= 10;
updateHelp();
updateText();
break;
case GLUT_KEY_DOWN:
scrollLine += 1;
updateHelp();
updateText();
break;
case GLUT_KEY_UP:
scrollLine -= 1;
updateHelp();
updateText();
break;
case GLUT_KEY_HOME:
scrollLine = 0;
updateHelp();
updateText();
break;
case GLUT_KEY_END:
scrollLine = 9999;
updateHelp();
updateText();
break;
case GLUT_KEY_RIGHT:
scrollCol -= 1;
updateHelp();
updateText();
break;
case GLUT_KEY_LEFT:
scrollCol += 1;
updateHelp();
updateText();
break;
}
}
/* mouseFunc - Mouse button callback */
void
mouseFunc(int button, int state, int x, int y)
{
PR("Mouse button %d, state %d, at pos %d, %d\n", button, state, x, y);
trackBall(MOUSEBUTTON, button, state, x, y);
}
/* motionFunc - Mouse movement (with a button down) callback */
void
motionFunc(int x, int y)
{
PR("Mouse motion at %d, %d\n", x, y);
trackBall(MOUSEMOTION, 0, 0, x, y);
glutPostRedisplay();
}
/* passiveMotionFunc - Mouse movement (with no button down)
callback */
void
passiveMotionFunc(int x, int y)
{
printf("Mouse motion at %d, %d\n", x, y);
}
/* entryFunc - Window entry event callback */
void
entryFunc(int state)
{
int winId = glutGetWindow();
PR("Entry event: window id %d (index %d), state %d \n", winId, idToIndex(
winId), state);
}
/* menuStateFunc - Callback to tell us when menus are popped
up/down. */
int menu_state = GLUT_MENU_NOT_IN_USE;
void
menuStateFunc(int state)
{
printf("menu stated = %d\n", state);
menu_state = state;
if (glutGetWindow() == 0) {
PR("menuStateFunc: window invalid\n");
return;
}
PR("Menus are%sin use\n", state == GLUT_MENU_IN_USE ? " " : " not ");
if ((state == GLUT_MENU_IN_USE) && menuFreeze)
glutIdleFunc(NULL);
else if (animation)
glutIdleFunc(idleFunc);
}
/* timerFunc - General test of global timer */
void
timerFunc(int value)
{
printf("timer callback: value %d\n", value);
if (timerOn) {
glutTimerFunc(DELAY, timerFunc, 1);
}
}
#if 0
/* delayedReinstateMenuStateCallback - Hack to reinstate
MenuStateCallback after a while. */
void
delayedReinstateMenuStateCallback(int state)
{
glutMenuStateFunc(menuStateFunc);
}
#endif
/* setInitDisplayMode - update display modes from display mode
menu */
void
setInitDisplayMode(void)
{
int i;
displayMode = 0;
for (i = 0; i < MODES; i++) {
if (modes[i]) {
/* printf("Requesting %s \n", modeNames[i]); */
displayMode |= glutMode[i];
}
}
glutInitDisplayMode(displayMode);
createMenu6();
if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
warning("This display mode not supported\n");
}
/* makeWindow - Create one of the windows */
void
makeWindow(int index)
{
char str[99];
if (winId[index] != 0) {
/* warning("Attempt to create window which is already
created"); */
return;
}
switch (index) {
case 0: /* ordinary RGB windows */
case 1:
case 2:
case 3:
setInitDisplayMode();
glutInitWindowPosition(pos[index][0], pos[index][1]);
glutInitWindowSize(size[index][0], size[index][1]);
winId[index] = glutCreateWindow(" ");
PR("Window %d id = %d \n", index, winId[index]);
gfxInit(index);
addCallbacks();
sprintf(str, "window %d (RGB)", index);
glutSetWindowTitle(str);
sprintf(str, "icon %d", index);
glutSetIconTitle(str);
glutSetMenu(menu1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
break;
case 4: /* subwindow */
setInitDisplayMode();
winId[index] = glutCreateSubWindow(winId[0], pos[index][0], pos[index]
[1], size[index][0], size[index][1]);
PR("Window %d id = %d \n", index, winId[index]);
gfxInit(index);
glutDisplayFunc(drawScene);
glutVisibilityFunc(visible);
glutReshapeFunc(reshapeFunc);
break;
case 5: /* help window */
case 8: /* text window */
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(pos[index][0], pos[index][1]);
glutInitWindowSize(size[index][0], size[index][1]);
winId[index] = glutCreateWindow(" ");
PR("Window %d id = %d \n", index, winId[index]);
/* addCallbacks(); */
glutKeyboardFunc(keyFunc);
glutSpecialFunc(specialFunc);
glClearColor(0.15, 0.15, 0.15, 1.0);
glColor3f(1, 1, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 300, 0, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (index == 5) {
glutDisplayFunc(updateHelp);
glutSetWindowTitle("help (RGB) win 5");
glutSetIconTitle("help");
} else {
glutDisplayFunc(updateText);
glutSetWindowTitle("text (RGB) win 8");
glutSetIconTitle("text");
}
glutSetMenu(menu1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
break;
case 6: /* color index window */
case 7: /* color index window */
glutInitDisplayMode(GLUT_DOUBLE | GLUT_INDEX | GLUT_DEPTH);
glutInitWindowPosition(pos[index][0], pos[index][1]);
glutInitWindowSize(size[index][0], size[index][1]);
winId[index] = glutCreateWindow(" ");
PR("Window %d id = %d \n", index, winId[index]);
gfxInit(index);
addCallbacks();
sprintf(str, "window %d (color index)", index);
glutSetWindowTitle(str);
sprintf(str, "icon %d", index);
glutSetIconTitle(str);
glutSetMenu(menu1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
break;
}
}
/* killWindow - Kill one of the main windows */
void
killWindow(int index)
{
int i;
if (winId[index] == 0) {
/* fprintf(stderr, "Attempt to kill invalid window in
killWindow\n"); */
return;
}
PR("Killing win %d\n", index);
glutSetWindow(winId[index]);
/* Disable all callbacks for safety, although
glutDestroyWindow should do this. */
removeCallbacks();
glutDestroyWindow(winId[index]);
winId[index] = 0;
winVis[index] = GL_FALSE;
#if 0
/* If we reinstate the menu state func here, prog breaks. So
reinstate it a little later. */
glutTimerFunc(MENUDELAY, delayedReinstateMenuStateCallback, 1);
#endif
if (index == 5) { /* help */
scrollLine = 0;
scrollCol = 0;
}
if (index == 8) { /* text window */
for (i = 0; textPtr[i] != NULL; i++) {
free(textPtr[i]); /* free the text strings */
textPtr[i] = NULL;
}
}
}
/* addCallbacks - Add some standard callbacks after creating a
window */
void
addCallbacks(void)
{
glutDisplayFunc(drawScene);
glutVisibilityFunc(visible);
glutReshapeFunc(reshapeFunc);
glutKeyboardFunc(keyFunc);
glutSpecialFunc(specialFunc);
glutMouseFunc(mouseFunc);
glutMotionFunc(motionFunc);
glutEntryFunc(entryFunc);
/* Callbacks for exotic input devices. Must get my dials &
buttons back. */
glutSpaceballMotionFunc(spaceballMotionCB);
glutSpaceballRotateFunc(spaceballRotateCB);
glutSpaceballButtonFunc(spaceballButtonCB);
glutButtonBoxFunc(buttonBoxCB);
glutDialsFunc(dialsCB);
glutTabletMotionFunc(tabletMotionCB);
glutTabletButtonFunc(tabletButtonCB);
}
/* removeCallbacks - Remove all callbacks before destroying a
window. GLUT probably does this anyway but we'll be safe. */
void
removeCallbacks(void)
{
glutVisibilityFunc(NULL);
glutReshapeFunc(NULL);
glutKeyboardFunc(NULL);
glutSpecialFunc(NULL);
glutMouseFunc(NULL);
glutMotionFunc(NULL);
glutEntryFunc(NULL);
}
/* updateHelp - Update the help window after user scrolls. */
void
updateHelp(void)
{
static char *helpPtr[] =
{
"(Use PGUP, PGDN, HOME, END, arrows to scroll help text) ",
" ",
"A demo program for GLUT. ",
"G Edwards, Aug 95 ",
"Exercises 99% of GLUT calls ",
VERSIONLONG,
" ",
"This text uses GLUT_STROKE_MONO_ROMAN font, a built-in vector font.",
"(Try resizing the help window). ",
" ",
"Keys: ",
" esc quit ",
" t toggle text on/off in each window ",
" h toggle help ",
" q quit current window ",
" a auto demo ",
" p pause/unpause demo ",
" l increase line width (gfx & stroke text) ",
" L decrease line width (gfx & stroke text) ",
" r reset transforms ",
" k show keyboard events ",
" D show all events ",
" ",
"Mouse: ",
" Left button: rotate ",
" Middle button: pan ",
" Left + middle: zoom ",
NULL};
updateScrollWindow(5, helpPtr);
}
/* updateText - Update a text window */
void
updateText(void)
{
int i;
if (textPtr[0] == NULL) {
for (i = 0; i < 20; i++) {
textPtr[i] = (char *) malloc(50);
strcpy(textPtr[i], "no current text");
}
textPtr[20] = NULL;
}
updateScrollWindow(8, textPtr);
}
/* updateScrollWindow */
void
updateScrollWindow(int index, char **ptr)
{
int i, j, lines = 0;
if (winId[index] == 0)
return;
glutSetWindow(winId[index]);
for (i = 0; ptr[i] != NULL; i++)
lines++;
if (scrollLine < 0)
scrollLine = 0;
if (scrollLine > (lines - 5))
scrollLine = lines - 5;
glClear(GL_COLOR_BUFFER_BIT);
glLineWidth(lineWidth);
for (i = scrollLine, j = 1; ptr[i] != NULL; i++, j++)
strokeString(scrollCol * 50, 100 - j * 6, ptr[i],
GLUT_STROKE_MONO_ROMAN);
glutSwapBuffers();
}
/* updateAll - Update all visible windows after soem global
change, eg. line width */
void
updateAll(void)
{
int i;
if (winId[5] != 0)
updateHelp();
if (winId[8] != 0)
updateText();
for (i = 0; i < MAXWIN; i++)
if (winId[i]) {
glutSetWindow(winId[i]);
glutPostRedisplay();
}
}
/* idToIndex - Convert GLUT window id to our internal index */
int
idToIndex(int id)
{
int i;
for (i = 0; i < MAXWIN; i++) {
if (winId[i] == id)
return i;
}
fprintf(stderr, "error: id %d not found \n", id);
return (-1);
}
/* warning - warning messages */
void
warning(char *msg)
{
fprintf(stderr, "\007");
if (debug) {
fprintf(stderr, "%s", msg);
if (msg[strlen(msg)] != '\n')
fprintf(stderr, "%s", "\n");
}
}
/* dumpIds - Debug: dump some internal data */
void
dumpIds(void)
{
int i, j;
printf("\nInternal data:\n");
for (i = 0; i < MAXWIN; i++)
printf("Index %d, glut win id %d, visibility %d\n", i, winId[i],
winVis[i]);
for (i = 0; i < MAXWIN; i++) {
if (winId[i])
glutSetWindow(winId[i]);
else {
printf("index %d - no glut window\n", i);
continue;
}
for (j = 1; j <= MAXWIN; j++)
printf("Index %d, display list %d %s defined\n", i, j, glIsList(j) ?
"is " : "not");
}
}
/* autoDemo - Run auto demo/test This is a bit tricky. We need
to start a timer sequence which progressively orders things
to be done. The work really gets done when we return from
our callback. Have to think about the event loop / callback
design here. */
void
autoDemo(int value)
{
#define STEP(a, b) \
case a: \
action(a); \
glutTimerFunc(AUTODELAY * b, autoDemo, next(a); \
break;
static int index = 0;
static int count = 0;
static int restartValue = -2;
if (value == -999)
value = restartValue;
restartValue = value;
#define AUTODELAY2 (unsigned int) (AUTODELAY*0.66)
/* fprintf(stderr, "autoDemo: value %d \n", value); */
if (!demoMode)
return;
if (menu_state == GLUT_MENU_IN_USE) {
glutTimerFunc(AUTODELAY / 2, autoDemo, value);
return;
}
switch (value) {
/* Entry point; kill off existing windows. */
case -2:
killAllWindows();
glutTimerFunc(AUTODELAY / 2, autoDemo, 1);
break;
/* Start making windows */
case -1:
makeWindow(0);
glutTimerFunc(AUTODELAY, autoDemo, 0); /* skip case 0
first time */
break;
/* Change shape & backdrop */
case 0:
currentShape = (currentShape + 1) % 9;
redefineShapes(currentShape);
count += 1;
if (count % 2)
backdrop = !backdrop;
glutTimerFunc(AUTODELAY, autoDemo, 1);
break;
/* Keep making windows */
case 1:
makeWindow(1);
glutTimerFunc(AUTODELAY, autoDemo, 2);
break;
case 2:
makeWindow(2);
glutTimerFunc(AUTODELAY, autoDemo, 3);
break;
case 3:
makeWindow(3);
glutTimerFunc(AUTODELAY, autoDemo, 4);
break;
case 4:
makeWindow(4);
glutTimerFunc(AUTODELAY, autoDemo, 5);
break;
case 5:
makeWindow(5);
glutTimerFunc(AUTODELAY * 2, autoDemo, 51);
break;
case 51:
makeWindow(6);
glutTimerFunc(AUTODELAY * 2, autoDemo, 52);
break;
case 52:
makeWindow(7);
glutTimerFunc(AUTODELAY * 2, autoDemo, 53);
break;
/* Kill last 3 windows, leave 4 up. */
case 53:
killWindow(7);
glutTimerFunc(AUTODELAY, autoDemo, 54);
break;
case 54:
killWindow(6);
glutTimerFunc(AUTODELAY, autoDemo, 6);
break;
case 6:
killWindow(5);
glutTimerFunc(AUTODELAY, autoDemo, 7);
break;
case 7:
killWindow(4);
glutTimerFunc(AUTODELAY, autoDemo, 700);
break;
/* Change shape again */
case 700:
currentShape = (currentShape + 1) % 9;
redefineShapes(currentShape);
glutTimerFunc(AUTODELAY, autoDemo, 701);
break;
/* Cycle 4 main windows through various window ops. */
case 701:
positionWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 701 : 702);
break;
case 702:
reshapeWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 702 : 703);
break;
case 703:
iconifyWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 703 : 704);
break;
case 704:
showWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 704 : 705);
break;
case 705:
hideWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 705 : 706);
break;
case 706:
showWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 706 : 707);
break;
case 707:
pushWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 707 : 708);
break;
case 708:
popWindow(index);
index = (index + 1) % 4;
glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 708 : 8);
break;
/* Kill all windows */
case 8:
killWindow(3);
glutTimerFunc(AUTODELAY, autoDemo, 9);
break;
case 9:
killWindow(2);
glutTimerFunc(AUTODELAY, autoDemo, 10);
break;
case 10:
killWindow(1);
glutTimerFunc(AUTODELAY, autoDemo, 11);
break;
case 11:
killWindow(0);
glutTimerFunc(AUTODELAY, autoDemo, -1); /* back to start */
break;
}
}
/* attachMenus - Attach/detach menus to/from mouse buttons */
void
attachMenus(void)
{
int i, b;
int button[3] =
{GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON};
for (i = 0; i < MAXWIN; i++) {
if (winId[i] != 0) {
for (b = 0; b < 3; b++) {
glutSetWindow(winId[i]);
glutSetMenu(menu1);
if (menuButton[b])
glutAttachMenu(button[b]);
else
glutDetachMenu(button[b]);
}
}
}
}
/* killAllWindows - Kill all windows (except 0) */
void
killAllWindows(void)
{
int w;
for (w = 1; w < MAXWIN; w++)
if (winId[w])
killWindow(w);
}
/* makeAllWindows - Make all windows */
void
makeAllWindows(void)
{
int w;
for (w = 0; w < MAXWIN; w++)
if (!winId[w])
makeWindow(w);
}
/* checkArgs - Check command line args */
void
checkArgs(int argc, char *argv[])
{
int argp;
GLboolean quit = GL_FALSE;
GLboolean error = GL_FALSE;
#define AA argv[argp]
#if 0
#define NEXT argp++; \
if(argp >= argc) \
{ \
Usage(); \
Exit(1); \
}
#endif
argp = 1;
while (argp < argc) {
if (match(AA, "-help")) {
commandLineHelp();
quit = GL_TRUE;
} else if (match(AA, "-version")) {
printf(VERSIONLONG "\n");
quit = GL_TRUE;
} else if (match(AA, "-auto")) {
demoMode = GL_TRUE;
} else if (match(AA, "-scale")) {
argp++;
scaleFactor = atof(argv[argp]);
} else {
fprintf(stderr, "Unknown arg: %s\n", AA);
error = GL_TRUE;
quit = GL_TRUE;
}
argp++;
}
if (error) {
commandLineHelp();
exit(1);
}
if (quit)
exit(0);
}
/* commandLineHelp - Command line help */
void
commandLineHelp(void)
{
printf("Usage:\n");
printf(" -h[elp] this stuff\n");
printf(" -v[ersion] show version\n");
printf(" -a[uto] start in auto demo mode\n");
printf(" -s[cale] f scale windows by f\n");
printf("Standard GLUT args:\n");
printf(" -iconic start iconic\n");
printf(" -display DISP use display DISP\n");
printf(" -direct use direct rendering (default)\n");
printf(" -indirect use indirect rendering\n");
printf(" -sync use synchronous X protocol\n");
printf(" -gldebug check OpenGL errors\n");
printf(" -geometry WxH+X+Y standard X window spec (overridden here) \n");
}
/* match - Match a string (any unique substring). */
GLboolean
match(char *arg, char *t)
{
if (strstr(t, arg))
return GL_TRUE;
else
return GL_FALSE;
}
/* scaleWindows - Scale initial window sizes ansd positions */
void
scaleWindows(float scale)
{
int i;
for (i = 0; i < MAXWIN; i++) {
pos[i][0] = pos[i][0] * scale;
pos[i][1] = pos[i][1] * scale;
size[i][0] = size[i][0] * scale;
size[i][1] = size[i][1] * scale;
}
}
/* trackBall - A simple trackball (not with proper rotations). */
/** A simple trackball with spin = left button
pan = middle button
zoom = left + middle
Doesn't have proper trackball rotation, ie axes which remain fixed in
the scene. We should use the trackball code from 4Dgifts. */
#define STARTROTATE(x, y) \
{ \
startMX = x; \
startMY = y; \
}
#define STOPROTATE(x, y) \
{ \
steadyXangle = varXangle; \
steadyYangle = varYangle; \
}
#define STARTPAN(x, y) \
{ \
startMX = x; \
startMY = y; \
}
#define STOPPAN(x, y) \
{ \
steadyX = varX; \
steadyY = varY; \
}
#define STARTZOOM(x, y) \
{ \
startMX = x; \
startMY = y; \
}
#define STOPZOOM(x, y) \
{ \
steadyZ = varZ; \
}
static float
fixAngle(float angle)
{
return angle - floor(angle / 360.0) * 360.0;
}
void
trackBall(int mode, int button, int state, int x, int y)
{
static int startMX = 0, startMY = 0; /* initial mouse pos */
static int deltaMX = 0, deltaMY = 0; /* initial mouse pos */
static float steadyXangle = 0.0, steadyYangle = 0.0;
static float varXangle = 0.0, varYangle = 0.0;
static float steadyX = 0.0, steadyY = 0.0, steadyZ = 0.0;
static float varX = 0.0, varY = 0.0, varZ = 0.0;
switch (mode) {
case RESET:
steadyXangle = steadyYangle = steadyX = steadyY = steadyZ = 0.0;
break;
case MOUSEBUTTON:
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && !middleDown) {
STARTROTATE(x, y);
leftDown = GL_TRUE;
} else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN &&
middleDown) {
STOPPAN(x, y);
STARTZOOM(x, y);
leftDown = GL_TRUE;
} else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN &&
!leftDown) {
STARTPAN(x, y);
middleDown = GL_TRUE;
} else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN &&
leftDown) {
STOPROTATE(x, y);
STARTZOOM(x, y);
middleDown = GL_TRUE;
} else if (state == GLUT_UP && button == GLUT_LEFT_BUTTON && !middleDown) {
STOPROTATE(x, y);
leftDown = GL_FALSE;
} else if (state == GLUT_UP && button == GLUT_LEFT_BUTTON && middleDown) {
STOPZOOM(x, y);
STARTROTATE(x, y);
leftDown = GL_FALSE;
} else if (state == GLUT_UP && button == GLUT_MIDDLE_BUTTON && !leftDown) {
STOPPAN(x, y);
middleDown = GL_FALSE;
} else if (state == GLUT_UP && button == GLUT_MIDDLE_BUTTON && leftDown) {
STOPZOOM(x, y);
STARTROTATE(x, y);
middleDown = GL_FALSE;
}
break;
case APPLY:
if (leftDown && !middleDown) {
glTranslatef(steadyX, steadyY, steadyZ);
glRotatef(varXangle, 0, 1, 0);
glRotatef(varYangle, 1, 0, 0);
}
/* Middle button pan */
else if (middleDown && !leftDown) {
glTranslatef(varX, varY, steadyZ);
glRotatef(steadyXangle, 0, 1, 0);
glRotatef(steadyYangle, 1, 0, 0);
}
/* Left + middle zoom. */
else if (leftDown && middleDown) {
glTranslatef(steadyX, steadyY, varZ);
glRotatef(steadyXangle, 0, 1, 0);
glRotatef(steadyYangle, 1, 0, 0);
}
/* Nothing down. */
else {
glTranslatef(steadyX, steadyY, steadyZ);
glRotatef(steadyXangle, 0, 1, 0);
glRotatef(steadyYangle, 1, 0, 0);
}
break;
case MOUSEMOTION:
deltaMX = x - startMX;
deltaMY = startMY - y;
if (leftDown && !middleDown) {
varXangle = fixAngle(steadyXangle + deltaMX);
varYangle = fixAngle(steadyYangle + deltaMY);
} else if (middleDown && !leftDown) {
varX = steadyX + deltaMX / 100.0;
varY = steadyY + deltaMY / 100.0;
} else if (leftDown && middleDown) {
varZ = steadyZ - deltaMY / 50.0;
}
break;
}
}
/* Callbacks for exotic input devices. These have not been
tested yet owing to the usual complete absence of such
devices in the UK support group. */
/* spaceballMotionCB */
void
spaceballMotionCB(int x, int y, int z)
{
printf("spaceballMotionCB: translations are X %d, Y %d, Z %d\n", x, y, z);
}
/* spaceballRotateCB */
void
spaceballRotateCB(int x, int y, int z)
{
printf("spaceballRotateCB: rotations are X %d, Y %d, Z %d\n", x, y, z);
}
/* spaceballButtonCB */
void
spaceballButtonCB(int button, int state)
{
printf("spaceballButtonCB: button %d, state %d\n", button, state);
}
/* buttonBoxCB */
void
buttonBoxCB(int button, int state)
{
printf("buttonBoxCB: button %d, state %d\n", button, state);
}
/* dialsCB */
void
dialsCB(int dial, int value)
{
printf("dialsCB: dial %d, value %d\n", dial, value);
}
/* tabletMotionCB */
void
tabletMotionCB(int x, int y)
{
printf("tabletMotionCB: X %d, Y %d\n", x, y);
}
/* tabletButtonCB */
/* ARGSUSED2 */
void
tabletButtonCB(int button, int state, int dummy1, int dummy2)
{
printf("tabletButtonCB: button %d, state %d\n", button, state);
}