blob: b5a6d08c57ebae248bda361d975b6234d930a825 [file] [log] [blame]
Brian Pauld25df352000-03-27 15:46:12 +00001/* $Id: tessdemo.c,v 1.6 2000/03/27 15:46:12 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 * Updated for GLU 1.3 tessellation by Gareth Hughes <garethh@bell-labs.com>
6 */
jtgafb833d1999-08-19 00:55:39 +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
Gareth Hugheseb459c61999-11-04 04:00:42 +000013#define MAX_POINTS 256
14#define MAX_CONTOURS 32
15#define MAX_TRIANGLES 256
jtgafb833d1999-08-19 00:55:39 +000016
17#ifndef GLCALLBACK
18#ifdef CALLBACK
19#define GLCALLBACK CALLBACK
20#else
21#define GLCALLBACK
22#endif
23#endif
24
Gareth Hugheseb459c61999-11-04 04:00:42 +000025typedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
26typedef enum{ DEFINE, TESSELATED } mode_type;
jtgafb833d1999-08-19 00:55:39 +000027
Gareth Hugheseb459c61999-11-04 04:00:42 +000028static GLsizei width, height;
29static GLuint contour_cnt;
30static GLuint triangle_cnt;
31
32static mode_type mode;
33static int menu;
34
35static GLuint list_start;
36
37static GLfloat edge_color[3];
38
39static struct
jtgafb833d1999-08-19 00:55:39 +000040{
Gareth Hughes3b7a75a2000-01-23 21:25:39 +000041 GLfloat p[MAX_POINTS][2];
Gareth Hugheseb459c61999-11-04 04:00:42 +000042 GLuint point_cnt;
43} contours[MAX_CONTOURS];
jtgafb833d1999-08-19 00:55:39 +000044
Gareth Hugheseb459c61999-11-04 04:00:42 +000045static struct
46{
47 GLsizei no;
Gareth Hughes3b7a75a2000-01-23 21:25:39 +000048 GLfloat p[3][2];
Gareth Hugheseb459c61999-11-04 04:00:42 +000049 GLclampf color[3][3];
50} triangles[MAX_TRIANGLES];
51
52
53
Gareth Hughes3b7a75a2000-01-23 21:25:39 +000054void GLCALLBACK error_callback( GLenum err )
Gareth Hugheseb459c61999-11-04 04:00:42 +000055{
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 }
jtgafb833d1999-08-19 00:55:39 +000068}
69
Gareth Hugheseb459c61999-11-04 04:00:42 +000070void GLCALLBACK begin_callback( GLenum mode )
jtgafb833d1999-08-19 00:55:39 +000071{
Gareth Hugheseb459c61999-11-04 04:00:42 +000072 /* Allow multiple triangles to be output inside the begin/end pair. */
73 triangle_cnt = 0;
74 triangles[triangle_cnt].no = 0;
jtgafb833d1999-08-19 00:55:39 +000075}
76
Gareth Hugheseb459c61999-11-04 04:00:42 +000077void GLCALLBACK edge_callback( GLenum flag )
jtgafb833d1999-08-19 00:55:39 +000078{
Gareth Hugheseb459c61999-11-04 04:00:42 +000079 /* 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 }
jtgafb833d1999-08-19 00:55:39 +000092}
93
94void GLCALLBACK end_callback()
95{
Gareth Hugheseb459c61999-11-04 04:00:42 +000096 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
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000108 glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
109 glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000110
111 glColor3f( triangles[i].color[1][0],
112 triangles[i].color[1][1],
113 triangles[i].color[1][2] );
114
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000115 glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
116 glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000117
118 glColor3f( triangles[i].color[2][0],
119 triangles[i].color[2][1],
120 triangles[i].color[2][2] );
121
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000122 glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
123 glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000124 }
125
126 glEnd();
jtgafb833d1999-08-19 00:55:39 +0000127}
128
Gareth Hugheseb459c61999-11-04 04:00:42 +0000129void GLCALLBACK vertex_callback( void *data )
jtgafb833d1999-08-19 00:55:39 +0000130{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000131 GLsizei no;
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000132 GLfloat *p;
jtgafb833d1999-08-19 00:55:39 +0000133
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000134 p = (GLfloat *) data;
Gareth Hugheseb459c61999-11-04 04:00:42 +0000135 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 }
jtgafb833d1999-08-19 00:55:39 +0000150}
151
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000152void GLCALLBACK combine_callback( GLdouble coords[3],
153 GLdouble *vertex_data[4],
154 GLfloat weight[4], void **data )
155{
156 GLfloat *vertex;
157 int i;
158
159 vertex = (GLfloat *) malloc( 2 * sizeof(GLfloat) );
160
161 vertex[0] = (GLfloat) coords[0];
162 vertex[1] = (GLfloat) coords[1];
163
164 *data = vertex;
165}
166
167
Gareth Hugheseb459c61999-11-04 04:00:42 +0000168void set_screen_wh( GLsizei w, GLsizei h )
jtgafb833d1999-08-19 00:55:39 +0000169{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000170 width = w;
171 height = h;
jtgafb833d1999-08-19 00:55:39 +0000172}
173
Gareth Hugheseb459c61999-11-04 04:00:42 +0000174void tesse( void )
jtgafb833d1999-08-19 00:55:39 +0000175{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000176 GLUtesselator *tobj;
177 GLdouble data[3];
178 GLuint i, j, point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000179
Gareth Hugheseb459c61999-11-04 04:00:42 +0000180 list_start = glGenLists( 2 );
181
182 tobj = gluNewTess();
183
184 if ( tobj != NULL )
185 {
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000186 gluTessNormal( tobj, 0.0, 0.0, 1.0 );
187 gluTessCallback( tobj, GLU_TESS_BEGIN, glBegin );
188 gluTessCallback( tobj, GLU_TESS_VERTEX, glVertex2fv );
189 gluTessCallback( tobj, GLU_TESS_END, glEnd );
190 gluTessCallback( tobj, GLU_TESS_ERROR, error_callback );
191 gluTessCallback( tobj, GLU_TESS_COMBINE, combine_callback );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000192
193 glNewList( list_start, GL_COMPILE );
194 gluBeginPolygon( tobj );
195
196 for ( j = 0 ; j <= contour_cnt ; j++ )
197 {
198 point_cnt = contours[j].point_cnt;
199 gluNextContour( tobj, GLU_UNKNOWN );
200
201 for ( i = 0 ; i < point_cnt ; i++ )
202 {
203 data[0] = (GLdouble)( contours[j].p[i][0] );
204 data[1] = (GLdouble)( contours[j].p[i][1] );
205 data[2] = 0.0;
206 gluTessVertex( tobj, data, contours[j].p[i] );
207 }
208 }
209
210 gluEndPolygon( tobj );
211 glEndList();
212
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000213 gluTessCallback( tobj, GLU_TESS_BEGIN, begin_callback );
214 gluTessCallback( tobj, GLU_TESS_VERTEX, vertex_callback );
215 gluTessCallback( tobj, GLU_TESS_END, end_callback );
216 gluTessCallback( tobj, GLU_TESS_EDGE_FLAG, edge_callback );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000217
218 glNewList( list_start + 1, GL_COMPILE );
219 gluBeginPolygon( tobj );
220
221 for ( j = 0 ; j <= contour_cnt ; j++ )
222 {
223 point_cnt = contours[j].point_cnt;
224 gluNextContour( tobj, GLU_UNKNOWN );
225
226 for ( i = 0 ; i < point_cnt ; i++ )
227 {
228 data[0] = (GLdouble)( contours[j].p[i][0] );
229 data[1] = (GLdouble)( contours[j].p[i][1] );
230 data[2] = 0.0;
231 gluTessVertex( tobj, data, contours[j].p[i] );
232 }
233 }
234
235 gluEndPolygon( tobj );
236 glEndList();
237
238 gluDeleteTess( tobj );
239
240 glutMouseFunc( NULL );
241 mode = TESSELATED;
242 }
jtgafb833d1999-08-19 00:55:39 +0000243}
244
Gareth Hugheseb459c61999-11-04 04:00:42 +0000245void left_down( int x1, int y1 )
jtgafb833d1999-08-19 00:55:39 +0000246{
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000247 GLfloat P[2];
Gareth Hugheseb459c61999-11-04 04:00:42 +0000248 GLuint point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000249
Gareth Hugheseb459c61999-11-04 04:00:42 +0000250 /* translate GLUT into GL coordinates */
251
252 P[0] = x1;
253 P[1] = height - y1;
254
255 point_cnt = contours[contour_cnt].point_cnt;
256
257 contours[contour_cnt].p[point_cnt][0] = P[0];
258 contours[contour_cnt].p[point_cnt][1] = P[1];
259
260 glBegin( GL_LINES );
261
262 if ( point_cnt )
263 {
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000264 glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
265 glVertex2fv( P );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000266 }
267 else
268 {
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000269 glVertex2fv( P );
270 glVertex2fv( P );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000271 }
272
273 glEnd();
274 glFinish();
275
276 contours[contour_cnt].point_cnt++;
jtgafb833d1999-08-19 00:55:39 +0000277}
278
Gareth Hugheseb459c61999-11-04 04:00:42 +0000279void middle_down( int x1, int y1 )
jtgafb833d1999-08-19 00:55:39 +0000280{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000281 GLuint point_cnt;
282 (void) x1;
283 (void) y1;
jtgafb833d1999-08-19 00:55:39 +0000284
Gareth Hugheseb459c61999-11-04 04:00:42 +0000285 point_cnt = contours[contour_cnt].point_cnt;
286
287 if ( point_cnt > 2 )
288 {
289 glBegin( GL_LINES );
290
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000291 glVertex2fv( contours[contour_cnt].p[0] );
292 glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000293
294 contours[contour_cnt].p[point_cnt][0] = -1;
295
296 glEnd();
297 glFinish();
298
299 contour_cnt++;
300 contours[contour_cnt].point_cnt = 0;
301 }
jtgafb833d1999-08-19 00:55:39 +0000302}
303
Gareth Hugheseb459c61999-11-04 04:00:42 +0000304void mouse_clicked( int button, int state, int x, int y )
jtgafb833d1999-08-19 00:55:39 +0000305{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000306 x -= x%10;
307 y -= y%10;
308
309 switch ( button )
310 {
311 case GLUT_LEFT_BUTTON:
312 if ( state == GLUT_DOWN ) {
313 left_down( x, y );
314 }
315 break;
316 case GLUT_MIDDLE_BUTTON:
317 if ( state == GLUT_DOWN ) {
318 middle_down( x, y );
319 }
320 break;
321 }
jtgafb833d1999-08-19 00:55:39 +0000322}
323
Gareth Hugheseb459c61999-11-04 04:00:42 +0000324void display( void )
jtgafb833d1999-08-19 00:55:39 +0000325{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000326 GLuint i,j;
327 GLuint point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000328
Gareth Hugheseb459c61999-11-04 04:00:42 +0000329 glClear( GL_COLOR_BUFFER_BIT );
jtgafb833d1999-08-19 00:55:39 +0000330
Gareth Hugheseb459c61999-11-04 04:00:42 +0000331 switch ( mode )
332 {
333 case DEFINE:
334 /* draw grid */
335 glColor3f( 0.6, 0.5, 0.5 );
336
337 glBegin( GL_LINES );
338
339 for ( i = 0 ; i < width ; i += 10 )
340 {
341 for ( j = 0 ; j < height ; j += 10 )
342 {
343 glVertex2i( 0, j );
344 glVertex2i( width, j );
345 glVertex2i( i, height );
346 glVertex2i( i, 0 );
347 }
348 }
349
Brian Pauld25df352000-03-27 15:46:12 +0000350 glEnd();
351
Gareth Hugheseb459c61999-11-04 04:00:42 +0000352 glColor3f( 1.0, 1.0, 0.0 );
353
354 for ( i = 0 ; i <= contour_cnt ; i++ )
355 {
356 point_cnt = contours[i].point_cnt;
357
358 glBegin( GL_LINES );
359
360 switch ( point_cnt )
361 {
362 case 0:
363 break;
364 case 1:
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000365 glVertex2fv( contours[i].p[0] );
366 glVertex2fv( contours[i].p[0] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000367 break;
368 case 2:
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000369 glVertex2fv( contours[i].p[0] );
370 glVertex2fv( contours[i].p[1] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000371 break;
372 default:
373 --point_cnt;
374 for ( j = 0 ; j < point_cnt ; j++ )
375 {
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000376 glVertex2fv( contours[i].p[j] );
377 glVertex2fv( contours[i].p[j+1] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000378 }
379 if ( contours[i].p[j+1][0] == -1 )
380 {
Gareth Hughes3b7a75a2000-01-23 21:25:39 +0000381 glVertex2fv( contours[i].p[0] );
382 glVertex2fv( contours[i].p[j] );
Gareth Hugheseb459c61999-11-04 04:00:42 +0000383 }
384 break;
385 }
386
387 glEnd();
388 }
389
390 glFinish();
391 break;
392
393 case TESSELATED:
394 /* draw triangles */
395 glColor3f( 0.7, 0.7, 0.0 );
396 glCallList( list_start );
397
398 glLineWidth( 2.0 );
399 glCallList( list_start + 1 );
400 glLineWidth( 1.0 );
401
402 glFlush();
403 break;
404 }
405
406 glColor3f( 1.0, 1.0, 0.0 );
jtgafb833d1999-08-19 00:55:39 +0000407}
408
409void clear( void )
410{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000411 contour_cnt = 0;
412 contours[0].point_cnt = 0;
413 triangle_cnt = 0;
414
415 glutMouseFunc( mouse_clicked );
416
417 mode = DEFINE;
418
419 glDeleteLists( list_start, 2 );
420 list_start = 0;
jtgafb833d1999-08-19 00:55:39 +0000421}
422
423void quit( void )
424{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000425 exit( 0 );
jtgafb833d1999-08-19 00:55:39 +0000426}
427
Gareth Hugheseb459c61999-11-04 04:00:42 +0000428void menu_selected( int entry )
jtgafb833d1999-08-19 00:55:39 +0000429{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000430 switch ( entry )
431 {
432 case CLEAR:
433 clear();
434 break;
435 case TESSELATE:
436 tesse();
437 break;
438 case QUIT:
439 quit();
440 break;
441 }
442
443 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000444}
445
Gareth Hugheseb459c61999-11-04 04:00:42 +0000446void key_pressed( unsigned char key, int x, int y )
jtgafb833d1999-08-19 00:55:39 +0000447{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000448 (void) x;
449 (void) y;
450
451 switch ( key )
452 {
453 case 'c':
454 case 'C':
455 clear();
456 break;
457 case 't':
458 case 'T':
459 tesse();
460 break;
461 case 'q':
462 case 'Q':
463 quit();
464 break;
465 }
466
467 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000468}
469
Gareth Hugheseb459c61999-11-04 04:00:42 +0000470void myinit( void )
jtgafb833d1999-08-19 00:55:39 +0000471{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000472 /* clear background to gray */
473 glClearColor( 0.4, 0.4, 0.4, 0.0 );
474 glShadeModel( GL_FLAT );
475 glPolygonMode( GL_FRONT, GL_FILL );
jtgafb833d1999-08-19 00:55:39 +0000476
Gareth Hugheseb459c61999-11-04 04:00:42 +0000477 menu = glutCreateMenu( menu_selected );
478
479 glutAddMenuEntry( "clear", CLEAR );
480 glutAddMenuEntry( "tesselate", TESSELATE );
481 glutAddMenuEntry( "quit", QUIT );
482
483 glutAttachMenu( GLUT_RIGHT_BUTTON );
484
485 glutMouseFunc( mouse_clicked );
486 glutKeyboardFunc( key_pressed );
487
488 contour_cnt = 0;
489 mode = DEFINE;
jtgafb833d1999-08-19 00:55:39 +0000490}
491
Gareth Hugheseb459c61999-11-04 04:00:42 +0000492static void reshape( GLsizei w, GLsizei h )
jtgafb833d1999-08-19 00:55:39 +0000493{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000494 glViewport( 0, 0, w, h );
495
496 glMatrixMode( GL_PROJECTION );
497 glLoadIdentity();
498 glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
499
500 glMatrixMode( GL_MODELVIEW );
501 glLoadIdentity();
502
503 set_screen_wh( w, h );
jtgafb833d1999-08-19 00:55:39 +0000504}
505
506
507static void usage( void )
508{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000509 printf( "Use left mouse button to place vertices.\n" );
510 printf( "Press middle mouse button when done.\n" );
511 printf( "Select tesselate from the pop-up menu.\n" );
jtgafb833d1999-08-19 00:55:39 +0000512}
513
514
Gareth Hugheseb459c61999-11-04 04:00:42 +0000515/*
516 * Main Loop
517 * Open window with initial window size, title bar,
518 * RGBA display mode, and handle input events.
jtgafb833d1999-08-19 00:55:39 +0000519 */
Gareth Hugheseb459c61999-11-04 04:00:42 +0000520int main( int argc, char **argv )
jtgafb833d1999-08-19 00:55:39 +0000521{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000522 usage();
523
524 glutInit( &argc, argv );
525 glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
526 glutInitWindowSize( 400, 400 );
527 glutCreateWindow( argv[0] );
528
529 myinit();
530
531 glutDisplayFunc( display );
532 glutReshapeFunc( reshape );
533
534 glutMainLoop();
535
536 return 0;
jtgafb833d1999-08-19 00:55:39 +0000537}