/** * Test rubber-band selection box w/ logicops and blend. */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <GL/glew.h> #include <GL/glut.h> #include "readtex.c" #define IMAGE_FILE "../images/arch.rgb" static int ImgWidth, ImgHeight; static GLenum ImgFormat; static GLubyte *Image = NULL; static int Win; static int Width = 512, Height = 512; struct rect { int x0, y0, x1, y1; }; static struct rect OldRect, NewRect; static GLboolean ButtonDown = GL_FALSE; static GLboolean LogicOp = 0*GL_TRUE; static GLboolean RedrawBackground = GL_TRUE; static const GLfloat red[4] = {1.0, 0.2, 0.2, 1.0}; static const GLfloat green[4] = {0.2, 1.0, 0.2, 1.0}; static const GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; /* * Draw rubberband box in front buffer */ static void DrawRect(const struct rect *r) { glDrawBuffer(GL_FRONT); if (LogicOp) { glLogicOp(GL_XOR); glEnable(GL_COLOR_LOGIC_OP); } else { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); } glColor3f(1, 1, 1); glLineWidth(3.0); glBegin(GL_LINE_LOOP); glVertex2i(r->x0, r->y0); glVertex2i(r->x1, r->y0); glVertex2i(r->x1, r->y1); glVertex2i(r->x0, r->y1); glEnd(); glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_BLEND); glDrawBuffer(GL_BACK); } static void PrintString(const char *s) { while (*s) { glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); s++; } } static void DrawBackground(void) { char s[100]; sprintf(s, "[L/B] %s mode. Use mouse to make selection box.", LogicOp ? "LogicOp" : "Blend"); glClear(GL_COLOR_BUFFER_BIT); glWindowPos2i((Width - ImgWidth) / 2, (Height - ImgHeight) / 2); glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image); glWindowPos2i(10, 10); PrintString(s); glutSwapBuffers(); } static void Draw(void) { if (RedrawBackground) { DrawBackground(); } if (ButtonDown) { if (!RedrawBackground) DrawRect(&OldRect); /* erase old */ DrawRect(&NewRect); /* draw new */ OldRect = NewRect; } RedrawBackground = GL_FALSE; } static void Reshape(int width, int height) { Width = width; Height = height; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, Width, Height, 0, -1, 1); /* Inverted Y! */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); RedrawBackground = GL_TRUE; } static void Key(unsigned char key, int x, int y) { (void) x; (void) y; switch (key) { case 'b': case 'B': LogicOp = GL_FALSE; break; case 'l': case 'L': LogicOp = GL_TRUE; break; case 27: glutDestroyWindow(Win); exit(0); break; } RedrawBackground = GL_TRUE; glutPostRedisplay(); } static void SpecialKey(int key, int x, int y) { (void) x; (void) y; switch (key) { case GLUT_KEY_UP: break; case GLUT_KEY_DOWN: break; case GLUT_KEY_LEFT: break; case GLUT_KEY_RIGHT: break; } glutPostRedisplay(); } static void MouseMotion(int x, int y) { if (ButtonDown) { NewRect.x1 = x; NewRect.y1 = y; glutPostRedisplay(); } } static void MouseButton(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { ButtonDown = GL_TRUE; RedrawBackground = GL_TRUE; NewRect.x0 = NewRect.x1 = x; NewRect.y0 = NewRect.y1 = y; OldRect = NewRect; } else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { ButtonDown = GL_FALSE; } glutPostRedisplay(); } static void Init(void) { Image = LoadRGBImage(IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat); if (!Image) { printf("Couldn't read %s\n", IMAGE_FILE); exit(0); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitWindowSize(Width, Height); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); Win = glutCreateWindow(argv[0]); glewInit(); glutReshapeFunc(Reshape); glutKeyboardFunc(Key); glutSpecialFunc(SpecialKey); glutMotionFunc(MouseMotion); glutMouseFunc(MouseButton); glutDisplayFunc(Draw); Init(); glutPostRedisplay(); glutMainLoop(); return 0; }