rubberband.c revision 32001f49
1/**
2 * Test rubber-band selection box w/ logicops and blend.
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <math.h>
8#include <GL/glew.h>
9#include "glut_wrap.h"
10#include "readtex.c"
11
12#define IMAGE_FILE DEMOS_DATA_DIR "arch.rgb"
13
14static int ImgWidth, ImgHeight;
15static GLenum ImgFormat;
16static GLubyte *Image = NULL;
17
18static int Win;
19static int Width = 512, Height = 512;
20
21struct rect
22{
23   int x0, y0, x1, y1;
24};
25
26static struct rect OldRect, NewRect;
27
28static GLboolean ButtonDown = GL_FALSE;
29static GLboolean LogicOp = 0*GL_TRUE;
30
31static GLboolean RedrawBackground = GL_TRUE;
32
33static const GLfloat red[4] = {1.0, 0.2, 0.2, 1.0};
34static const GLfloat green[4] = {0.2, 1.0, 0.2, 1.0};
35static const GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
36
37
38/*
39 * Draw rubberband box in front buffer
40 */
41static void
42DrawRect(const struct rect *r)
43{
44   glDrawBuffer(GL_FRONT);
45
46   if (LogicOp) {
47      glLogicOp(GL_XOR);
48      glEnable(GL_COLOR_LOGIC_OP);
49   }
50   else {
51      glEnable(GL_BLEND);
52      glBlendFunc(GL_ONE, GL_ONE);
53      glBlendEquation(GL_FUNC_SUBTRACT);
54   }
55
56   glColor3f(1, 1, 1);
57
58   glLineWidth(3.0);
59
60   glBegin(GL_LINE_LOOP);
61   glVertex2i(r->x0, r->y0);
62   glVertex2i(r->x1, r->y0);
63   glVertex2i(r->x1, r->y1);
64   glVertex2i(r->x0, r->y1);
65   glEnd();
66
67   glDisable(GL_COLOR_LOGIC_OP);
68   glDisable(GL_BLEND);
69
70   /* Need this to ensure the front buffer drawing is actually displayed */
71   glFlush();
72
73   glDrawBuffer(GL_BACK);
74}
75
76
77static void
78PrintString(const char *s)
79{
80   while (*s) {
81      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
82      s++;
83   }
84}
85
86
87static void
88DrawBackground(void)
89{
90   char s[100];
91
92   sprintf(s, "[L/B] %s mode.   Use mouse to make selection box.",
93               LogicOp ? "LogicOp" : "Blend");
94
95   glClear(GL_COLOR_BUFFER_BIT);
96
97   glWindowPos2i((Width - ImgWidth) / 2, (Height - ImgHeight) / 2);
98   glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image);
99
100   glWindowPos2i(10, 10);
101   PrintString(s);
102
103   glutSwapBuffers();
104}
105
106
107static void
108Draw(void)
109{
110   if (RedrawBackground) {
111      DrawBackground();
112   }
113
114   if (ButtonDown) {
115      if (!RedrawBackground)
116         DrawRect(&OldRect); /* erase old */
117
118      DrawRect(&NewRect); /* draw new */
119
120      OldRect = NewRect;
121   }
122
123   RedrawBackground = GL_FALSE;
124}
125
126
127static void
128Reshape(int width, int height)
129{
130   Width = width;
131   Height = height;
132
133   glViewport(0, 0, width, height);
134
135   glMatrixMode(GL_PROJECTION);
136   glLoadIdentity();
137   glOrtho(0, Width, Height, 0, -1, 1); /* Inverted Y! */
138
139   glMatrixMode(GL_MODELVIEW);
140   glLoadIdentity();
141
142   RedrawBackground = GL_TRUE;
143}
144
145
146static void
147Key(unsigned char key, int x, int y)
148{
149   (void) x;
150   (void) y;
151   switch (key) {
152   case 'b':
153   case 'B':
154      LogicOp = GL_FALSE;
155      break;
156   case 'l':
157   case 'L':
158      LogicOp = GL_TRUE;
159      break;
160   case 27:
161      glutDestroyWindow(Win);
162      exit(0);
163      break;
164   }
165   RedrawBackground = GL_TRUE;
166   glutPostRedisplay();
167}
168
169
170static void
171SpecialKey(int key, int x, int y)
172{
173   (void) x;
174   (void) y;
175   switch (key) {
176   case GLUT_KEY_UP:
177      break;
178   case GLUT_KEY_DOWN:
179      break;
180   case GLUT_KEY_LEFT:
181      break;
182   case GLUT_KEY_RIGHT:
183      break;
184   }
185   glutPostRedisplay();
186}
187
188
189static void
190MouseMotion(int x, int y)
191{
192   if (ButtonDown) {
193      NewRect.x1 = x;
194      NewRect.y1 = y;
195      glutPostRedisplay();
196   }
197}
198
199
200static void
201MouseButton(int button, int state, int x, int y)
202{
203  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
204     ButtonDown = GL_TRUE;
205     RedrawBackground = GL_TRUE;
206     NewRect.x0 = NewRect.x1 = x;
207     NewRect.y0 = NewRect.y1 = y;
208     OldRect = NewRect;
209  }
210  else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
211     ButtonDown = GL_FALSE;
212  }
213  glutPostRedisplay();
214}
215
216
217static void
218Init(void)
219{
220   Image = LoadRGBImage(IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat);
221   if (!Image) {
222      printf("Couldn't read %s\n", IMAGE_FILE);
223      exit(0);
224   }
225
226   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
227   glPixelStorei(GL_PACK_ALIGNMENT, 1);
228}
229
230
231int
232main(int argc, char *argv[])
233{
234   glutInit(&argc, argv);
235   glutInitWindowSize(Width, Height);
236   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
237   Win = glutCreateWindow(argv[0]);
238   glewInit();
239   glutReshapeFunc(Reshape);
240   glutKeyboardFunc(Key);
241   glutSpecialFunc(SpecialKey);
242   glutMotionFunc(MouseMotion);
243   glutMouseFunc(MouseButton);
244   glutDisplayFunc(Draw);
245   Init();
246   glutPostRedisplay();
247   glutMainLoop();
248   return 0;
249}
250