Merge branch '7.8'
[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 #if 0 /* debug - test culling */
97 glCullFace(GL_BACK);
98 glFrontFace(GL_CW);
99 glEnable(GL_CULL_FACE);
100 #endif
101 }
102
103 static void Reshape(int width, int height)
104 {
105
106 windW = (GLint)width;
107 windH = (GLint)height;
108 }
109
110 static void Render(GLenum mode)
111 {
112 GLint i;
113
114 for (i = 0; i < objectCount; i++) {
115 if (mode == GL_SELECT) {
116 glLoadName(i);
117 }
118 glColor3fv(objects[i].color);
119 glBegin(GL_POLYGON);
120 glVertex2fv(objects[i].v1);
121 glVertex2fv(objects[i].v2);
122 glVertex2fv(objects[i].v3);
123 glEnd();
124 }
125 }
126
127 static GLint DoSelect(GLint x, GLint y)
128 {
129 GLint hits;
130
131 glSelectBuffer(MAXSELECT, selectBuf);
132 (void)glRenderMode(GL_SELECT);
133 glInitNames();
134 glPushName(~0);
135
136 glPushMatrix();
137
138 glViewport(0, 0, windW, windH);
139 glGetIntegerv(GL_VIEWPORT, vp);
140
141 glMatrixMode(GL_PROJECTION);
142 glLoadIdentity();
143 gluPickMatrix(x, windH-y, 4, 4, vp);
144 gluOrtho2D(-175, 175, -175, 175);
145 glMatrixMode(GL_MODELVIEW);
146
147 glClearColor(0.0, 0.0, 0.0, 0.0);
148 glClear(GL_COLOR_BUFFER_BIT);
149
150 glScalef(zoom, zoom, zoom);
151 glRotatef(zRotation, 0, 0, 1);
152
153 Render(GL_SELECT);
154
155 glPopMatrix();
156
157 hits = glRenderMode(GL_RENDER);
158 if (hits <= 0) {
159 return -1;
160 }
161
162 return selectBuf[(hits-1)*4+3];
163 }
164
165 static void RecolorTri(GLint h)
166 {
167
168 objects[h].color[0] = ((rand() % 100) + 50) / 150.0;
169 objects[h].color[1] = ((rand() % 100) + 50) / 150.0;
170 objects[h].color[2] = ((rand() % 100) + 50) / 150.0;
171 }
172
173 static void DeleteTri(GLint h)
174 {
175
176 objects[h] = objects[objectCount-1];
177 objectCount--;
178 }
179
180 static void GrowTri(GLint h)
181 {
182 float v[2];
183 float *oldV = NULL;
184 GLint i;
185
186 v[0] = objects[h].v1[0] + objects[h].v2[0] + objects[h].v3[0];
187 v[1] = objects[h].v1[1] + objects[h].v2[1] + objects[h].v3[1];
188 v[0] /= 3;
189 v[1] /= 3;
190
191 for (i = 0; i < 3; i++) {
192 switch (i) {
193 case 0:
194 oldV = objects[h].v1;
195 break;
196 case 1:
197 oldV = objects[h].v2;
198 break;
199 case 2:
200 oldV = objects[h].v3;
201 break;
202 }
203 oldV[0] = 1.5 * (oldV[0] - v[0]) + v[0];
204 oldV[1] = 1.5 * (oldV[1] - v[1]) + v[1];
205 }
206 }
207
208 static void Mouse(int button, int state, int mouseX, int mouseY)
209 {
210 GLint hit;
211
212 if (state != GLUT_DOWN)
213 return;
214
215 hit = DoSelect((GLint)mouseX, (GLint)mouseY);
216 if (hit != -1) {
217 if (button == GLUT_LEFT_BUTTON) {
218 RecolorTri(hit);
219 }
220 if (button == GLUT_MIDDLE_BUTTON) {
221 GrowTri(hit);
222 }
223 if (button == GLUT_RIGHT_BUTTON) {
224 DeleteTri(hit);
225 }
226 }
227
228 glutPostRedisplay();
229 }
230
231 static void Draw(void)
232 {
233
234 glPushMatrix();
235
236 glViewport(0, 0, windW, windH);
237 glGetIntegerv(GL_VIEWPORT, vp);
238
239 glMatrixMode(GL_PROJECTION);
240 glLoadIdentity();
241 gluOrtho2D(-175, 175, -175, 175);
242 glMatrixMode(GL_MODELVIEW);
243
244 glClearColor(0.0, 0.0, 0.0, 0.0);
245 glClear(GL_COLOR_BUFFER_BIT);
246
247 glScalef(zoom, zoom, zoom);
248 glRotatef(zRotation, 0, 0, 1);
249
250 Render(GL_RENDER);
251
252 glPopMatrix();
253
254 glFlush();
255 }
256
257 static void DrawZoom(GLint x, GLint y)
258 {
259
260 glPushMatrix();
261
262 glViewport(0, 0, windW, windH);
263 glGetIntegerv(GL_VIEWPORT, vp);
264
265 glMatrixMode(GL_PROJECTION);
266 glLoadIdentity();
267 gluPickMatrix(x, windH-y, 4, 4, vp);
268 gluOrtho2D(-175, 175, -175, 175);
269 glMatrixMode(GL_MODELVIEW);
270
271 glClearColor(0.0, 0.0, 0.0, 0.0);
272 glClear(GL_COLOR_BUFFER_BIT);
273
274 glScalef(zoom, zoom, zoom);
275 glRotatef(zRotation, 0, 0, 1);
276
277 Render(GL_RENDER);
278
279 glPopMatrix();
280 }
281
282 static void DumpFeedbackVert(GLint *i, GLint n)
283 {
284 GLint index;
285
286 index = *i;
287 if (index+7 > n) {
288 *i = n;
289 printf(" ???\n");
290 return;
291 }
292 printf(" (%g %g %g), color = (%4.2f %4.2f %4.2f)\n",
293 feedBuf[index],
294 feedBuf[index+1],
295 feedBuf[index+2],
296 feedBuf[index+3],
297 feedBuf[index+4],
298 feedBuf[index+5]);
299 index += 7;
300 *i = index;
301 }
302
303 static void DrawFeedback(GLint n)
304 {
305 GLint i;
306 GLint verts;
307
308 printf("Feedback results (%d floats):\n", n);
309 for (i = 0; i < n; i++) {
310 switch ((GLint)feedBuf[i]) {
311 case GL_POLYGON_TOKEN:
312 printf("Polygon");
313 i++;
314 if (i < n) {
315 verts = (GLint)feedBuf[i];
316 i++;
317 printf(": %d vertices", verts);
318 } else {
319 verts = 0;
320 }
321 printf("\n");
322 while (verts) {
323 DumpFeedbackVert(&i, n);
324 verts--;
325 }
326 i--;
327 break;
328 case GL_LINE_TOKEN:
329 printf("Line:\n");
330 i++;
331 DumpFeedbackVert(&i, n);
332 DumpFeedbackVert(&i, n);
333 i--;
334 break;
335 case GL_LINE_RESET_TOKEN:
336 printf("Line Reset:\n");
337 i++;
338 DumpFeedbackVert(&i, n);
339 DumpFeedbackVert(&i, n);
340 i--;
341 break;
342 default:
343 printf("%9.2f\n", feedBuf[i]);
344 break;
345 }
346 }
347 if (i == MAXFEED) {
348 printf("...\n");
349 }
350 printf("\n");
351 }
352
353 static void DoFeedback(void)
354 {
355 GLint x;
356
357 glFeedbackBuffer(MAXFEED, GL_3D_COLOR, feedBuf);
358 (void)glRenderMode(GL_FEEDBACK);
359
360 glPushMatrix();
361
362 glViewport(0, 0, windW, windH);
363 glGetIntegerv(GL_VIEWPORT, vp);
364
365 glMatrixMode(GL_PROJECTION);
366 glLoadIdentity();
367 gluOrtho2D(-175, 175, -175, 175);
368 glMatrixMode(GL_MODELVIEW);
369
370 glClearColor(0.0, 0.0, 0.0, 0.0);
371 glClear(GL_COLOR_BUFFER_BIT);
372
373 glScalef(zoom, zoom, zoom);
374 glRotatef(zRotation, 0, 0, 1);
375
376 Render(GL_FEEDBACK);
377
378 glPopMatrix();
379
380 x = glRenderMode(GL_RENDER);
381 if (x == -1) {
382 x = MAXFEED;
383 }
384
385 DrawFeedback((GLint)x);
386 }
387
388 static void Key2(int key, int x, int y)
389 {
390 switch (key) {
391 case GLUT_KEY_LEFT:
392 zRotation += 0.5;
393 break;
394 case GLUT_KEY_RIGHT:
395 zRotation -= 0.5;
396 break;
397 default:
398 return;
399 }
400
401 glutPostRedisplay();
402 }
403
404 static void Key(unsigned char key, int x, int y)
405 {
406 switch (key) {
407 case 27:
408 exit(1);
409 case 'Z':
410 zoom /= 0.75;
411 break;
412 case 'z':
413 zoom *= 0.75;
414 break;
415 case 'f':
416 DoFeedback();
417 break;
418 case 'd':
419 DrawZoom(x, y);
420 break;
421 case 'l':
422 linePoly = !linePoly;
423 if (linePoly) {
424 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
425 } else {
426 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
427 }
428 break;
429 default:
430 return;
431 }
432
433 glutPostRedisplay();
434 }
435
436 int main(int argc, char **argv)
437 {
438 GLenum type;
439
440 glutInit(&argc, argv);
441
442 windW = 300;
443 windH = 300;
444 glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH);
445
446 type = GLUT_RGB | GLUT_SINGLE;
447 glutInitDisplayMode(type);
448
449 if (glutCreateWindow("Select Test") == GL_FALSE) {
450 exit(1);
451 }
452
453 Init();
454
455 glutReshapeFunc(Reshape);
456 glutKeyboardFunc(Key);
457 glutSpecialFunc(Key2);
458 glutMouseFunc(Mouse);
459 glutDisplayFunc(Draw);
460 glutMainLoop();
461 return 0;
462 }