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