#include <stdio.h>
#include <stdlib.h>
#include <math.h>
+#include <string.h>
+#include <GL/glew.h>
#include <GL/glut.h>
-#include "readtex.c" /* I know, this is a hack. */
+#include "readtex.h"
+#include "trackball.h"
+
#define SPECULAR_TEXTURE_FILE "../images/reflect.rgb"
#define BASE_TEXTURE_FILE "../images/tile.rgb"
#define ANIMATE 3
#define QUIT 100
+/* for convolution */
+#define FILTER_SIZE 7
+
+static GLint WinWidth = 500, WinHeight = 500;
static GLuint CylinderObj = 0;
static GLuint TeapotObj = 0;
static GLuint Object = 0;
static GLboolean Animate = GL_TRUE;
-static GLfloat Xrot = 0.0, Yrot = 0.0, Zrot = 0.0;
-static GLfloat DXrot = 1.0, DYrot = 2.5;
+static float CurQuat[4] = { 0, 0, 0, 1 };
static GLfloat Black[4] = { 0, 0, 0, 0 };
static GLfloat White[4] = { 1, 1, 1, 1 };
static GLuint BaseTexture, SpecularTexture;
static GLboolean DoSpecTexture = GL_TRUE;
+static GLboolean ButtonDown = GL_FALSE;
+static GLint ButtonX, ButtonY;
+
+
/* performance info */
static GLint T0 = 0;
static GLint Frames = 0;
-
-
static void Idle( void )
{
- if (Animate) {
- Xrot += DXrot;
- Yrot += DYrot;
- glutPostRedisplay();
- }
+ static const float yAxis[3] = {0, 1, 0};
+ static double t0 = -1.;
+ float quat[4];
+ double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ if (t0 < 0.0)
+ t0 = t;
+ dt = t - t0;
+ t0 = t;
+
+ axis_to_quat(yAxis, 2.0 * dt, quat);
+ add_quats(quat, CurQuat, CurQuat);
+
+ glutPostRedisplay();
}
static void Display( void )
{
+ GLfloat rot[4][4];
+
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
- glRotatef(Xrot, 1.0, 0.0, 0.0);
- glRotatef(Yrot, 0.0, 1.0, 0.0);
- glRotatef(Zrot, 0.0, 0.0, 1.0);
+ build_rotmatrix(rot, CurQuat);
+ glMultMatrixf(&rot[0][0]);
/* First pass: diffuse lighting with base texture */
glMaterialfv(GL_FRONT, GL_DIFFUSE, Diffuse);
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
+ fflush(stdout);
T0 = t;
Frames = 0;
}
{
GLfloat h = 30.0;
GLfloat w = h * width / height;
+ WinWidth = width;
+ WinHeight = height;
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMaterialf(GL_FRONT, GL_SHININESS, Shininess);
printf("Shininess = %g\n", Shininess);
break;
+ case 'a':
case ' ':
ToggleAnimate();
break;
}
-static void SpecialKey( int key, int x, int y )
+static void
+MouseMotion(int x, int y)
{
- float step = 3.0;
- (void) x;
- (void) y;
+ if (ButtonDown) {
+ float x0 = (2.0 * ButtonX - WinWidth) / WinWidth;
+ float y0 = (WinHeight - 2.0 * ButtonY) / WinHeight;
+ float x1 = (2.0 * x - WinWidth) / WinWidth;
+ float y1 = (WinHeight - 2.0 * y) / WinHeight;
+ float q[4];
+
+ trackball(q, x0, y0, x1, y1);
+ ButtonX = x;
+ ButtonY = y;
+ add_quats(q, CurQuat, CurQuat);
- switch (key) {
- case GLUT_KEY_UP:
- Xrot += step;
- break;
- case GLUT_KEY_DOWN:
- Xrot -= step;
- break;
- case GLUT_KEY_LEFT:
- Yrot += step;
- break;
- case GLUT_KEY_RIGHT:
- Yrot -= step;
- break;
+ glutPostRedisplay();
}
- glutPostRedisplay();
+}
+
+
+static void
+MouseButton(int button, int state, int x, int y)
+{
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+ ButtonDown = GL_TRUE;
+ ButtonX = x;
+ ButtonY = y;
+ }
+ else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+ ButtonDown = GL_FALSE;
+ }
}
static void Init( int argc, char *argv[] )
{
+ GLboolean convolve = GL_FALSE;
+ GLboolean fullscreen = GL_FALSE;
+ int i;
+
+ 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));
+ }
+ else if (strcmp(argv[i], "-c")==0) {
+ convolve = GL_TRUE;
+ }
+ else if (strcmp(argv[i], "-f")==0) {
+ fullscreen = GL_TRUE;
+ }
+ }
+
+ if (fullscreen)
+ glutFullScreen();
+
/* Cylinder object */
{
static GLfloat height = 100.0;
glBindTexture(GL_TEXTURE_2D, SpecularTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#if 1
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-#else
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
- glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
-#endif
- if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE, GL_RGB)) {
- printf("Error: couldn't load texture image file %s\n", SPECULAR_TEXTURE_FILE);
- exit(1);
+ if (convolve) {
+ /* use convolution to blur the texture to simulate a dull finish
+ * on the object.
+ */
+ GLubyte *img;
+ GLenum format;
+ GLint w, h;
+ GLfloat filter[FILTER_SIZE][FILTER_SIZE][4];
+
+ for (h = 0; h < FILTER_SIZE; h++) {
+ for (w = 0; w < FILTER_SIZE; w++) {
+ const GLfloat k = 1.0 / (FILTER_SIZE * FILTER_SIZE);
+ filter[h][w][0] = k;
+ filter[h][w][1] = k;
+ filter[h][w][2] = k;
+ filter[h][w][3] = k;
+ }
+ }
+
+ glEnable(GL_CONVOLUTION_2D);
+ glConvolutionParameteri(GL_CONVOLUTION_2D,
+ GL_CONVOLUTION_BORDER_MODE, GL_CONSTANT_BORDER);
+ glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_RGBA,
+ FILTER_SIZE, FILTER_SIZE,
+ GL_RGBA, GL_FLOAT, filter);
+
+ img = LoadRGBImage(SPECULAR_TEXTURE_FILE, &w, &h, &format);
+ if (!img) {
+ printf("Error: couldn't load texture image file %s\n",
+ SPECULAR_TEXTURE_FILE);
+ exit(1);
+ }
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
+ format, GL_UNSIGNED_BYTE, img);
+ free(img);
+ }
+ else {
+ /* regular path */
+ if (!LoadRGBMipmaps(SPECULAR_TEXTURE_FILE, GL_RGB)) {
+ printf("Error: couldn't load texture image file %s\n",
+ SPECULAR_TEXTURE_FILE);
+ exit(1);
+ }
}
/* misc */
glEnable(GL_NORMALIZE);
glPolygonOffset( -1, -1 );
-
- if (argc > 1 && strcmp(argv[1], "-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));
- }
}
int main( int argc, char *argv[] )
{
glutInit( &argc, argv );
- glutInitWindowPosition(0, 0);
- glutInitWindowSize( 500, 500 );
-
+ glutInitWindowSize(WinWidth, WinHeight);
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
-
glutCreateWindow(argv[0] );
-
- Init(argc, argv);
-
+ glewInit();
glutReshapeFunc( Reshape );
glutKeyboardFunc( Key );
- glutSpecialFunc( SpecialKey );
glutDisplayFunc( Display );
- glutIdleFunc( Idle );
+ glutMotionFunc(MouseMotion);
+ glutMouseFunc(MouseButton);
+ if (Animate)
+ glutIdleFunc( Idle );
glutCreateMenu(ModeMenu);
glutAddMenuEntry("Toggle Highlight", DO_SPEC_TEXTURE);
glutAddMenuEntry("Quit", QUIT);
glutAttachMenu(GLUT_RIGHT_BUTTON);
+ Init(argc, argv);
+
glutMainLoop();
return 0;
}