blob: 2e02b9027e9cb286505f3d8c10d780c7d3cce534 [file] [log] [blame]
Brian Paulc4266ac2000-07-11 14:11:58 +00001/* $Id: tessdemo.c,v 1.8 2000/07/11 14:11:58 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
Gareth Hugheseb459c61999-11-04 04:00:42 +00005 */
jtgafb833d1999-08-19 00:55:39 +00006
Brian Paulc4266ac2000-07-11 14:11:58 +00007
jtgafb833d1999-08-19 00:55:39 +00008#include <GL/glut.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
Brian Paulc4266ac2000-07-11 14:11:58 +000013#define MAX_POINTS 200
14#define MAX_CONTOURS 50
jtgafb833d1999-08-19 00:55:39 +000015
Brian Paulc4266ac2000-07-11 14:11:58 +000016static int menu;
17typedef enum
18{ QUIT, TESSELATE, CLEAR }
19menu_entries;
jtgafb833d1999-08-19 00:55:39 +000020
Brian Paulc4266ac2000-07-11 14:11:58 +000021typedef enum
22{ DEFINE, TESSELATED }
23mode_type;
jtgafb833d1999-08-19 00:55:39 +000024
Brian Paulc4266ac2000-07-11 14:11:58 +000025struct
jtgafb833d1999-08-19 00:55:39 +000026{
Brian Paulc4266ac2000-07-11 14:11:58 +000027 GLint p[MAX_POINTS][2];
28 GLuint point_cnt;
29}
30contours[MAX_CONTOURS];
jtgafb833d1999-08-19 00:55:39 +000031
Brian Paulc4266ac2000-07-11 14:11:58 +000032static GLuint contour_cnt;
33static GLsizei width, height;
34static mode_type mode;
35
36struct
Gareth Hugheseb459c61999-11-04 04:00:42 +000037{
Brian Paulc4266ac2000-07-11 14:11:58 +000038 GLsizei no;
39 GLfloat color[3];
40 GLint p[3][2];
41 GLclampf p_color[3][3];
42}
43triangle;
Gareth Hugheseb459c61999-11-04 04:00:42 +000044
45
Brian Paulc4266ac2000-07-11 14:11:58 +000046static void GLCALLBACK
47my_error(GLenum err)
Gareth Hugheseb459c61999-11-04 04:00:42 +000048{
Brian Paulc4266ac2000-07-11 14:11:58 +000049 int len, i;
50 char const *str;
Gareth Hugheseb459c61999-11-04 04:00:42 +000051
Brian Paulc4266ac2000-07-11 14:11:58 +000052 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}
Gareth Hugheseb459c61999-11-04 04:00:42 +000059
Gareth Hugheseb459c61999-11-04 04:00:42 +000060
Brian Paulc4266ac2000-07-11 14:11:58 +000061static void GLCALLBACK
62begin_callback(GLenum mode)
63{
64 triangle.no = 0;
65}
66
67
68static void GLCALLBACK
69edge_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;
Gareth Hugheseb459c61999-11-04 04:00:42 +000080 }
jtgafb833d1999-08-19 00:55:39 +000081}
82
Brian Paulc4266ac2000-07-11 14:11:58 +000083
84static void GLCALLBACK
85end_callback()
jtgafb833d1999-08-19 00:55:39 +000086{
Brian Paulc4266ac2000-07-11 14:11:58 +000087 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]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000100 glEnd();
jtgafb833d1999-08-19 00:55:39 +0000101}
102
Brian Paulc4266ac2000-07-11 14:11:58 +0000103
104static void GLCALLBACK
105vertex_callback(void *data)
jtgafb833d1999-08-19 00:55:39 +0000106{
Brian Paulc4266ac2000-07-11 14:11:58 +0000107 GLsizei no;
108 GLint *p;
jtgafb833d1999-08-19 00:55:39 +0000109
Brian Paulc4266ac2000-07-11 14:11:58 +0000110 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);
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000118}
119
120
Brian Paulc4266ac2000-07-11 14:11:58 +0000121static void
122set_screen_wh(GLsizei w, GLsizei h)
jtgafb833d1999-08-19 00:55:39 +0000123{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000124 width = w;
125 height = h;
jtgafb833d1999-08-19 00:55:39 +0000126}
127
jtgafb833d1999-08-19 00:55:39 +0000128
Brian Paulc4266ac2000-07-11 14:11:58 +0000129static void
130tesse(void)
131{
132 GLUtriangulatorObj *tobj;
133 GLdouble data[3];
134 GLuint i, j, point_cnt;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000135
136 tobj = gluNewTess();
Brian Paulc4266ac2000-07-11 14:11:58 +0000137 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++) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000146 point_cnt = contours[j].point_cnt;
Brian Paulc4266ac2000-07-11 14:11:58 +0000147 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]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000151 data[2] = 0.0;
Brian Paulc4266ac2000-07-11 14:11:58 +0000152 gluTessVertex(tobj, data, contours[j].p[i]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000153 }
154 }
Brian Paulc4266ac2000-07-11 14:11:58 +0000155 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++) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000163 point_cnt = contours[j].point_cnt;
Brian Paulc4266ac2000-07-11 14:11:58 +0000164 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]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000168 data[2] = 0.0;
Brian Paulc4266ac2000-07-11 14:11:58 +0000169 gluTessVertex(tobj, data, contours[j].p[i]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000170 }
171 }
Brian Paulc4266ac2000-07-11 14:11:58 +0000172 gluEndPolygon(tobj);
173 gluDeleteTess(tobj);
174 glutMouseFunc(NULL);
175 glColor3f(1.0, 1.0, 0.0);
176 glLineWidth(1.0);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000177 mode = TESSELATED;
178 }
jtgafb833d1999-08-19 00:55:39 +0000179}
180
Brian Paulc4266ac2000-07-11 14:11:58 +0000181
182static void
183left_down(int x1, int y1)
jtgafb833d1999-08-19 00:55:39 +0000184{
Brian Paulc4266ac2000-07-11 14:11:58 +0000185 GLint P[2];
186 GLuint point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000187
Gareth Hugheseb459c61999-11-04 04:00:42 +0000188 /* translate GLUT into GL coordinates */
Gareth Hugheseb459c61999-11-04 04:00:42 +0000189 P[0] = x1;
190 P[1] = height - y1;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000191 point_cnt = contours[contour_cnt].point_cnt;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000192 contours[contour_cnt].p[point_cnt][0] = P[0];
193 contours[contour_cnt].p[point_cnt][1] = P[1];
Brian Paulc4266ac2000-07-11 14:11:58 +0000194 glBegin(GL_LINES);
195 if (point_cnt) {
196 glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
197 glVertex2iv(P);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000198 }
Brian Paulc4266ac2000-07-11 14:11:58 +0000199 else {
200 glVertex2iv(P);
201 glVertex2iv(P);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000202 }
Gareth Hugheseb459c61999-11-04 04:00:42 +0000203 glEnd();
204 glFinish();
Brian Paulc4266ac2000-07-11 14:11:58 +0000205 ++(contours[contour_cnt].point_cnt);
jtgafb833d1999-08-19 00:55:39 +0000206}
207
Brian Paulc4266ac2000-07-11 14:11:58 +0000208
209static void
210middle_down(int x1, int y1)
jtgafb833d1999-08-19 00:55:39 +0000211{
Brian Paulc4266ac2000-07-11 14:11:58 +0000212 GLuint point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000213
Gareth Hugheseb459c61999-11-04 04:00:42 +0000214 point_cnt = contours[contour_cnt].point_cnt;
Brian Paulc4266ac2000-07-11 14:11:58 +0000215 if (point_cnt > 2) {
216 glBegin(GL_LINES);
217 glVertex2iv(contours[contour_cnt].p[0]);
218 glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000219 contours[contour_cnt].p[point_cnt][0] = -1;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000220 glEnd();
221 glFinish();
Gareth Hugheseb459c61999-11-04 04:00:42 +0000222 contour_cnt++;
223 contours[contour_cnt].point_cnt = 0;
224 }
jtgafb833d1999-08-19 00:55:39 +0000225}
226
Gareth Hugheseb459c61999-11-04 04:00:42 +0000227
Brian Paulc4266ac2000-07-11 14:11:58 +0000228static void
229mouse_clicked(int button, int state, int x, int y)
230{
231 x -= x % 10;
232 y -= y % 10;
233 switch (button) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000234 case GLUT_LEFT_BUTTON:
Brian Paulc4266ac2000-07-11 14:11:58 +0000235 if (state == GLUT_DOWN)
236 left_down(x, y);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000237 break;
238 case GLUT_MIDDLE_BUTTON:
Brian Paulc4266ac2000-07-11 14:11:58 +0000239 if (state == GLUT_DOWN)
240 middle_down(x, y);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000241 break;
242 }
jtgafb833d1999-08-19 00:55:39 +0000243}
244
Brian Paulc4266ac2000-07-11 14:11:58 +0000245
246static void
247display(void)
jtgafb833d1999-08-19 00:55:39 +0000248{
Brian Paulc4266ac2000-07-11 14:11:58 +0000249 GLuint i, j;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000250 GLuint point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000251
Brian Paulc4266ac2000-07-11 14:11:58 +0000252 glClear(GL_COLOR_BUFFER_BIT);
253 switch (mode) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000254 case DEFINE:
255 /* draw grid */
Brian Paulc4266ac2000-07-11 14:11:58 +0000256 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);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000264 }
Brian Pauld25df352000-03-27 15:46:12 +0000265 glEnd();
Brian Paulc4266ac2000-07-11 14:11:58 +0000266 glColor3f(1.0, 1.0, 0.0);
267 for (i = 0; i <= contour_cnt; i++) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000268 point_cnt = contours[i].point_cnt;
Brian Paulc4266ac2000-07-11 14:11:58 +0000269 glBegin(GL_LINES);
270 switch (point_cnt) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000271 case 0:
272 break;
273 case 1:
Brian Paulc4266ac2000-07-11 14:11:58 +0000274 glVertex2iv(contours[i].p[0]);
275 glVertex2iv(contours[i].p[0]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000276 break;
277 case 2:
Brian Paulc4266ac2000-07-11 14:11:58 +0000278 glVertex2iv(contours[i].p[0]);
279 glVertex2iv(contours[i].p[1]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000280 break;
281 default:
282 --point_cnt;
Brian Paulc4266ac2000-07-11 14:11:58 +0000283 for (j = 0; j < point_cnt; j++) {
284 glVertex2iv(contours[i].p[j]);
285 glVertex2iv(contours[i].p[j + 1]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000286 }
Brian Paulc4266ac2000-07-11 14:11:58 +0000287 if (contours[i].p[j + 1][0] == -1) {
288 glVertex2iv(contours[i].p[0]);
289 glVertex2iv(contours[i].p[j]);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000290 }
291 break;
292 }
Gareth Hugheseb459c61999-11-04 04:00:42 +0000293 glEnd();
294 }
Gareth Hugheseb459c61999-11-04 04:00:42 +0000295 glFinish();
296 break;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000297 case TESSELATED:
Brian Paulc4266ac2000-07-11 14:11:58 +0000298 /* draw lines */
299 tesse();
Gareth Hugheseb459c61999-11-04 04:00:42 +0000300 break;
301 }
302
Brian Paulc4266ac2000-07-11 14:11:58 +0000303 glColor3f(1.0, 1.0, 0.0);
jtgafb833d1999-08-19 00:55:39 +0000304}
305
Brian Paulc4266ac2000-07-11 14:11:58 +0000306
307static void
308clear(void)
jtgafb833d1999-08-19 00:55:39 +0000309{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000310 contour_cnt = 0;
311 contours[0].point_cnt = 0;
Brian Paulc4266ac2000-07-11 14:11:58 +0000312 glutMouseFunc(mouse_clicked);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000313 mode = DEFINE;
Brian Paulc4266ac2000-07-11 14:11:58 +0000314 display();
jtgafb833d1999-08-19 00:55:39 +0000315}
316
Brian Paulc4266ac2000-07-11 14:11:58 +0000317
318static void
319quit(void)
jtgafb833d1999-08-19 00:55:39 +0000320{
Brian Paulc4266ac2000-07-11 14:11:58 +0000321 exit(0);
jtgafb833d1999-08-19 00:55:39 +0000322}
323
Brian Paulc4266ac2000-07-11 14:11:58 +0000324
325static void
326menu_selected(int entry)
jtgafb833d1999-08-19 00:55:39 +0000327{
Brian Paulc4266ac2000-07-11 14:11:58 +0000328 switch (entry) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000329 case CLEAR:
330 clear();
331 break;
332 case TESSELATE:
333 tesse();
334 break;
335 case QUIT:
336 quit();
337 break;
338 }
jtgafb833d1999-08-19 00:55:39 +0000339}
340
Gareth Hugheseb459c61999-11-04 04:00:42 +0000341
Brian Paulc4266ac2000-07-11 14:11:58 +0000342static void
343key_pressed(unsigned char key, int x, int y)
344{
345 switch (key) {
Gareth Hugheseb459c61999-11-04 04:00:42 +0000346 case 't':
347 case 'T':
348 tesse();
Brian Paulc4266ac2000-07-11 14:11:58 +0000349 glFinish();
Gareth Hugheseb459c61999-11-04 04:00:42 +0000350 break;
351 case 'q':
352 case 'Q':
353 quit();
354 break;
Brian Paulc4266ac2000-07-11 14:11:58 +0000355 case 'c':
356 case 'C':
357 clear();
358 break;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000359 }
jtgafb833d1999-08-19 00:55:39 +0000360}
361
Brian Paulc4266ac2000-07-11 14:11:58 +0000362
363static void
364myinit(void)
jtgafb833d1999-08-19 00:55:39 +0000365{
Brian Paulc4266ac2000-07-11 14:11:58 +0000366/* clear background to gray */
367 glClearColor(0.4, 0.4, 0.4, 0.0);
368 glShadeModel(GL_FLAT);
jtgafb833d1999-08-19 00:55:39 +0000369
Brian Paulc4266ac2000-07-11 14:11:58 +0000370 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);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000377 contour_cnt = 0;
Brian Paulc4266ac2000-07-11 14:11:58 +0000378 glPolygonMode(GL_FRONT, GL_FILL);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000379 mode = DEFINE;
jtgafb833d1999-08-19 00:55:39 +0000380}
381
Brian Paulc4266ac2000-07-11 14:11:58 +0000382
383static void
384reshape(GLsizei w, GLsizei h)
jtgafb833d1999-08-19 00:55:39 +0000385{
Brian Paulc4266ac2000-07-11 14:11:58 +0000386 glViewport(0, 0, w, h);
387 glMatrixMode(GL_PROJECTION);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000388 glLoadIdentity();
Brian Paulc4266ac2000-07-11 14:11:58 +0000389 glOrtho(0.0, (GLdouble) w, 0.0, (GLdouble) h, -1.0, 1.0);
390 glMatrixMode(GL_MODELVIEW);
Gareth Hugheseb459c61999-11-04 04:00:42 +0000391 glLoadIdentity();
Brian Paulc4266ac2000-07-11 14:11:58 +0000392 set_screen_wh(w, h);
jtgafb833d1999-08-19 00:55:39 +0000393}
394
395
Brian Paulc4266ac2000-07-11 14:11:58 +0000396static void
397usage(void)
jtgafb833d1999-08-19 00:55:39 +0000398{
Brian Paulc4266ac2000-07-11 14:11:58 +0000399 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");
jtgafb833d1999-08-19 00:55:39 +0000402}
403
404
Brian Paulc4266ac2000-07-11 14:11:58 +0000405/* Main Loop
406 * Open window with initial window size, title bar,
407 * RGBA display mode, and handle input events.
jtgafb833d1999-08-19 00:55:39 +0000408 */
Brian Paulc4266ac2000-07-11 14:11:58 +0000409int
410main(int argc, char **argv)
jtgafb833d1999-08-19 00:55:39 +0000411{
Brian Paulc4266ac2000-07-11 14:11:58 +0000412 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;
jtgafb833d1999-08-19 00:55:39 +0000422}