fixed compiler warnings
[mesa.git] / progs / demos / tessdemo.c
1 /* $Id: tessdemo.c,v 1.7 2000/06/27 17:04:43 brianp Exp $ */
2
3 /*
4 * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
5 * Updated for GLU 1.3 tessellation by Gareth Hughes <garethh@bell-labs.com>
6 */
7
8 #include <GL/glut.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #define MAX_POINTS 256
14 #define MAX_CONTOURS 32
15 #define MAX_TRIANGLES 256
16
17 #ifndef GLCALLBACK
18 #ifdef CALLBACK
19 #define GLCALLBACK CALLBACK
20 #else
21 #define GLCALLBACK
22 #endif
23 #endif
24
25 typedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
26 typedef enum{ DEFINE, TESSELATED } mode_type;
27
28 static GLsizei width, height;
29 static GLuint contour_cnt;
30 static GLuint triangle_cnt;
31
32 static mode_type mode;
33 static int menu;
34
35 static GLuint list_start;
36
37 static GLfloat edge_color[3];
38
39 static struct
40 {
41 GLfloat p[MAX_POINTS][2];
42 GLuint point_cnt;
43 } contours[MAX_CONTOURS];
44
45 static struct
46 {
47 GLsizei no;
48 GLfloat p[3][2];
49 GLclampf color[3][3];
50 } triangles[MAX_TRIANGLES];
51
52
53
54 static void GLCALLBACK error_callback( GLenum err )
55 {
56 int len, i;
57 char const *str;
58
59 glColor3f( 0.9, 0.9, 0.9 );
60 glRasterPos2i( 5, 5 );
61
62 str = (const char *) gluErrorString( err );
63 len = strlen( str );
64
65 for ( i = 0 ; i < len ; i++ ) {
66 glutBitmapCharacter( GLUT_BITMAP_9_BY_15, str[i] );
67 }
68 }
69
70 static void GLCALLBACK begin_callback( GLenum mode )
71 {
72 /* Allow multiple triangles to be output inside the begin/end pair. */
73 triangle_cnt = 0;
74 triangles[triangle_cnt].no = 0;
75 }
76
77 static void GLCALLBACK edge_callback( GLenum flag )
78 {
79 /* Persist the edge flag across triangles. */
80 if ( flag == GL_TRUE )
81 {
82 edge_color[0] = 1.0;
83 edge_color[1] = 1.0;
84 edge_color[2] = 0.5;
85 }
86 else
87 {
88 edge_color[0] = 1.0;
89 edge_color[1] = 0.0;
90 edge_color[2] = 0.0;
91 }
92 }
93
94 static void GLCALLBACK end_callback()
95 {
96 GLint i;
97
98 glBegin( GL_LINES );
99
100 /* Output the three edges of each triangle as lines colored
101 according to their edge flag. */
102 for ( i = 0 ; i < triangle_cnt ; i++ )
103 {
104 glColor3f( triangles[i].color[0][0],
105 triangles[i].color[0][1],
106 triangles[i].color[0][2] );
107
108 glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
109 glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
110
111 glColor3f( triangles[i].color[1][0],
112 triangles[i].color[1][1],
113 triangles[i].color[1][2] );
114
115 glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
116 glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
117
118 glColor3f( triangles[i].color[2][0],
119 triangles[i].color[2][1],
120 triangles[i].color[2][2] );
121
122 glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
123 glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
124 }
125
126 glEnd();
127 }
128
129 static void GLCALLBACK vertex_callback( void *data )
130 {
131 GLsizei no;
132 GLfloat *p;
133
134 p = (GLfloat *) data;
135 no = triangles[triangle_cnt].no;
136
137 triangles[triangle_cnt].p[no][0] = p[0];
138 triangles[triangle_cnt].p[no][1] = p[1];
139
140 triangles[triangle_cnt].color[no][0] = edge_color[0];
141 triangles[triangle_cnt].color[no][1] = edge_color[1];
142 triangles[triangle_cnt].color[no][2] = edge_color[2];
143
144 /* After every three vertices, initialize the next triangle. */
145 if ( ++(triangles[triangle_cnt].no) == 3 )
146 {
147 triangle_cnt++;
148 triangles[triangle_cnt].no = 0;
149 }
150 }
151
152 static void GLCALLBACK combine_callback( GLdouble coords[3],
153 GLdouble *vertex_data[4],
154 GLfloat weight[4], void **data )
155 {
156 GLfloat *vertex;
157
158 vertex = (GLfloat *) malloc( 2 * sizeof(GLfloat) );
159
160 vertex[0] = (GLfloat) coords[0];
161 vertex[1] = (GLfloat) coords[1];
162
163 *data = vertex;
164 }
165
166
167 static void set_screen_wh( GLsizei w, GLsizei h )
168 {
169 width = w;
170 height = h;
171 }
172
173 static void tesse( void )
174 {
175 GLUtesselator *tobj;
176 GLdouble data[3];
177 GLuint i, j, point_cnt;
178
179 list_start = glGenLists( 2 );
180
181 tobj = gluNewTess();
182
183 if ( tobj != NULL )
184 {
185 gluTessNormal( tobj, 0.0, 0.0, 1.0 );
186 gluTessCallback( tobj, GLU_TESS_BEGIN, glBegin );
187 gluTessCallback( tobj, GLU_TESS_VERTEX, glVertex2fv );
188 gluTessCallback( tobj, GLU_TESS_END, glEnd );
189 gluTessCallback( tobj, GLU_TESS_ERROR, error_callback );
190 gluTessCallback( tobj, GLU_TESS_COMBINE, combine_callback );
191
192 glNewList( list_start, GL_COMPILE );
193 gluBeginPolygon( tobj );
194
195 for ( j = 0 ; j <= contour_cnt ; j++ )
196 {
197 point_cnt = contours[j].point_cnt;
198 gluNextContour( tobj, GLU_UNKNOWN );
199
200 for ( i = 0 ; i < point_cnt ; i++ )
201 {
202 data[0] = (GLdouble)( contours[j].p[i][0] );
203 data[1] = (GLdouble)( contours[j].p[i][1] );
204 data[2] = 0.0;
205 gluTessVertex( tobj, data, contours[j].p[i] );
206 }
207 }
208
209 gluEndPolygon( tobj );
210 glEndList();
211
212 gluTessCallback( tobj, GLU_TESS_BEGIN, begin_callback );
213 gluTessCallback( tobj, GLU_TESS_VERTEX, vertex_callback );
214 gluTessCallback( tobj, GLU_TESS_END, end_callback );
215 gluTessCallback( tobj, GLU_TESS_EDGE_FLAG, edge_callback );
216
217 glNewList( list_start + 1, GL_COMPILE );
218 gluBeginPolygon( tobj );
219
220 for ( j = 0 ; j <= contour_cnt ; j++ )
221 {
222 point_cnt = contours[j].point_cnt;
223 gluNextContour( tobj, GLU_UNKNOWN );
224
225 for ( i = 0 ; i < point_cnt ; i++ )
226 {
227 data[0] = (GLdouble)( contours[j].p[i][0] );
228 data[1] = (GLdouble)( contours[j].p[i][1] );
229 data[2] = 0.0;
230 gluTessVertex( tobj, data, contours[j].p[i] );
231 }
232 }
233
234 gluEndPolygon( tobj );
235 glEndList();
236
237 gluDeleteTess( tobj );
238
239 glutMouseFunc( NULL );
240 mode = TESSELATED;
241 }
242 }
243
244 static void left_down( int x1, int y1 )
245 {
246 GLfloat P[2];
247 GLuint point_cnt;
248
249 /* translate GLUT into GL coordinates */
250
251 P[0] = x1;
252 P[1] = height - y1;
253
254 point_cnt = contours[contour_cnt].point_cnt;
255
256 contours[contour_cnt].p[point_cnt][0] = P[0];
257 contours[contour_cnt].p[point_cnt][1] = P[1];
258
259 glBegin( GL_LINES );
260
261 if ( point_cnt )
262 {
263 glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
264 glVertex2fv( P );
265 }
266 else
267 {
268 glVertex2fv( P );
269 glVertex2fv( P );
270 }
271
272 glEnd();
273 glFinish();
274
275 contours[contour_cnt].point_cnt++;
276 }
277
278 static void middle_down( int x1, int y1 )
279 {
280 GLuint point_cnt;
281 (void) x1;
282 (void) y1;
283
284 point_cnt = contours[contour_cnt].point_cnt;
285
286 if ( point_cnt > 2 )
287 {
288 glBegin( GL_LINES );
289
290 glVertex2fv( contours[contour_cnt].p[0] );
291 glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
292
293 contours[contour_cnt].p[point_cnt][0] = -1;
294
295 glEnd();
296 glFinish();
297
298 contour_cnt++;
299 contours[contour_cnt].point_cnt = 0;
300 }
301 }
302
303 static void mouse_clicked( int button, int state, int x, int y )
304 {
305 x -= x%10;
306 y -= y%10;
307
308 switch ( button )
309 {
310 case GLUT_LEFT_BUTTON:
311 if ( state == GLUT_DOWN ) {
312 left_down( x, y );
313 }
314 break;
315 case GLUT_MIDDLE_BUTTON:
316 if ( state == GLUT_DOWN ) {
317 middle_down( x, y );
318 }
319 break;
320 }
321 }
322
323 static void display( void )
324 {
325 GLuint i,j;
326 GLuint point_cnt;
327
328 glClear( GL_COLOR_BUFFER_BIT );
329
330 switch ( mode )
331 {
332 case DEFINE:
333 /* draw grid */
334 glColor3f( 0.6, 0.5, 0.5 );
335
336 glBegin( GL_LINES );
337
338 for ( i = 0 ; i < width ; i += 10 )
339 {
340 for ( j = 0 ; j < height ; j += 10 )
341 {
342 glVertex2i( 0, j );
343 glVertex2i( width, j );
344 glVertex2i( i, height );
345 glVertex2i( i, 0 );
346 }
347 }
348
349 glEnd();
350
351 glColor3f( 1.0, 1.0, 0.0 );
352
353 for ( i = 0 ; i <= contour_cnt ; i++ )
354 {
355 point_cnt = contours[i].point_cnt;
356
357 glBegin( GL_LINES );
358
359 switch ( point_cnt )
360 {
361 case 0:
362 break;
363 case 1:
364 glVertex2fv( contours[i].p[0] );
365 glVertex2fv( contours[i].p[0] );
366 break;
367 case 2:
368 glVertex2fv( contours[i].p[0] );
369 glVertex2fv( contours[i].p[1] );
370 break;
371 default:
372 --point_cnt;
373 for ( j = 0 ; j < point_cnt ; j++ )
374 {
375 glVertex2fv( contours[i].p[j] );
376 glVertex2fv( contours[i].p[j+1] );
377 }
378 if ( contours[i].p[j+1][0] == -1 )
379 {
380 glVertex2fv( contours[i].p[0] );
381 glVertex2fv( contours[i].p[j] );
382 }
383 break;
384 }
385
386 glEnd();
387 }
388
389 glFinish();
390 break;
391
392 case TESSELATED:
393 /* draw triangles */
394 glColor3f( 0.7, 0.7, 0.0 );
395 glCallList( list_start );
396
397 glLineWidth( 2.0 );
398 glCallList( list_start + 1 );
399 glLineWidth( 1.0 );
400
401 glFlush();
402 break;
403 }
404
405 glColor3f( 1.0, 1.0, 0.0 );
406 }
407
408 static void clear( void )
409 {
410 contour_cnt = 0;
411 contours[0].point_cnt = 0;
412 triangle_cnt = 0;
413
414 glutMouseFunc( mouse_clicked );
415
416 mode = DEFINE;
417
418 glDeleteLists( list_start, 2 );
419 list_start = 0;
420 }
421
422 static void quit( void )
423 {
424 exit( 0 );
425 }
426
427 static void menu_selected( int entry )
428 {
429 switch ( entry )
430 {
431 case CLEAR:
432 clear();
433 break;
434 case TESSELATE:
435 tesse();
436 break;
437 case QUIT:
438 quit();
439 break;
440 }
441
442 glutPostRedisplay();
443 }
444
445 static void key_pressed( unsigned char key, int x, int y )
446 {
447 (void) x;
448 (void) y;
449
450 switch ( key )
451 {
452 case 'c':
453 case 'C':
454 clear();
455 break;
456 case 't':
457 case 'T':
458 tesse();
459 break;
460 case 'q':
461 case 'Q':
462 quit();
463 break;
464 }
465
466 glutPostRedisplay();
467 }
468
469 static void myinit( void )
470 {
471 /* clear background to gray */
472 glClearColor( 0.4, 0.4, 0.4, 0.0 );
473 glShadeModel( GL_FLAT );
474 glPolygonMode( GL_FRONT, GL_FILL );
475
476 menu = glutCreateMenu( menu_selected );
477
478 glutAddMenuEntry( "clear", CLEAR );
479 glutAddMenuEntry( "tesselate", TESSELATE );
480 glutAddMenuEntry( "quit", QUIT );
481
482 glutAttachMenu( GLUT_RIGHT_BUTTON );
483
484 glutMouseFunc( mouse_clicked );
485 glutKeyboardFunc( key_pressed );
486
487 contour_cnt = 0;
488 mode = DEFINE;
489 }
490
491 static void reshape( GLsizei w, GLsizei h )
492 {
493 glViewport( 0, 0, w, h );
494
495 glMatrixMode( GL_PROJECTION );
496 glLoadIdentity();
497 glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
498
499 glMatrixMode( GL_MODELVIEW );
500 glLoadIdentity();
501
502 set_screen_wh( w, h );
503 }
504
505
506 static void usage( void )
507 {
508 printf( "Use left mouse button to place vertices.\n" );
509 printf( "Press middle mouse button when done.\n" );
510 printf( "Select tesselate from the pop-up menu.\n" );
511 }
512
513
514 /*
515 * Main Loop
516 * Open window with initial window size, title bar,
517 * RGBA display mode, and handle input events.
518 */
519 int main( int argc, char **argv )
520 {
521 usage();
522
523 glutInit( &argc, argv );
524 glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
525 glutInitWindowSize( 400, 400 );
526 glutCreateWindow( argv[0] );
527
528 myinit();
529
530 glutDisplayFunc( display );
531 glutReshapeFunc( reshape );
532
533 glutMainLoop();
534
535 return 0;
536 }