Initial revision
[mesa.git] / progs / samples / select.c
1 /*
2 * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that (i) the above copyright notices and this permission notice appear in
7 * all copies of the software and related documentation, and (ii) the name of
8 * Silicon Graphics may not be used in any advertising or
9 * publicity relating to the software without the specific, prior written
10 * permission of Silicon Graphics.
11 *
12 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
13 * ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #include <string.h>
29 #include <time.h>
30 #include <GL/glut.h>
31
32
33 #define MAXOBJS 10000
34 #define MAXSELECT 100
35 #define MAXFEED 300
36 #define SOLID 1
37 #define LINE 2
38 #define POINT 3
39
40
41 GLint windW, windH;
42
43 GLuint selectBuf[MAXSELECT];
44 GLfloat feedBuf[MAXFEED];
45 GLint vp[4];
46 float zRotation = 90.0;
47 float zoom = 1.0;
48 GLint objectCount;
49 GLint numObjects;
50 struct object {
51 float v1[2];
52 float v2[2];
53 float v3[2];
54 float color[3];
55 } objects[MAXOBJS];
56 GLenum linePoly = GL_FALSE;
57
58
59 static void InitObjects(GLint num)
60 {
61 GLint i;
62 float x, y;
63
64 if (num > MAXOBJS) {
65 num = MAXOBJS;
66 }
67 if (num < 1) {
68 num = 1;
69 }
70 objectCount = num;
71
72 srand((unsigned int)time(NULL));
73 for (i = 0; i < num; i++) {
74 x = (rand() % 300) - 150;
75 y = (rand() % 300) - 150;
76
77 objects[i].v1[0] = x + (rand() % 50) - 25;
78 objects[i].v2[0] = x + (rand() % 50) - 25;
79 objects[i].v3[0] = x + (rand() % 50) - 25;
80 objects[i].v1[1] = y + (rand() % 50) - 25;
81 objects[i].v2[1] = y + (rand() % 50) - 25;
82 objects[i].v3[1] = y + (rand() % 50) - 25;
83 objects[i].color[0] = ((rand() % 100) + 50) / 150.0;
84 objects[i].color[1] = ((rand() % 100) + 50) / 150.0;
85 objects[i].color[2] = ((rand() % 100) + 50) / 150.0;
86 }
87 }
88
89 static void Init(void)
90 {
91
92 numObjects = 10;
93 InitObjects(numObjects);
94 glGetIntegerv(GL_VIEWPORT, vp);
95 }
96
97 static void Reshape(int width, int height)
98 {
99
100 windW = (GLint)width;
101 windH = (GLint)height;
102 }
103
104 static void Render(GLenum mode)
105 {
106 GLint i;
107
108 for (i = 0; i < objectCount; i++) {
109 if (mode == GL_SELECT) {
110 glLoadName(i);
111 }
112 glColor3fv(objects[i].color);
113 glBegin(GL_POLYGON);
114 glVertex2fv(objects[i].v1);
115 glVertex2fv(objects[i].v2);
116 glVertex2fv(objects[i].v3);
117 glEnd();
118 }
119 }
120
121 static GLint DoSelect(GLint x, GLint y)
122 {
123 GLint hits;
124
125 glSelectBuffer(MAXSELECT, selectBuf);
126 (void)glRenderMode(GL_SELECT);
127 glInitNames();
128 glPushName(~0);
129
130 glPushMatrix();
131
132 glViewport(0, 0, windW, windH);
133 glGetIntegerv(GL_VIEWPORT, vp);
134
135 glMatrixMode(GL_PROJECTION);
136 glLoadIdentity();
137 gluPickMatrix(x, windH-y, 4, 4, vp);
138 gluOrtho2D(-175, 175, -175, 175);
139 glMatrixMode(GL_MODELVIEW);
140
141 glClearColor(0.0, 0.0, 0.0, 0.0);
142 glClear(GL_COLOR_BUFFER_BIT);
143
144 glScalef(zoom, zoom, zoom);
145 glRotatef(zRotation, 0, 0, 1);
146
147 Render(GL_SELECT);
148
149 glPopMatrix();
150
151 hits = glRenderMode(GL_RENDER);
152 if (hits <= 0) {
153 return -1;
154 }
155
156 return selectBuf[(hits-1)*4+3];
157 }
158
159 static void RecolorTri(GLint h)
160 {
161
162 objects[h].color[0] = ((rand() % 100) + 50) / 150.0;
163 objects[h].color[1] = ((rand() % 100) + 50) / 150.0;
164 objects[h].color[2] = ((rand() % 100) + 50) / 150.0;
165 }
166
167 static void DeleteTri(GLint h)
168 {
169
170 objects[h] = objects[objectCount-1];
171 objectCount--;
172 }
173
174 static void GrowTri(GLint h)
175 {
176 float v[2];
177 float *oldV;
178 GLint i;
179
180 v[0] = objects[h].v1[0] + objects[h].v2[0] + objects[h].v3[0];
181 v[1] = objects[h].v1[1] + objects[h].v2[1] + objects[h].v3[1];
182 v[0] /= 3;
183 v[1] /= 3;
184
185 for (i = 0; i < 3; i++) {
186 switch (i) {
187 case 0:
188 oldV = objects[h].v1;
189 break;
190 case 1:
191 oldV = objects[h].v2;
192 break;
193 case 2:
194 oldV = objects[h].v3;
195 break;
196 }
197 oldV[0] = 1.5 * (oldV[0] - v[0]) + v[0];
198 oldV[1] = 1.5 * (oldV[1] - v[1]) + v[1];
199 }
200 }
201
202 static void Mouse(int button, int state, int mouseX, int mouseY)
203 {
204 GLint hit;
205
206 if (state != GLUT_DOWN)
207 return;
208
209 hit = DoSelect((GLint)mouseX, (GLint)mouseY);
210 if (hit != -1) {
211 if (button == GLUT_LEFT_BUTTON) {
212 RecolorTri(hit);
213 }
214 if (button == GLUT_MIDDLE_BUTTON) {
215 GrowTri(hit);
216 }
217 if (button == GLUT_RIGHT_BUTTON) {
218 DeleteTri(hit);
219 }
220 }
221
222 glutPostRedisplay();
223 }
224
225 static void Draw(void)
226 {
227
228 glPushMatrix();
229
230 glViewport(0, 0, windW, windH);
231 glGetIntegerv(GL_VIEWPORT, vp);
232
233 glMatrixMode(GL_PROJECTION);
234 glLoadIdentity();
235 gluOrtho2D(-175, 175, -175, 175);
236 glMatrixMode(GL_MODELVIEW);
237
238 glClearColor(0.0, 0.0, 0.0, 0.0);
239 glClear(GL_COLOR_BUFFER_BIT);
240
241 glScalef(zoom, zoom, zoom);
242 glRotatef(zRotation, 0, 0, 1);
243
244 Render(GL_RENDER);
245
246 glPopMatrix();
247
248 glFlush();
249 }
250
251 static void DrawZoom(GLint x, GLint y)
252 {
253
254 glPushMatrix();
255
256 glViewport(0, 0, windW, windH);
257 glGetIntegerv(GL_VIEWPORT, vp);
258
259 glMatrixMode(GL_PROJECTION);
260 glLoadIdentity();
261 gluPickMatrix(x, windH-y, 4, 4, vp);
262 gluOrtho2D(-175, 175, -175, 175);
263 glMatrixMode(GL_MODELVIEW);
264
265 glClearColor(0.0, 0.0, 0.0, 0.0);
266 glClear(GL_COLOR_BUFFER_BIT);
267
268 glScalef(zoom, zoom, zoom);
269 glRotatef(zRotation, 0, 0, 1);
270
271 Render(GL_RENDER);
272
273 glPopMatrix();
274 }
275
276 static void DumpFeedbackVert(GLint *i, GLint n)
277 {
278 GLint index;
279
280 index = *i;
281 if (index+7 > n) {
282 *i = n;
283 printf(" ???\n");
284 return;
285 }
286 printf(" (%g %g %g), color = (%4.2f %4.2f %4.2f)\n",
287 feedBuf[index],
288 feedBuf[index+1],
289 feedBuf[index+2],
290 feedBuf[index+3],
291 feedBuf[index+4],
292 feedBuf[index+5]);
293 index += 7;
294 *i = index;
295 }
296
297 static void DrawFeedback(GLint n)
298 {
299 GLint i;
300 GLint verts;
301
302 printf("Feedback results (%d floats):\n", n);
303 for (i = 0; i < n; i++) {
304 switch ((GLint)feedBuf[i]) {
305 case GL_POLYGON_TOKEN:
306 printf("Polygon");
307 i++;
308 if (i < n) {
309 verts = (GLint)feedBuf[i];
310 i++;
311 printf(": %d vertices", verts);
312 } else {
313 verts = 0;
314 }
315 printf("\n");
316 while (verts) {
317 DumpFeedbackVert(&i, n);
318 verts--;
319 }
320 i--;
321 break;
322 case GL_LINE_TOKEN:
323 printf("Line:\n");
324 i++;
325 DumpFeedbackVert(&i, n);
326 DumpFeedbackVert(&i, n);
327 i--;
328 break;
329 case GL_LINE_RESET_TOKEN:
330 printf("Line Reset:\n");
331 i++;
332 DumpFeedbackVert(&i, n);
333 DumpFeedbackVert(&i, n);
334 i--;
335 break;
336 default:
337 printf("%9.2f\n", feedBuf[i]);
338 break;
339 }
340 }
341 if (i == MAXFEED) {
342 printf("...\n");
343 }
344 printf("\n");
345 }
346
347 static void DoFeedback(void)
348 {
349 GLint x;
350
351 glFeedbackBuffer(MAXFEED, GL_3D_COLOR, feedBuf);
352 (void)glRenderMode(GL_FEEDBACK);
353
354 glPushMatrix();
355
356 glViewport(0, 0, windW, windH);
357 glGetIntegerv(GL_VIEWPORT, vp);
358
359 glMatrixMode(GL_PROJECTION);
360 glLoadIdentity();
361 gluOrtho2D(-175, 175, -175, 175);
362 glMatrixMode(GL_MODELVIEW);
363
364 glClearColor(0.0, 0.0, 0.0, 0.0);
365 glClear(GL_COLOR_BUFFER_BIT);
366
367 glScalef(zoom, zoom, zoom);
368 glRotatef(zRotation, 0, 0, 1);
369
370 Render(GL_FEEDBACK);
371
372 glPopMatrix();
373
374 x = glRenderMode(GL_RENDER);
375 if (x == -1) {
376 x = MAXFEED;
377 }
378
379 DrawFeedback((GLint)x);
380 }
381
382 static void Key2(int key, int x, int y)
383 {
384 switch (key) {
385 case GLUT_KEY_LEFT:
386 zRotation += 0.5;
387 break;
388 case GLUT_KEY_RIGHT:
389 zRotation -= 0.5;
390 break;
391 default:
392 return;
393 }
394
395 glutPostRedisplay();
396 }
397
398 static void Key(unsigned char key, int x, int y)
399 {
400 switch (key) {
401 case 27:
402 exit(1);
403 case 'Z':
404 zoom /= 0.75;
405 break;
406 case 'z':
407 zoom *= 0.75;
408 break;
409 case 'f':
410 DoFeedback();
411 break;
412 case 'd':
413 DrawZoom(x, y);
414 break;
415 case 'l':
416 linePoly = !linePoly;
417 if (linePoly) {
418 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
419 } else {
420 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
421 }
422 break;
423 default:
424 return;
425 }
426
427 glutPostRedisplay();
428 }
429
430 int main(int argc, char **argv)
431 {
432 GLenum type;
433
434 glutInit(&argc, argv);
435
436 windW = 300;
437 windH = 300;
438 glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH);
439
440 type = GLUT_RGB | GLUT_SINGLE;
441 glutInitDisplayMode(type);
442
443 if (glutCreateWindow("Select Test") == GL_FALSE) {
444 exit(1);
445 }
446
447 Init();
448
449 glutReshapeFunc(Reshape);
450 glutKeyboardFunc(Key);
451 glutSpecialFunc(Key2);
452 glutMouseFunc(Mouse);
453 glutDisplayFunc(Draw);
454 glutMainLoop();
455 return 0;
456 }