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