reverted to old tessellator
[mesa.git] / progs / demos / tessdemo.c
1 /* $Id: tessdemo.c,v 1.8 2000/07/11 14:11:58 brianp Exp $ */
2
3 /*
4 * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
5 */
6
7
8 #include <GL/glut.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #define MAX_POINTS 200
14 #define MAX_CONTOURS 50
15
16 static int menu;
17 typedef enum
18 { QUIT, TESSELATE, CLEAR }
19 menu_entries;
20
21 typedef enum
22 { DEFINE, TESSELATED }
23 mode_type;
24
25 struct
26 {
27 GLint p[MAX_POINTS][2];
28 GLuint point_cnt;
29 }
30 contours[MAX_CONTOURS];
31
32 static GLuint contour_cnt;
33 static GLsizei width, height;
34 static mode_type mode;
35
36 struct
37 {
38 GLsizei no;
39 GLfloat color[3];
40 GLint p[3][2];
41 GLclampf p_color[3][3];
42 }
43 triangle;
44
45
46 static void GLCALLBACK
47 my_error(GLenum err)
48 {
49 int len, i;
50 char const *str;
51
52 glColor3f(0.9, 0.9, 0.9);
53 glRasterPos2i(5, 5);
54 str = (const char *) gluErrorString(err);
55 len = strlen(str);
56 for (i = 0; i < len; i++)
57 glutBitmapCharacter(GLUT_BITMAP_9_BY_15, str[i]);
58 }
59
60
61 static void GLCALLBACK
62 begin_callback(GLenum mode)
63 {
64 triangle.no = 0;
65 }
66
67
68 static void GLCALLBACK
69 edge_callback(GLenum flag)
70 {
71 if (flag == GL_TRUE) {
72 triangle.color[0] = 1.0;
73 triangle.color[1] = 1.0;
74 triangle.color[2] = 0.5;
75 }
76 else {
77 triangle.color[0] = 1.0;
78 triangle.color[1] = 0.0;
79 triangle.color[2] = 0.0;
80 }
81 }
82
83
84 static void GLCALLBACK
85 end_callback()
86 {
87 glBegin(GL_LINES);
88 glColor3f(triangle.p_color[0][0], triangle.p_color[0][1],
89 triangle.p_color[0][2]);
90 glVertex2i(triangle.p[0][0], triangle.p[0][1]);
91 glVertex2i(triangle.p[1][0], triangle.p[1][1]);
92 glColor3f(triangle.p_color[1][0], triangle.p_color[1][1],
93 triangle.p_color[1][2]);
94 glVertex2i(triangle.p[1][0], triangle.p[1][1]);
95 glVertex2i(triangle.p[2][0], triangle.p[2][1]);
96 glColor3f(triangle.p_color[2][0], triangle.p_color[2][1],
97 triangle.p_color[2][2]);
98 glVertex2i(triangle.p[2][0], triangle.p[2][1]);
99 glVertex2i(triangle.p[0][0], triangle.p[0][1]);
100 glEnd();
101 }
102
103
104 static void GLCALLBACK
105 vertex_callback(void *data)
106 {
107 GLsizei no;
108 GLint *p;
109
110 p = (GLint *) data;
111 no = triangle.no;
112 triangle.p[no][0] = p[0];
113 triangle.p[no][1] = p[1];
114 triangle.p_color[no][0] = triangle.color[0];
115 triangle.p_color[no][1] = triangle.color[1];
116 triangle.p_color[no][2] = triangle.color[2];
117 ++(triangle.no);
118 }
119
120
121 static void
122 set_screen_wh(GLsizei w, GLsizei h)
123 {
124 width = w;
125 height = h;
126 }
127
128
129 static void
130 tesse(void)
131 {
132 GLUtriangulatorObj *tobj;
133 GLdouble data[3];
134 GLuint i, j, point_cnt;
135
136 tobj = gluNewTess();
137 if (tobj != NULL) {
138 glClear(GL_COLOR_BUFFER_BIT);
139 glColor3f(0.7, 0.7, 0.0);
140 gluTessCallback(tobj, GLU_BEGIN, glBegin);
141 gluTessCallback(tobj, GLU_END, glEnd);
142 gluTessCallback(tobj, GLU_ERROR, my_error);
143 gluTessCallback(tobj, GLU_VERTEX, glVertex2iv);
144 gluBeginPolygon(tobj);
145 for (j = 0; j <= contour_cnt; j++) {
146 point_cnt = contours[j].point_cnt;
147 gluNextContour(tobj, GLU_UNKNOWN);
148 for (i = 0; i < point_cnt; i++) {
149 data[0] = (GLdouble) (contours[j].p[i][0]);
150 data[1] = (GLdouble) (contours[j].p[i][1]);
151 data[2] = 0.0;
152 gluTessVertex(tobj, data, contours[j].p[i]);
153 }
154 }
155 gluEndPolygon(tobj);
156 glLineWidth(2.0);
157 gluTessCallback(tobj, GLU_BEGIN, begin_callback);
158 gluTessCallback(tobj, GLU_END, end_callback);
159 gluTessCallback(tobj, GLU_VERTEX, vertex_callback);
160 gluTessCallback(tobj, GLU_EDGE_FLAG, edge_callback);
161 gluBeginPolygon(tobj);
162 for (j = 0; j <= contour_cnt; j++) {
163 point_cnt = contours[j].point_cnt;
164 gluNextContour(tobj, GLU_UNKNOWN);
165 for (i = 0; i < point_cnt; i++) {
166 data[0] = (GLdouble) (contours[j].p[i][0]);
167 data[1] = (GLdouble) (contours[j].p[i][1]);
168 data[2] = 0.0;
169 gluTessVertex(tobj, data, contours[j].p[i]);
170 }
171 }
172 gluEndPolygon(tobj);
173 gluDeleteTess(tobj);
174 glutMouseFunc(NULL);
175 glColor3f(1.0, 1.0, 0.0);
176 glLineWidth(1.0);
177 mode = TESSELATED;
178 }
179 }
180
181
182 static void
183 left_down(int x1, int y1)
184 {
185 GLint P[2];
186 GLuint point_cnt;
187
188 /* translate GLUT into GL coordinates */
189 P[0] = x1;
190 P[1] = height - y1;
191 point_cnt = contours[contour_cnt].point_cnt;
192 contours[contour_cnt].p[point_cnt][0] = P[0];
193 contours[contour_cnt].p[point_cnt][1] = P[1];
194 glBegin(GL_LINES);
195 if (point_cnt) {
196 glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
197 glVertex2iv(P);
198 }
199 else {
200 glVertex2iv(P);
201 glVertex2iv(P);
202 }
203 glEnd();
204 glFinish();
205 ++(contours[contour_cnt].point_cnt);
206 }
207
208
209 static void
210 middle_down(int x1, int y1)
211 {
212 GLuint point_cnt;
213
214 point_cnt = contours[contour_cnt].point_cnt;
215 if (point_cnt > 2) {
216 glBegin(GL_LINES);
217 glVertex2iv(contours[contour_cnt].p[0]);
218 glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
219 contours[contour_cnt].p[point_cnt][0] = -1;
220 glEnd();
221 glFinish();
222 contour_cnt++;
223 contours[contour_cnt].point_cnt = 0;
224 }
225 }
226
227
228 static void
229 mouse_clicked(int button, int state, int x, int y)
230 {
231 x -= x % 10;
232 y -= y % 10;
233 switch (button) {
234 case GLUT_LEFT_BUTTON:
235 if (state == GLUT_DOWN)
236 left_down(x, y);
237 break;
238 case GLUT_MIDDLE_BUTTON:
239 if (state == GLUT_DOWN)
240 middle_down(x, y);
241 break;
242 }
243 }
244
245
246 static void
247 display(void)
248 {
249 GLuint i, j;
250 GLuint point_cnt;
251
252 glClear(GL_COLOR_BUFFER_BIT);
253 switch (mode) {
254 case DEFINE:
255 /* draw grid */
256 glColor3f(0.6, 0.5, 0.5);
257 glBegin(GL_LINES);
258 for (i = 0; i < width; i += 10)
259 for (j = 0; j < height; j += 10) {
260 glVertex2i(0, j);
261 glVertex2i(width, j);
262 glVertex2i(i, height);
263 glVertex2i(i, 0);
264 }
265 glEnd();
266 glColor3f(1.0, 1.0, 0.0);
267 for (i = 0; i <= contour_cnt; i++) {
268 point_cnt = contours[i].point_cnt;
269 glBegin(GL_LINES);
270 switch (point_cnt) {
271 case 0:
272 break;
273 case 1:
274 glVertex2iv(contours[i].p[0]);
275 glVertex2iv(contours[i].p[0]);
276 break;
277 case 2:
278 glVertex2iv(contours[i].p[0]);
279 glVertex2iv(contours[i].p[1]);
280 break;
281 default:
282 --point_cnt;
283 for (j = 0; j < point_cnt; j++) {
284 glVertex2iv(contours[i].p[j]);
285 glVertex2iv(contours[i].p[j + 1]);
286 }
287 if (contours[i].p[j + 1][0] == -1) {
288 glVertex2iv(contours[i].p[0]);
289 glVertex2iv(contours[i].p[j]);
290 }
291 break;
292 }
293 glEnd();
294 }
295 glFinish();
296 break;
297 case TESSELATED:
298 /* draw lines */
299 tesse();
300 break;
301 }
302
303 glColor3f(1.0, 1.0, 0.0);
304 }
305
306
307 static void
308 clear(void)
309 {
310 contour_cnt = 0;
311 contours[0].point_cnt = 0;
312 glutMouseFunc(mouse_clicked);
313 mode = DEFINE;
314 display();
315 }
316
317
318 static void
319 quit(void)
320 {
321 exit(0);
322 }
323
324
325 static void
326 menu_selected(int entry)
327 {
328 switch (entry) {
329 case CLEAR:
330 clear();
331 break;
332 case TESSELATE:
333 tesse();
334 break;
335 case QUIT:
336 quit();
337 break;
338 }
339 }
340
341
342 static void
343 key_pressed(unsigned char key, int x, int y)
344 {
345 switch (key) {
346 case 't':
347 case 'T':
348 tesse();
349 glFinish();
350 break;
351 case 'q':
352 case 'Q':
353 quit();
354 break;
355 case 'c':
356 case 'C':
357 clear();
358 break;
359 }
360 }
361
362
363 static void
364 myinit(void)
365 {
366 /* clear background to gray */
367 glClearColor(0.4, 0.4, 0.4, 0.0);
368 glShadeModel(GL_FLAT);
369
370 menu = glutCreateMenu(menu_selected);
371 glutAddMenuEntry("clear", CLEAR);
372 glutAddMenuEntry("tesselate", TESSELATE);
373 glutAddMenuEntry("quit", QUIT);
374 glutAttachMenu(GLUT_RIGHT_BUTTON);
375 glutMouseFunc(mouse_clicked);
376 glutKeyboardFunc(key_pressed);
377 contour_cnt = 0;
378 glPolygonMode(GL_FRONT, GL_FILL);
379 mode = DEFINE;
380 }
381
382
383 static void
384 reshape(GLsizei w, GLsizei h)
385 {
386 glViewport(0, 0, w, h);
387 glMatrixMode(GL_PROJECTION);
388 glLoadIdentity();
389 glOrtho(0.0, (GLdouble) w, 0.0, (GLdouble) h, -1.0, 1.0);
390 glMatrixMode(GL_MODELVIEW);
391 glLoadIdentity();
392 set_screen_wh(w, h);
393 }
394
395
396 static void
397 usage(void)
398 {
399 printf("Use left mouse button to place vertices.\n");
400 printf("Press middle mouse button when done.\n");
401 printf("Select tesselate from the pop-up menu.\n");
402 }
403
404
405 /* Main Loop
406 * Open window with initial window size, title bar,
407 * RGBA display mode, and handle input events.
408 */
409 int
410 main(int argc, char **argv)
411 {
412 usage();
413 glutInit(&argc, argv);
414 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
415 glutInitWindowSize(400, 400);
416 glutCreateWindow(argv[0]);
417 myinit();
418 glutDisplayFunc(display);
419 glutReshapeFunc(reshape);
420 glutMainLoop();
421 return 0;
422 }