/* Copyright (c) Mark J. Kilgard, 1994. */ /* This program is freely distributable without licensing fees and is provided without guarantee or warrantee expressed or implied. This program is -not- in the public domain. */ #include #include #include #include /* for cos(), sin(), and sqrt() */ #include extern unsigned char mjk_image[]; extern int mjk_depth; extern int mjk_height; extern int mjk_width; float tick1 = 0; float tick2 = 0; float angle; float size; int set_timeout = 0; int visible = 0; int spinning = 1; int scaling = 1; int interval = 100; #define CUBE 1 #define SQUARES 2 #define DRUM 3 int mode = SQUARES; void animate(int value) { if (visible) { if (spinning || scaling) { if (value) { if (spinning) { tick1 += 4 * (interval / 100.0); angle = ((int) tick1) % 360; } if (scaling) { tick2 += 2 * (interval / 100.0); size = .7 - .5 * sin(tick2 / 20.0); } } glutPostRedisplay(); set_timeout = 1; } } } #define TIMEDELTA(dest, src1, src2) { \ if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) {\ (dest).tv_usec += 1000000;\ (dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1;\ } else (dest).tv_sec = (src1).tv_sec - (src2).tv_sec; } void redraw(void) { int begin, end, elapsed; int i, j; float amplitude; if (set_timeout) { begin = glutGet(GLUT_ELAPSED_TIME); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); if (mode != DRUM) { glScalef(size, size, size); } switch (mode) { case SQUARES: #define COLS 6 #define TILE_TEX_W (1.0/COLS) #define ROWS 6 #define TILE_TEX_H (1.0/ROWS) glTranslatef(-COLS / 2.0 + .5, -ROWS / 2.0 + .5, 0); for (i = 0; i < COLS; i++) { for (j = 0; j < ROWS; j++) { glPushMatrix(); glTranslatef(i, j, 0); glRotatef(angle, 0, 1, 1); glBegin(GL_QUADS); glTexCoord2f(i * TILE_TEX_W, j * TILE_TEX_H); glVertex2f(-.5, -.5); glTexCoord2f((i + 1) * TILE_TEX_W, j * TILE_TEX_H); glVertex2f(.5, -.5); glTexCoord2f((i + 1) * TILE_TEX_W, (j + 1) * TILE_TEX_H); glVertex2f(.5, .5); glTexCoord2f(i * TILE_TEX_W, (j + 1) * TILE_TEX_H); glVertex2f(-.5, .5); glEnd(); glPopMatrix(); } } break; case DRUM: #undef COLS #undef TILE_TEX_W #undef ROWS #undef TILE_TEX_H #define COLS 12 #define TILE_TEX_W (1.0/COLS) #define ROWS 12 #define TILE_TEX_H (1.0/ROWS) glRotatef(angle, 0, 0, 1); glTranslatef(-COLS / 2.0 + .5, -ROWS / 2.0 + .5, 0); amplitude = 0.4 * sin(tick2 / 6.0); for (i = 0; i < COLS; i++) { for (j = 0; j < ROWS; j++) { #define Z(x,y) (((COLS-(x))*(x) + (ROWS-(y))*(y)) * amplitude) - 28.0 glPushMatrix(); glTranslatef(i, j, 0); glBegin(GL_QUADS); glTexCoord2f(i * TILE_TEX_W, j * TILE_TEX_H); glVertex3f(-.5, -.5, Z(i, j)); glTexCoord2f((i + 1) * TILE_TEX_W, j * TILE_TEX_H); glVertex3f(.5, -.5, Z(i + 1, j)); glTexCoord2f((i + 1) * TILE_TEX_W, (j + 1) * TILE_TEX_H); glVertex3f(.5, .5, Z(i + 1, j + 1)); glTexCoord2f(i * TILE_TEX_W, (j + 1) * TILE_TEX_H); glVertex3f(-.5, .5, Z(i, j + 1)); glEnd(); glPopMatrix(); } } break; case CUBE: glRotatef(angle, 0, 1, 0); glBegin(GL_QUADS); /* front */ glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 1.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); /* back */ glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, -1.0); glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0); /* left */ glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0); glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0); glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0); /* right */ glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, -1.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 1.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 1.0); glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, -1.0); glEnd(); } glPopMatrix(); glutSwapBuffers(); if (set_timeout) { set_timeout = 0; end = glutGet(GLUT_ELAPSED_TIME); elapsed = end - begin; if (elapsed > interval) { glutTimerFunc(0, animate, 1); } else { glutTimerFunc(interval - elapsed, animate, 1); } } } int width; int height; int depth; unsigned char *bits; void visibility(int state) { if (state == GLUT_VISIBLE) { visible = 1; animate(0); } else { visible = 0; } } void minify_select(int value) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, value); gluBuild2DMipmaps(GL_TEXTURE_2D, depth, width, height, GL_RGB, GL_UNSIGNED_BYTE, bits); glutPostRedisplay(); } void rate_select(int value) { interval = value; } void menu_select(int value) { switch (value) { case 1: spinning = !spinning; if (spinning) animate(0); break; case 2: scaling = !scaling; if (scaling) animate(0); break; case 3: mode++; if (mode > DRUM) mode = CUBE; switch (mode) { case CUBE: glEnable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); break; case SQUARES: glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); break; case DRUM: glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); break; } glutPostRedisplay(); break; case 666: exit(0); } } int main(int argc, char **argv) { int minify_menu, rate_menu; glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("mjkwarp"); glutDisplayFunc(redraw); glMatrixMode(GL_PROJECTION); gluPerspective( /* field of view in degree */ 40.0, /* aspect ratio */ 1.0, /* Z near */ 1.0, /* Z far */ 70.0); glMatrixMode(GL_MODELVIEW); gluLookAt(0.0, 0.0, 5.0, /* eye is at (0,0,30) */ 0.0, 0.0, 0.0, /* center is at (0,0,0) */ 0.0, 1.0, 0.); /* up is in positive Y direction */ depth = mjk_depth; width = mjk_width; height = mjk_height; bits = mjk_image; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); gluBuild2DMipmaps(GL_TEXTURE_2D, depth, width, height, GL_RGB, GL_UNSIGNED_BYTE, bits); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glEnable(GL_TEXTURE_2D); glutVisibilityFunc(visibility); minify_menu = glutCreateMenu(minify_select); glutAddMenuEntry("Nearest", GL_NEAREST); glutAddMenuEntry("Linear", GL_LINEAR); glutAddMenuEntry("Nearest mipmap nearest", GL_NEAREST_MIPMAP_NEAREST); glutAddMenuEntry("Linear mipmap nearest", GL_LINEAR_MIPMAP_NEAREST); glutAddMenuEntry("Nearest mipmap linear", GL_NEAREST_MIPMAP_LINEAR); glutAddMenuEntry("Linear mipmap linear", GL_LINEAR_MIPMAP_LINEAR); rate_menu = glutCreateMenu(rate_select); glutAddMenuEntry(" 2/sec", 500); glutAddMenuEntry(" 6/sec", 166); glutAddMenuEntry("10/sec", 100); glutAddMenuEntry("20/sec", 50); glutAddMenuEntry("30/sec", 33); glutAddMenuEntry("60/sec", 16); glutCreateMenu(menu_select); glutAddMenuEntry("Toggle spinning", 1); glutAddMenuEntry("Toggle scaling", 2); glutAddMenuEntry("Switch mode", 3); glutAddSubMenu("Minimum frame rate", rate_menu); glutAddSubMenu("Minify modes", minify_menu); glutAddMenuEntry("Quit", 666); glutAttachMenu(GLUT_RIGHT_BUTTON); menu_select(3); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }