/* texture.c Nate Robins, 1997 Tool for teaching about OpenGL texture. */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <GL/glut.h> #include "glm.h" #pragma comment( linker, "/entry:\"mainCRTStartup\"" ) // set the entry point to be main() typedef struct _cell { int id; int x, y; float min, max; float value; float step; char* info; char* format; } cell; cell texcoords[2*4] = { { 1, 140, 370, -2.0, 2.0, 0.0, 0.01, "Specifies S value of 1st texture coordinate", "%.1f" }, { 2, 190, 370, -2.0, 2.0, 0.0, 0.01, "Specifies T value of 1st texture coordinate", "%.1f" }, { 3, 140, 400, -2.0, 2.0, 1.0, 0.01, "Specifies S value of 2nd texture coordinate", "%.1f" }, { 4, 190, 400, -2.0, 2.0, 0.0, 0.01, "Specifies T value of 2nd texture coordinate", "%.1f" }, { 5, 140, 430, -2.0, 2.0, 1.0, 0.01, "Specifies S value of 3rd texture coordinate", "%.1f" }, { 6, 190, 430, -2.0, 2.0, 1.0, 0.01, "Specifies T value of 3rd texture coordinate", "%.1f" }, { 7, 140, 460, -2.0, 2.0, 0.0, 0.01, "Specifies S value of 4th texture coordinate", "%.1f" }, { 8, 190, 460, -2.0, 2.0, 1.0, 0.01, "Specifies T value of 4th texture coordinate", "%.1f" }, }; cell vertices[3*4] = { { 9, 350, 370, -2.0, 2.0, -1.0, 0.01, "Specifies X coordinate of 1st vertex", "%.1f" }, { 10, 400, 370, -2.0, 2.0, -1.0, 0.01, "Specifies Y coordinate of 1st vertex", "%.1f" }, { 11, 450, 370, -2.0, 2.0, 0.0, 0.01, "Specifies Z coordinate of 1st vertex", "%.1f" }, { 12, 350, 400, -2.0, 2.0, 1.0, 0.01, "Specifies X coordinate of 2nd vertex", "%.1f" }, { 13, 400, 400, -2.0, 2.0, -1.0, 0.01, "Specifies Y coordinate of 2nd vertex", "%.1f" }, { 14, 450, 400, -2.0, 2.0, 0.0, 0.01, "Specifies Z coordinate of 2nd vertex", "%.1f" }, { 15, 350, 430, -2.0, 2.0, 1.0, 0.01, "Specifies X coordinate of 3rd vertex", "%.1f" }, { 16, 400, 430, -2.0, 2.0, 1.0, 0.01, "Specifies Y coordinate of 3rd vertex", "%.1f" }, { 17, 450, 430, -2.0, 2.0, 0.0, 0.01, "Specifies Z coordinate of 3rd vertex", "%.1f" }, { 18, 350, 460, -2.0, 2.0, -1.0, 0.01, "Specifies X coordinate of 4th vertex", "%.1f" }, { 19, 400, 460, -2.0, 2.0, 1.0, 0.01, "Specifies Y coordinate of 4th vertex", "%.1f" }, { 20, 450, 460, -2.0, 2.0, 0.0, 0.01, "Specifies Z coordinate of 4th vertex", "%.1f" }, }; GLenum minfilter = GL_NEAREST; GLenum magfilter = GL_NEAREST; GLenum env = GL_MODULATE; GLenum wraps = GL_REPEAT; GLenum wrapt = GL_REPEAT; cell translation[3] = { { 21, 120, 90, -5.0, 5.0, 0.0, 0.01, "Specifies X coordinate of translation vector.", "%.2f" }, { 22, 180, 90, -5.0, 5.0, 0.0, 0.01, "Specifies Y coordinate of translation vector.", "%.2f" }, { 23, 240, 90, -5.0, 5.0, 0.0, 0.01, "Specifies Z coordinate of translation vector.", "%.2f" }, }; cell rotation[4] = { { 24, 120, 120, -360.0, 360.0, 0.0, 1.0, "Specifies angle of rotation, in degrees.", "%.1f" }, { 25, 180, 120, -1.0, 1.0, 0.0, 0.01, "Specifies X coordinate of vector to rotate about.", "%.2f" }, { 26, 240, 120, -1.0, 1.0, 0.0, 0.01, "Specifies Y coordinate of vector to rotate about.", "%.2f" }, { 27, 300, 120, -1.0, 1.0, 1.0, 0.01, "Specifies Z coordinate of vector to rotate about.", "%.2f" }, }; cell scale[3] = { { 28, 120, 150, -5.0, 5.0, 1.0, 0.01, "Specifies scale factor along X axis.", "%.2f" }, { 29, 180, 150, -5.0, 5.0, 1.0, 0.01, "Specifies scale factor along Y axis.", "%.2f" }, { 30, 240, 150, -5.0, 5.0, 1.0, 0.01, "Specifies scale factor along Z axis.", "%.2f" }, }; cell pcolor[4] = { { 31, 120, 310, 0.0, 1.0, 0.6, 0.01, "Specifies red component of polygon color.", "%.2f" }, { 32, 180, 310, 0.0, 1.0, 0.6, 0.01, "Specifies green component of polygon color.", "%.2f" }, { 33, 240, 310, 0.0, 1.0, 0.6, 0.01, "Specifies blue component of polygon color.", "%.2f" }, { 34, 300, 310, 0.0, 1.0, 1.0, 0.01, "Specifies alpha component of polygon color.", "%.2f" }, }; cell bcolor[4] = { { 39, 240, 30, 0.0, 1.0, 1.0, 0.01, "Specifies red component of texture border color.", "%.2f" }, { 40, 300, 30, 0.0, 1.0, 0.0, 0.01, "Specifies green component of texture border color.", "%.2f" }, { 41, 360, 30, 0.0, 1.0, 0.0, 0.01, "Specifies blue component of texture border color.", "%.2f" }, { 42, 420, 30, 0.0, 1.0, 1.0, 0.01, "Specifies alpha component of texture border color.", "%.2f" }, }; cell ecolor[4] = { { 35, 240, 60, 0.0, 1.0, 0.0, 0.01, "Specifies red component of texture environment color.", "%.2f" }, { 36, 300, 60, 0.0, 1.0, 1.0, 0.01, "Specifies green component of texture environment color.", "%.2f" }, { 37, 360, 60, 0.0, 1.0, 0.0, 0.01, "Specifies blue component of texture environment color.", "%.2f" }, { 38, 420, 60, 0.0, 1.0, 1.0, 0.01, "Specifies alpha component of texture environment color.", "%.2f" }, }; GLfloat eye[3] = { 0.0, 0.0, 3.0 }; GLfloat at[3] = { 0.0, 0.0, 0.0 }; GLfloat up[3] = { 0.0, 1.0, 0.0 }; void redisplay_all(void); GLuint window, world, screen, command; GLuint sub_width = 256, sub_height = 256; GLint selection = 0; GLfloat spin_x = 0.0; GLfloat spin_y = 0.0; int iheight, iwidth; unsigned char* image = NULL; int twidth, theight; int stipple; #if defined(GL_VERSION_1_1) #define GL_REPLACE_EXT GL_REPLACE #endif GLvoid *font_style = GLUT_BITMAP_TIMES_ROMAN_10; void setfont(char* name, int size) { font_style = GLUT_BITMAP_HELVETICA_10; if (strcmp(name, "helvetica") == 0) { if (size == 12) font_style = GLUT_BITMAP_HELVETICA_12; else if (size == 18) font_style = GLUT_BITMAP_HELVETICA_18; } else if (strcmp(name, "times roman") == 0) { font_style = GLUT_BITMAP_TIMES_ROMAN_10; if (size == 24) font_style = GLUT_BITMAP_TIMES_ROMAN_24; } else if (strcmp(name, "8x13") == 0) { font_style = GLUT_BITMAP_8_BY_13; } else if (strcmp(name, "9x15") == 0) { font_style = GLUT_BITMAP_9_BY_15; } } void drawstr(GLuint x, GLuint y, char* format, ...) { va_list args; char buffer[255], *s; va_start(args, format); vsprintf(buffer, format, args); va_end(args); glRasterPos2i(x, y); for (s = buffer; *s; s++) glutBitmapCharacter(font_style, *s); } void cell_draw(cell* cell) { glColor3ub(0, 255, 128); if (selection == cell->id) { glColor3ub(255, 255, 0); drawstr(10, 525, cell->info); glColor3ub(255, 0, 0); } drawstr(cell->x, cell->y, cell->format, cell->value); } int cell_hit(cell* cell, int x, int y) { if (x > cell->x && x < cell->x+50 && y > cell->y-20 && y < cell->y+10) return cell->id; return 0; } void cell_update(cell* cell, int update) { if (selection != cell->id) return; cell->value += update * cell->step; if (cell->value < cell->min) cell->value = cell->min; else if (cell->value > cell->max) cell->value = cell->max; } void cell_vector(float* dst, cell* cell, int num) { while (--num >= 0) dst[num] = cell[num].value; } void drawaxes(void) { glColor3ub(255, 0, 0); glBegin(GL_LINE_STRIP); glVertex3f(0.0, 0.0, 0.0); glVertex3f(1.0, 0.0, 0.0); glVertex3f(0.75, 0.25, 0.0); glVertex3f(0.75, -0.25, 0.0); glVertex3f(1.0, 0.0, 0.0); glVertex3f(0.75, 0.0, 0.25); glVertex3f(0.75, 0.0, -0.25); glVertex3f(1.0, 0.0, 0.0); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 1.0, 0.0); glVertex3f(0.0, 0.75, 0.25); glVertex3f(0.0, 0.75, -0.25); glVertex3f(0.0, 1.0, 0.0); glVertex3f(0.25, 0.75, 0.0); glVertex3f(-0.25, 0.75, 0.0); glVertex3f(0.0, 1.0, 0.0); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 1.0); glVertex3f(0.25, 0.0, 0.75); glVertex3f(-0.25, 0.0, 0.75); glVertex3f(0.0, 0.0, 1.0); glVertex3f(0.0, 0.25, 0.75); glVertex3f(0.0, -0.25, 0.75); glVertex3f(0.0, 0.0, 1.0); glEnd(); glColor3ub(255, 255, 0); glRasterPos3f(1.1, 0.0, 0.0); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, 'x'); glRasterPos3f(0.0, 1.1, 0.0); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, 'y'); glRasterPos3f(0.0, 0.0, 1.1); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, 'z'); } void texenv(void) { GLfloat env_color[4], border_color[4]; cell_vector(env_color, ecolor, 4); cell_vector(border_color, bcolor, 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wraps); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapt); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); } void texture(void) { texenv(); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, iwidth, iheight, GL_RGB, GL_UNSIGNED_BYTE, image); } void main_reshape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, width, height, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); #define GAP 25 /* gap between subwindows */ sub_width = (width-GAP*3)/3; sub_height = (height-GAP*3)/2; glutSetWindow(screen); glutPositionWindow(GAP, GAP); glutReshapeWindow(sub_width, sub_height); glutSetWindow(world); glutPositionWindow(GAP, GAP+sub_height+GAP); glutReshapeWindow(sub_width, sub_height); glutSetWindow(command); glutPositionWindow(GAP+sub_width+GAP, GAP); glutReshapeWindow(sub_width*2, sub_height*2+GAP); } void main_display(void) { glClearColor(0.8, 0.8, 0.8, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3ub(0, 0, 0); setfont("helvetica", 12); drawstr(GAP, GAP-5, "Screen-space view"); drawstr(GAP+sub_width+GAP, GAP-5, "Command manipulation window"); drawstr(GAP, GAP+sub_height+GAP-5, "Texture-space view"); glutSwapBuffers(); } void world_reshape(int width, int height) { twidth = width; theight = height; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wraps); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapt); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, 0, height, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0, 0.0, 0.0, 1.0); glDisable(GL_DEPTH_TEST); glEnable(GL_LIGHT0); } void world_display(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, twidth, 0, theight, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3ub(255, 255, 255); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glBegin(GL_POLYGON); glTexCoord2f(-0.5, -0.5); glVertex2i(0, 0); glTexCoord2f(1.5, -0.5); glVertex2i(twidth, 0); glTexCoord2f(1.5, 1.5); glVertex2i(twidth, theight); glTexCoord2f(-0.5, 1.5); glVertex2i(0, theight); glEnd(); glBegin(GL_POLYGON); glTexCoord2f(-0.5, -0.5); glVertex2i(-1, -1); glTexCoord2f(1.5, -0.5); glVertex2i(1, -1); glTexCoord2f(1.5, 1.5); glVertex2i(1, 1); glTexCoord2f(-0.5, 1.5); glVertex2i(-1, 1); glEnd(); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glScalef(twidth/2, theight/2, 1.0); glTranslatef(0.5, 0.5, 0.0); glTranslatef(translation[0].value, translation[1].value, translation[2].value); glRotatef(rotation[0].value, rotation[1].value, rotation[2].value, rotation[3].value); glScalef(scale[0].value, scale[1].value, scale[2].value); /* axes */ glPushMatrix(); glTranslatef(-0.001, -0.001, 0.0); glColor3ub(0, 255, 128); glBegin(GL_LINE_STRIP); glVertex2f(0.1, 0.5); glVertex2f(0.0, 0.6); glVertex2f(-0.1, 0.5); glEnd(); glBegin(GL_LINE_STRIP); glVertex2f(0.5, 0.1); glVertex2f(0.6, 0.0); glVertex2f(0.5, -0.1); glEnd(); glBegin(GL_LINE_STRIP); glVertex2f(0.6, 0.0); glVertex2f(0.0, 0.0); glVertex2f(0.0, 0.6); glEnd(); glColor3ub(255, 255, 0); glRasterPos2f(0.6, -0.1); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, 's'); glRasterPos2f(-0.1, 0.6); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, 't'); glPopMatrix(); glEnable(GL_LINE_STIPPLE); glLineStipple(1, (GLushort)stipple); glColor3ub(255, 0, 0); glBegin(GL_LINE_LOOP); glVertex2f(texcoords[0].value, texcoords[1].value); glVertex2f(texcoords[2].value, texcoords[3].value); glVertex2f(texcoords[4].value, texcoords[5].value); glVertex2f(texcoords[6].value, texcoords[7].value); glEnd(); glLineStipple(1, (GLushort)(stipple^0xffff)); glColor3ub(255, 255, 255); glBegin(GL_LINE_LOOP); glVertex2f(texcoords[0].value, texcoords[1].value); glVertex2f(texcoords[2].value, texcoords[3].value); glVertex2f(texcoords[4].value, texcoords[5].value); glVertex2f(texcoords[6].value, texcoords[7].value); glEnd(); glDisable(GL_LINE_STIPPLE); glutSwapBuffers(); } void world_menu(int value) { char* name = 0; switch (value) { case 'f': name = "data/fishermen.ppm"; break; case 'o': name = "data/opengl.ppm"; break; case 'c': name = "data/checker.ppm"; break; case 'm': name = "data/marble.ppm"; break; case 't': name = "data/train.ppm"; break; } if (name) { free(image); image = glmReadPPM(name, &iwidth, &iheight); if (!image) image = glmReadPPM("data/fishermen.ppm", &iwidth, &iheight); } glutSetWindow(screen); texture(); glutSetWindow(world); texture(); redisplay_all(); } void screen_reshape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)width/height, 0.5, 8.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(eye[0], eye[1], eye[2], at[0], at[1], at[2], up[0], up[1],up[2]); glClearColor(0.2, 0.2, 0.2, 1.0); glEnable(GL_COLOR_MATERIAL); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glTranslatef(translation[0].value, translation[1].value, translation[2].value); glRotatef(rotation[0].value, rotation[1].value, rotation[2].value, rotation[3].value); glScalef(scale[0].value, scale[1].value, scale[2].value); glMatrixMode(GL_MODELVIEW); } void screen_display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(spin_y, 1.0, 0.0, 0.0); glRotatef(spin_x, 0.0, 1.0, 0.0); glColor4f(pcolor[0].value, pcolor[1].value, pcolor[2].value, pcolor[3].value); glBegin(GL_POLYGON); glNormal3f(0.0, 0.0, 1.0); glTexCoord2f(texcoords[0].value, texcoords[1].value); glVertex3f(vertices[0].value, vertices[1].value, vertices[2].value); glTexCoord2f(texcoords[2].value, texcoords[3].value); glVertex3f(vertices[3].value, vertices[4].value, vertices[5].value); glTexCoord2f(texcoords[4].value, texcoords[5].value); glVertex3f(vertices[6].value, vertices[7].value, vertices[8].value); glTexCoord2f(texcoords[6].value, texcoords[7].value); glVertex3f(vertices[9].value, vertices[10].value, vertices[11].value); glEnd(); glPopMatrix(); glutSwapBuffers(); } int old_x, old_y; void screen_mouse(int button, int state, int x, int y) { old_x = x; old_y = y; redisplay_all(); } void screen_motion(int x, int y) { spin_x = x - old_x; spin_y = y - old_y; redisplay_all(); } void command_reshape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, width, height, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0, 0.0, 0.0, 0.0); glDisable(GL_DEPTH_TEST); } void polygon_display(void) { setfont("helvetica", 12); drawstr(10, pcolor[0].y-50, "glEnable(GL_TEXTURE_2D);"); drawstr(10, pcolor[0].y-30, "gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h, " "GL_RGB, GL_UNSIGNED_BYTE, image);"); setfont("helvetica", 18); drawstr(10, pcolor[0].y, "glColor4f("); drawstr(pcolor[0].x+50, pcolor[0].y, ","); drawstr(pcolor[1].x+50, pcolor[1].y, ","); drawstr(pcolor[2].x+50, pcolor[2].y, ","); drawstr(pcolor[3].x+50, pcolor[2].y, ");"); drawstr(10, texcoords[0].y-30, "glBegin(GL_POLYGON);"); drawstr(10, texcoords[0].y, "glTexCoord2f("); drawstr(texcoords[0].x+40, texcoords[0].y, ","); drawstr(texcoords[1].x+40, texcoords[1].y, ");"); drawstr(250, vertices[0].y, "glVertex3f("); drawstr(vertices[0].x+40, vertices[0].y, ","); drawstr(vertices[1].x+40, vertices[1].y, ","); drawstr(vertices[2].x+40, vertices[1].y, ");"); drawstr(10, texcoords[2].y, "glTexCoord2f("); drawstr(texcoords[2].x+40, texcoords[2].y, ","); drawstr(texcoords[3].x+40, texcoords[3].y, ");"); drawstr(250, vertices[3].y, "glVertex3f("); drawstr(vertices[3].x+40, vertices[3].y, ","); drawstr(vertices[4].x+40, vertices[4].y, ","); drawstr(vertices[5].x+40, vertices[5].y, ");"); drawstr(10, texcoords[4].y, "glTexCoord2f("); drawstr(texcoords[4].x+40, texcoords[4].y, ","); drawstr(texcoords[5].x+40, texcoords[5].y, ");"); drawstr(250, vertices[6].y, "glVertex3f("); drawstr(vertices[6].x+40, vertices[6].y, ","); drawstr(vertices[7].x+40, vertices[7].y, ","); drawstr(vertices[8].x+40, vertices[8].y, ");"); drawstr(10, texcoords[6].y, "glTexCoord2f("); drawstr(texcoords[6].x+40, texcoords[6].y, ","); drawstr(texcoords[7].x+40, texcoords[7].y, ");"); drawstr(250, vertices[9].y, "glVertex3f("); drawstr(vertices[9].x+40, vertices[9].y, ","); drawstr(vertices[10].x+40, vertices[10].y, ","); drawstr(vertices[11].x+40, vertices[11].y, ");"); drawstr(10, vertices[11].y+30, "glEnd();"); cell_draw(&texcoords[0]); cell_draw(&texcoords[1]); cell_draw(&texcoords[2]); cell_draw(&texcoords[3]); cell_draw(&texcoords[4]); cell_draw(&texcoords[5]); cell_draw(&texcoords[6]); cell_draw(&texcoords[7]); cell_draw(&vertices[0]); cell_draw(&vertices[1]); cell_draw(&vertices[2]); cell_draw(&vertices[3]); cell_draw(&vertices[4]); cell_draw(&vertices[5]); cell_draw(&vertices[6]); cell_draw(&vertices[7]); cell_draw(&vertices[8]); cell_draw(&vertices[9]); cell_draw(&vertices[10]); cell_draw(&vertices[11]); cell_draw(&pcolor[0]); cell_draw(&pcolor[1]); cell_draw(&pcolor[2]); cell_draw(&pcolor[3]); glColor3ub(255, 255, 255); } void matrix_display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3ub(255, 255, 255); polygon_display(); setfont("helvetica", 18); drawstr(10, translation[0].y-30, "glMatrixMode(GL_TEXTURE);"); drawstr(10, translation[0].y, "glTranslatef("); drawstr(170, translation[0].y, ","); drawstr(230, translation[0].y, ","); drawstr(290, translation[0].y, ");"); drawstr(30, rotation[0].y, "glRotatef("); drawstr(170, rotation[0].y, ","); drawstr(230, rotation[0].y, ","); drawstr(290, rotation[0].y, ","); drawstr(350, rotation[0].y, ");"); drawstr(38, scale[0].y, "glScalef("); drawstr(170, scale[0].y, ","); drawstr(230, scale[0].y, ","); drawstr(290, scale[0].y, ");"); drawstr(10, scale[0].y+30, "glMatrixMode(GL_MODELVIEW);"); cell_draw(&translation[0]); cell_draw(&translation[1]); cell_draw(&translation[2]); cell_draw(&rotation[0]); cell_draw(&rotation[1]); cell_draw(&rotation[2]); cell_draw(&rotation[3]); cell_draw(&scale[0]); cell_draw(&scale[1]); cell_draw(&scale[2]); if (!selection) { glColor3ub(255, 255, 0); drawstr(10, 525, "Click on the arguments and move the mouse to modify values."); } glutSwapBuffers(); } void parameters_display(void) { float pos[4]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3ub(255, 255, 255); polygon_display(); setfont("helvetica", 18); drawstr(10, bcolor[0].y, "GLfloat border_color[ ] = { "); drawstr(bcolor[0].x+40, bcolor[0].y, ","); drawstr(bcolor[1].x+40, bcolor[0].y, ","); drawstr(bcolor[2].x+40, bcolor[0].y, ","); drawstr(bcolor[3].x+40, bcolor[0].y, "};"); drawstr(10, ecolor[0].y, "GLfloat env_color[ ] = { "); drawstr(ecolor[0].x+40, ecolor[0].y, ","); drawstr(ecolor[1].x+40, ecolor[0].y, ","); drawstr(ecolor[2].x+40, ecolor[0].y, ","); drawstr(ecolor[3].x+40, ecolor[0].y, "};"); setfont("helvetica", 12); drawstr(10, 90, "glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR," " border_color);"); drawstr(10, 110, "glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, " "env_color);"); drawstr(10, 140, "glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,"); drawstr(10, 160, "glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,"); drawstr(10, 180, "glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,"); drawstr(10, 200, "glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,"); drawstr(10, 220, "glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,"); glColor3ub(0, 255, 128); if (minfilter == GL_LINEAR_MIPMAP_LINEAR) { drawstr(380, 140, "GL_LINEAR_MIPMAP_LINEAR"); } else if (minfilter == GL_LINEAR_MIPMAP_NEAREST) { drawstr(380, 140, "GL_LINEAR_MIPMAP_NEAREST"); } else if (minfilter == GL_NEAREST_MIPMAP_LINEAR) { drawstr(380, 140, "GL_NEAREST_MIPMAP_LINEAR"); } else if (minfilter == GL_NEAREST_MIPMAP_NEAREST) { drawstr(380, 140, "GL_NEAREST_MIPMAP_NEAREST"); } else if (minfilter == GL_LINEAR) { drawstr(380, 140, "GL_LINEAR"); } else { drawstr(380, 140, "GL_NEAREST"); } glColor3ub(255, 255, 255); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); drawstr(pos[0]+2, glutGet(GLUT_WINDOW_HEIGHT)-pos[1]-1, ");"); glColor3ub(0, 255, 128); if (magfilter == GL_LINEAR) { drawstr(390, 160, "GL_LINEAR"); } else { drawstr(390, 160, "GL_NEAREST"); } glColor3ub(255, 255, 255); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); drawstr(pos[0]+2, glutGet(GLUT_WINDOW_HEIGHT)-pos[1]-1, ");"); glColor3ub(0, 255, 128); if (wraps == GL_REPEAT) { drawstr(360, 180, "GL_REPEAT"); } else { drawstr(360, 180, "GL_CLAMP"); } glColor3ub(255, 255, 255); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); drawstr(pos[0]+2, glutGet(GLUT_WINDOW_HEIGHT)-pos[1]-1, ");"); glColor3ub(0, 255, 128); if (wrapt == GL_REPEAT) { drawstr(360, 200, "GL_REPEAT"); } else { drawstr(360, 200, "GL_CLAMP"); } glColor3ub(255, 255, 255); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); drawstr(pos[0]+2, glutGet(GLUT_WINDOW_HEIGHT)-pos[1]-1, ");"); glColor3ub(0, 255, 128); if (env == GL_MODULATE) { drawstr(360, 220, "GL_MODULATE"); } else if (env == GL_DECAL) { drawstr(360, 220, "GL_DECAL"); } else if (env == GL_BLEND) { drawstr(360, 220, "GL_BLEND"); } else { drawstr(360, 220, "GL_REPLACE"); } glColor3ub(255, 255, 255); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); drawstr(pos[0]+2, glutGet(GLUT_WINDOW_HEIGHT)-pos[1]-1, ");"); setfont("helvetica", 18); cell_draw(&bcolor[0]); cell_draw(&bcolor[1]); cell_draw(&bcolor[2]); cell_draw(&bcolor[3]); cell_draw(&ecolor[0]); cell_draw(&ecolor[1]); cell_draw(&ecolor[2]); cell_draw(&ecolor[3]); if (!selection) { glColor3ub(255, 255, 0); drawstr(10, 525, "Click on the arguments and move the mouse to modify values."); } glutSwapBuffers(); } void polygon_mouse(int x, int y) { /* mouse should only hit _one_ of the cells, so adding up all the hits just propagates a single hit. */ selection += cell_hit(&texcoords[0], x, y); selection += cell_hit(&texcoords[1], x, y); selection += cell_hit(&texcoords[2], x, y); selection += cell_hit(&texcoords[3], x, y); selection += cell_hit(&texcoords[4], x, y); selection += cell_hit(&texcoords[5], x, y); selection += cell_hit(&texcoords[6], x, y); selection += cell_hit(&texcoords[7], x, y); selection += cell_hit(&vertices[0], x, y); selection += cell_hit(&vertices[1], x, y); selection += cell_hit(&vertices[2], x, y); selection += cell_hit(&vertices[3], x, y); selection += cell_hit(&vertices[4], x, y); selection += cell_hit(&vertices[5], x, y); selection += cell_hit(&vertices[6], x, y); selection += cell_hit(&vertices[7], x, y); selection += cell_hit(&vertices[8], x, y); selection += cell_hit(&vertices[9], x, y); selection += cell_hit(&vertices[10], x, y); selection += cell_hit(&vertices[11], x, y); selection += cell_hit(&pcolor[0], x, y); selection += cell_hit(&pcolor[1], x, y); selection += cell_hit(&pcolor[2], x, y); selection += cell_hit(&pcolor[3], x, y); } void matrix_mouse(int button, int state, int x, int y) { selection = 0; if (state == GLUT_DOWN) { polygon_mouse(x, y); /* mouse should only hit _one_ of the cells, so adding up all the hits just propagates a single hit. */ selection += cell_hit(&translation[0], x, y); selection += cell_hit(&translation[1], x, y); selection += cell_hit(&translation[2], x, y); selection += cell_hit(&rotation[0], x, y); selection += cell_hit(&rotation[1], x, y); selection += cell_hit(&rotation[2], x, y); selection += cell_hit(&rotation[3], x, y); selection += cell_hit(&scale[0], x, y); selection += cell_hit(&scale[1], x, y); selection += cell_hit(&scale[2], x, y); } old_y = y; redisplay_all(); } void parameters_mouse(int button, int state, int x, int y) { selection = 0; if (state == GLUT_DOWN) { polygon_mouse(x, y); selection += cell_hit(&bcolor[0], x, y); selection += cell_hit(&bcolor[1], x, y); selection += cell_hit(&bcolor[2], x, y); selection += cell_hit(&bcolor[3], x, y); selection += cell_hit(&ecolor[0], x, y); selection += cell_hit(&ecolor[1], x, y); selection += cell_hit(&ecolor[2], x, y); selection += cell_hit(&ecolor[3], x, y); if (!selection) { if (y < 145 && y > 125) { if (minfilter == GL_NEAREST) minfilter = GL_LINEAR; else if (minfilter == GL_LINEAR) minfilter = GL_NEAREST_MIPMAP_NEAREST; else if (minfilter == GL_NEAREST_MIPMAP_NEAREST) minfilter = GL_NEAREST_MIPMAP_LINEAR; else if (minfilter == GL_NEAREST_MIPMAP_LINEAR) minfilter = GL_LINEAR_MIPMAP_NEAREST; else if (minfilter == GL_LINEAR_MIPMAP_NEAREST) minfilter = GL_LINEAR_MIPMAP_LINEAR; else minfilter = GL_NEAREST; } else if (y < 165 && y > 145) { if (magfilter == GL_NEAREST) magfilter = GL_LINEAR; else magfilter = GL_NEAREST; } else if (y < 185 && y > 165) { if (wraps == GL_REPEAT) wraps = GL_CLAMP; else wraps = GL_REPEAT; } else if (y < 205 && y > 185) { if (wrapt == GL_REPEAT) wrapt = GL_CLAMP; else wrapt = GL_REPEAT; } else if (y < 225 && y > 205) { if (env == GL_REPLACE_EXT) env = GL_DECAL; else if (env == GL_DECAL) env = GL_BLEND; else if (env == GL_BLEND) env = GL_MODULATE; else env = GL_REPLACE_EXT; } } } glutSetWindow(screen); texenv(); glutSetWindow(world); texenv(); old_y = y; redisplay_all(); } void command_motion(int x, int y) { cell_update(&translation[0], old_y-y); cell_update(&translation[1], old_y-y); cell_update(&translation[2], old_y-y); cell_update(&rotation[0], old_y-y); cell_update(&rotation[1], old_y-y); cell_update(&rotation[2], old_y-y); cell_update(&rotation[3], old_y-y); cell_update(&scale[0], old_y-y); cell_update(&scale[1], old_y-y); cell_update(&scale[2], old_y-y); cell_update(&texcoords[0], old_y-y); cell_update(&texcoords[1], old_y-y); cell_update(&texcoords[2], old_y-y); cell_update(&texcoords[3], old_y-y); cell_update(&texcoords[4], old_y-y); cell_update(&texcoords[5], old_y-y); cell_update(&texcoords[6], old_y-y); cell_update(&texcoords[7], old_y-y); cell_update(&vertices[0], old_y-y); cell_update(&vertices[1], old_y-y); cell_update(&vertices[2], old_y-y); cell_update(&vertices[3], old_y-y); cell_update(&vertices[4], old_y-y); cell_update(&vertices[5], old_y-y); cell_update(&vertices[6], old_y-y); cell_update(&vertices[7], old_y-y); cell_update(&vertices[8], old_y-y); cell_update(&vertices[9], old_y-y); cell_update(&vertices[10], old_y-y); cell_update(&vertices[11], old_y-y); cell_update(&pcolor[0], old_y-y); cell_update(&pcolor[1], old_y-y); cell_update(&pcolor[2], old_y-y); cell_update(&pcolor[3], old_y-y); cell_update(&bcolor[0], old_y-y); cell_update(&bcolor[1], old_y-y); cell_update(&bcolor[2], old_y-y); cell_update(&bcolor[3], old_y-y); cell_update(&ecolor[0], old_y-y); cell_update(&ecolor[1], old_y-y); cell_update(&ecolor[2], old_y-y); cell_update(&ecolor[3], old_y-y); glutSetWindow(screen); texenv(); glutSetWindow(world); texenv(); old_y = y; redisplay_all(); } void timer(int value) { stipple = 0x00ff << value; if (value > 8) stipple += 0x00ff >> (8-(value-8)); value++; if (value >= 16) value = 0; glutSetWindow(world); glutPostRedisplay(); glutTimerFunc(100, timer, value); } void redisplay_all(void) { glutSetWindow(command); glutPostRedisplay(); glutSetWindow(world); world_reshape(sub_width, sub_height); glutPostRedisplay(); glutSetWindow(screen); screen_reshape(sub_width, sub_height); glutPostRedisplay(); } void main_keyboard(unsigned char key, int x, int y) { switch (key) { case 'm': glutSetWindow(command); glutMouseFunc(matrix_mouse); glutDisplayFunc(matrix_display); break; case 'p': glutSetWindow(command); glutMouseFunc(parameters_mouse); glutDisplayFunc(parameters_display); break; case 'r': translation[0].value = 0.0; translation[1].value = 0.0; translation[2].value = 0.0; rotation[0].value = 0.0; rotation[1].value = 0.0; rotation[2].value = 0.0; rotation[3].value = 1.0; scale[0].value = 1.0; scale[1].value = 1.0; scale[2].value = 1.0; texcoords[0].value = 0.0; texcoords[1].value = 0.0; texcoords[2].value = 1.0; texcoords[3].value = 0.0; texcoords[4].value = 1.0; texcoords[5].value = 1.0; texcoords[6].value = 0.0; texcoords[7].value = 1.0; vertices[0].value = -1.0; vertices[1].value = -1.0; vertices[2].value = 0.0; vertices[3].value = 1.0; vertices[4].value = -1.0; vertices[5].value = 0.0; vertices[6].value = 1.0; vertices[7].value = 1.0; vertices[8].value = 0.0; vertices[9].value = -1.0; vertices[10].value = 1.0; vertices[11].value = 0.0; pcolor[0].value = 0.6; pcolor[1].value = 0.6; pcolor[2].value = 0.6; pcolor[3].value = 0.6; bcolor[0].value = 1.0; bcolor[1].value = 0.0; bcolor[2].value = 0.0; bcolor[3].value = 1.0; ecolor[0].value = 0.0; ecolor[1].value = 1.0; ecolor[2].value = 0.0; ecolor[3].value = 1.0; minfilter = GL_NEAREST; magfilter = GL_NEAREST; env = GL_MODULATE; wraps = GL_REPEAT; wrapt = GL_REPEAT; break; case 27: exit(0); } glutSetWindow(screen); texenv(); redisplay_all(); } void command_menu(int value) { main_keyboard((unsigned char)value, 0, 0); } int main(int argc, char** argv) { image = glmReadPPM("data/fishermen.ppm", &iwidth, &iheight); if (!image) exit(0); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize((512+GAP*3)*3/2, 512+GAP*3); glutInitWindowPosition(50, 50); glutInit(&argc, argv); window = glutCreateWindow("Texture"); glutReshapeFunc(main_reshape); glutDisplayFunc(main_display); glutKeyboardFunc(main_keyboard); world = glutCreateSubWindow(window, GAP, GAP, 256, 256); glutReshapeFunc(world_reshape); glutDisplayFunc(world_display); glutKeyboardFunc(main_keyboard); glutCreateMenu(world_menu); glutAddMenuEntry("Textures", 0); glutAddMenuEntry("", 0); glutAddMenuEntry("Fishermen", 'f'); glutAddMenuEntry("OpenGL Logo", 'o'); glutAddMenuEntry("Checker", 'c'); glutAddMenuEntry("Marble", 'm'); glutAddMenuEntry("Train", 't'); glutAttachMenu(GLUT_RIGHT_BUTTON); texture(); screen = glutCreateSubWindow(window, GAP+256+GAP, GAP, 256, 256); glutReshapeFunc(screen_reshape); glutDisplayFunc(screen_display); glutKeyboardFunc(main_keyboard); glutMotionFunc(screen_motion); glutMouseFunc(screen_mouse); texture(); command = glutCreateSubWindow(window, GAP+256+GAP, GAP+256+GAP, 256, 256); glutReshapeFunc(command_reshape); glutMotionFunc(command_motion); glutDisplayFunc(parameters_display); glutMouseFunc(parameters_mouse); glutKeyboardFunc(main_keyboard); glutCreateMenu(command_menu); glutAddMenuEntry("Texture", 0); glutAddMenuEntry("", 0); glutAddMenuEntry("Matrix", 'm'); glutAddMenuEntry("Environment/Parameters", 'p'); glutAddMenuEntry("Reset parameters (r)", 'r'); glutAddMenuEntry("", 0); glutAddMenuEntry("Quit", 27); glutAttachMenu(GLUT_RIGHT_BUTTON); redisplay_all(); glutTimerFunc(500, timer, 0); glutMainLoop(); return 0; }