blob: 7b3cf9e7025bc5aa535e97e92e0e66f744fe5e7d [file] [log] [blame]
Gareth Hugheseb459c61999-11-04 04:00:42 +00001/* $Id: tessdemo.c,v 1.3 1999/11/04 04:00:42 gareth 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
Gareth Hugheseb459c61999-11-04 04:00:42 +000011/*
12 * Updated for GLU 1.3 tessellation by Gareth Hughes <garethh@bell-labs.com>
13 */
jtgafb833d1999-08-19 00:55:39 +000014
15/*
16 * $Log: tessdemo.c,v $
Gareth Hugheseb459c61999-11-04 04:00:42 +000017 * Revision 1.3 1999/11/04 04:00:42 gareth
18 * Updated demo for new GLU 1.3 tessellation. Added optimized rendering
19 * by saving the output of the tessellation into display lists.
20 *
tannerbc34adf1999-09-19 20:09:00 +000021 * Revision 1.2 1999/09/19 20:09:00 tanner
22 *
23 * lots of autoconf updates
24 *
25 * Revision 1.1.1.1 1999/08/19 00:55:40 jtg
26 * Imported sources
jtgafb833d1999-08-19 00:55:39 +000027 *
28 * Revision 3.5 1999/03/28 18:24:37 brianp
29 * minor clean-up
30 *
31 * Revision 3.4 1999/02/14 03:37:07 brianp
32 * fixed callback problem
33 *
34 * Revision 3.3 1998/07/26 01:25:26 brianp
35 * removed include of gl.h and glu.h
36 *
37 * Revision 3.2 1998/06/29 02:37:30 brianp
38 * minor changes for Windows (Ted Jump)
39 *
40 * Revision 3.1 1998/06/09 01:53:49 brianp
41 * main() should return an int
42 *
43 * Revision 3.0 1998/02/14 18:42:29 brianp
44 * initial rev
45 *
46 */
47
48
49#include <GL/glut.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53
Gareth Hugheseb459c61999-11-04 04:00:42 +000054#define MAX_POINTS 256
55#define MAX_CONTOURS 32
56#define MAX_TRIANGLES 256
jtgafb833d1999-08-19 00:55:39 +000057
58#ifndef GLCALLBACK
59#ifdef CALLBACK
60#define GLCALLBACK CALLBACK
61#else
62#define GLCALLBACK
63#endif
64#endif
65
Gareth Hugheseb459c61999-11-04 04:00:42 +000066typedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
67typedef enum{ DEFINE, TESSELATED } mode_type;
jtgafb833d1999-08-19 00:55:39 +000068
Gareth Hugheseb459c61999-11-04 04:00:42 +000069static GLsizei width, height;
70static GLuint contour_cnt;
71static GLuint triangle_cnt;
72
73static mode_type mode;
74static int menu;
75
76static GLuint list_start;
77
78static GLfloat edge_color[3];
79
80static struct
jtgafb833d1999-08-19 00:55:39 +000081{
Gareth Hugheseb459c61999-11-04 04:00:42 +000082 GLint p[MAX_POINTS][2];
83 GLuint point_cnt;
84} contours[MAX_CONTOURS];
jtgafb833d1999-08-19 00:55:39 +000085
Gareth Hugheseb459c61999-11-04 04:00:42 +000086static struct
87{
88 GLsizei no;
89 GLint p[3][2];
90 GLclampf color[3][3];
91} triangles[MAX_TRIANGLES];
92
93
94
95void GLCALLBACK my_error( GLenum err )
96{
97 int len, i;
98 char const *str;
99
100 glColor3f( 0.9, 0.9, 0.9 );
101 glRasterPos2i( 5, 5 );
102
103 str = (const char *) gluErrorString( err );
104 len = strlen( str );
105
106 for ( i = 0 ; i < len ; i++ ) {
107 glutBitmapCharacter( GLUT_BITMAP_9_BY_15, str[i] );
108 }
jtgafb833d1999-08-19 00:55:39 +0000109}
110
Gareth Hugheseb459c61999-11-04 04:00:42 +0000111void GLCALLBACK begin_callback( GLenum mode )
jtgafb833d1999-08-19 00:55:39 +0000112{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000113 /* Allow multiple triangles to be output inside the begin/end pair. */
114 triangle_cnt = 0;
115 triangles[triangle_cnt].no = 0;
jtgafb833d1999-08-19 00:55:39 +0000116}
117
Gareth Hugheseb459c61999-11-04 04:00:42 +0000118void GLCALLBACK edge_callback( GLenum flag )
jtgafb833d1999-08-19 00:55:39 +0000119{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000120 /* Persist the edge flag across triangles. */
121 if ( flag == GL_TRUE )
122 {
123 edge_color[0] = 1.0;
124 edge_color[1] = 1.0;
125 edge_color[2] = 0.5;
126 }
127 else
128 {
129 edge_color[0] = 1.0;
130 edge_color[1] = 0.0;
131 edge_color[2] = 0.0;
132 }
jtgafb833d1999-08-19 00:55:39 +0000133}
134
135void GLCALLBACK end_callback()
136{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000137 GLint i;
138
139 glBegin( GL_LINES );
140
141 /* Output the three edges of each triangle as lines colored
142 according to their edge flag. */
143 for ( i = 0 ; i < triangle_cnt ; i++ )
144 {
145 glColor3f( triangles[i].color[0][0],
146 triangles[i].color[0][1],
147 triangles[i].color[0][2] );
148
149 glVertex2i( triangles[i].p[0][0], triangles[i].p[0][1] );
150 glVertex2i( triangles[i].p[1][0], triangles[i].p[1][1] );
151
152 glColor3f( triangles[i].color[1][0],
153 triangles[i].color[1][1],
154 triangles[i].color[1][2] );
155
156 glVertex2i( triangles[i].p[1][0], triangles[i].p[1][1] );
157 glVertex2i( triangles[i].p[2][0], triangles[i].p[2][1] );
158
159 glColor3f( triangles[i].color[2][0],
160 triangles[i].color[2][1],
161 triangles[i].color[2][2] );
162
163 glVertex2i( triangles[i].p[2][0], triangles[i].p[2][1] );
164 glVertex2i( triangles[i].p[0][0], triangles[i].p[0][1] );
165 }
166
167 glEnd();
jtgafb833d1999-08-19 00:55:39 +0000168}
169
Gareth Hugheseb459c61999-11-04 04:00:42 +0000170void GLCALLBACK vertex_callback( void *data )
jtgafb833d1999-08-19 00:55:39 +0000171{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000172 GLsizei no;
173 GLint *p;
jtgafb833d1999-08-19 00:55:39 +0000174
Gareth Hugheseb459c61999-11-04 04:00:42 +0000175 p = (GLint *) data;
176 no = triangles[triangle_cnt].no;
177
178 triangles[triangle_cnt].p[no][0] = p[0];
179 triangles[triangle_cnt].p[no][1] = p[1];
180
181 triangles[triangle_cnt].color[no][0] = edge_color[0];
182 triangles[triangle_cnt].color[no][1] = edge_color[1];
183 triangles[triangle_cnt].color[no][2] = edge_color[2];
184
185 /* After every three vertices, initialize the next triangle. */
186 if ( ++(triangles[triangle_cnt].no) == 3 )
187 {
188 triangle_cnt++;
189 triangles[triangle_cnt].no = 0;
190 }
jtgafb833d1999-08-19 00:55:39 +0000191}
192
Gareth Hugheseb459c61999-11-04 04:00:42 +0000193void set_screen_wh( GLsizei w, GLsizei h )
jtgafb833d1999-08-19 00:55:39 +0000194{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000195 width = w;
196 height = h;
jtgafb833d1999-08-19 00:55:39 +0000197}
198
Gareth Hugheseb459c61999-11-04 04:00:42 +0000199void tesse( void )
jtgafb833d1999-08-19 00:55:39 +0000200{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000201 GLUtesselator *tobj;
202 GLdouble data[3];
203 GLuint i, j, point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000204
Gareth Hugheseb459c61999-11-04 04:00:42 +0000205 list_start = glGenLists( 2 );
206
207 tobj = gluNewTess();
208
209 if ( tobj != NULL )
210 {
211 gluTessCallback( tobj, GLU_BEGIN, glBegin );
212 gluTessCallback( tobj, GLU_VERTEX, glVertex2iv );
213 gluTessCallback( tobj, GLU_END, glEnd );
214 gluTessCallback( tobj, GLU_ERROR, my_error );
215
216 glNewList( list_start, GL_COMPILE );
217 gluBeginPolygon( tobj );
218
219 for ( j = 0 ; j <= contour_cnt ; j++ )
220 {
221 point_cnt = contours[j].point_cnt;
222 gluNextContour( tobj, GLU_UNKNOWN );
223
224 for ( i = 0 ; i < point_cnt ; i++ )
225 {
226 data[0] = (GLdouble)( contours[j].p[i][0] );
227 data[1] = (GLdouble)( contours[j].p[i][1] );
228 data[2] = 0.0;
229 gluTessVertex( tobj, data, contours[j].p[i] );
230 }
231 }
232
233 gluEndPolygon( tobj );
234 glEndList();
235
236 gluTessCallback( tobj, GLU_BEGIN, begin_callback );
237 gluTessCallback( tobj, GLU_VERTEX, vertex_callback );
238 gluTessCallback( tobj, GLU_END, end_callback );
239 gluTessCallback( tobj, GLU_EDGE_FLAG, edge_callback );
240
241 glNewList( list_start + 1, GL_COMPILE );
242 gluBeginPolygon( tobj );
243
244 for ( j = 0 ; j <= contour_cnt ; j++ )
245 {
246 point_cnt = contours[j].point_cnt;
247 gluNextContour( tobj, GLU_UNKNOWN );
248
249 for ( i = 0 ; i < point_cnt ; i++ )
250 {
251 data[0] = (GLdouble)( contours[j].p[i][0] );
252 data[1] = (GLdouble)( contours[j].p[i][1] );
253 data[2] = 0.0;
254 gluTessVertex( tobj, data, contours[j].p[i] );
255 }
256 }
257
258 gluEndPolygon( tobj );
259 glEndList();
260
261 gluDeleteTess( tobj );
262
263 glutMouseFunc( NULL );
264 mode = TESSELATED;
265 }
jtgafb833d1999-08-19 00:55:39 +0000266}
267
Gareth Hugheseb459c61999-11-04 04:00:42 +0000268void left_down( int x1, int y1 )
jtgafb833d1999-08-19 00:55:39 +0000269{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000270 GLint P[2];
271 GLuint point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000272
Gareth Hugheseb459c61999-11-04 04:00:42 +0000273 /* translate GLUT into GL coordinates */
274
275 P[0] = x1;
276 P[1] = height - y1;
277
278 point_cnt = contours[contour_cnt].point_cnt;
279
280 contours[contour_cnt].p[point_cnt][0] = P[0];
281 contours[contour_cnt].p[point_cnt][1] = P[1];
282
283 glBegin( GL_LINES );
284
285 if ( point_cnt )
286 {
287 glVertex2iv( contours[contour_cnt].p[point_cnt-1] );
288 glVertex2iv( P );
289 }
290 else
291 {
292 glVertex2iv( P );
293 glVertex2iv( P );
294 }
295
296 glEnd();
297 glFinish();
298
299 contours[contour_cnt].point_cnt++;
jtgafb833d1999-08-19 00:55:39 +0000300}
301
Gareth Hugheseb459c61999-11-04 04:00:42 +0000302void middle_down( int x1, int y1 )
jtgafb833d1999-08-19 00:55:39 +0000303{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000304 GLuint point_cnt;
305 (void) x1;
306 (void) y1;
jtgafb833d1999-08-19 00:55:39 +0000307
Gareth Hugheseb459c61999-11-04 04:00:42 +0000308 point_cnt = contours[contour_cnt].point_cnt;
309
310 if ( point_cnt > 2 )
311 {
312 glBegin( GL_LINES );
313
314 glVertex2iv( contours[contour_cnt].p[0] );
315 glVertex2iv( contours[contour_cnt].p[point_cnt-1] );
316
317 contours[contour_cnt].p[point_cnt][0] = -1;
318
319 glEnd();
320 glFinish();
321
322 contour_cnt++;
323 contours[contour_cnt].point_cnt = 0;
324 }
jtgafb833d1999-08-19 00:55:39 +0000325}
326
Gareth Hugheseb459c61999-11-04 04:00:42 +0000327void mouse_clicked( int button, int state, int x, int y )
jtgafb833d1999-08-19 00:55:39 +0000328{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000329 x -= x%10;
330 y -= y%10;
331
332 switch ( button )
333 {
334 case GLUT_LEFT_BUTTON:
335 if ( state == GLUT_DOWN ) {
336 left_down( x, y );
337 }
338 break;
339 case GLUT_MIDDLE_BUTTON:
340 if ( state == GLUT_DOWN ) {
341 middle_down( x, y );
342 }
343 break;
344 }
jtgafb833d1999-08-19 00:55:39 +0000345}
346
Gareth Hugheseb459c61999-11-04 04:00:42 +0000347void display( void )
jtgafb833d1999-08-19 00:55:39 +0000348{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000349 GLuint i,j;
350 GLuint point_cnt;
jtgafb833d1999-08-19 00:55:39 +0000351
Gareth Hugheseb459c61999-11-04 04:00:42 +0000352 glClear( GL_COLOR_BUFFER_BIT );
jtgafb833d1999-08-19 00:55:39 +0000353
Gareth Hugheseb459c61999-11-04 04:00:42 +0000354 switch ( mode )
355 {
356 case DEFINE:
357 /* draw grid */
358 glColor3f( 0.6, 0.5, 0.5 );
359
360 glBegin( GL_LINES );
361
362 for ( i = 0 ; i < width ; i += 10 )
363 {
364 for ( j = 0 ; j < height ; j += 10 )
365 {
366 glVertex2i( 0, j );
367 glVertex2i( width, j );
368 glVertex2i( i, height );
369 glVertex2i( i, 0 );
370 }
371 }
372
373 glColor3f( 1.0, 1.0, 0.0 );
374
375 for ( i = 0 ; i <= contour_cnt ; i++ )
376 {
377 point_cnt = contours[i].point_cnt;
378
379 glBegin( GL_LINES );
380
381 switch ( point_cnt )
382 {
383 case 0:
384 break;
385 case 1:
386 glVertex2iv( contours[i].p[0] );
387 glVertex2iv( contours[i].p[0] );
388 break;
389 case 2:
390 glVertex2iv( contours[i].p[0] );
391 glVertex2iv( contours[i].p[1] );
392 break;
393 default:
394 --point_cnt;
395 for ( j = 0 ; j < point_cnt ; j++ )
396 {
397 glVertex2iv( contours[i].p[j] );
398 glVertex2iv( contours[i].p[j+1] );
399 }
400 if ( contours[i].p[j+1][0] == -1 )
401 {
402 glVertex2iv( contours[i].p[0] );
403 glVertex2iv( contours[i].p[j] );
404 }
405 break;
406 }
407
408 glEnd();
409 }
410
411 glFinish();
412 break;
413
414 case TESSELATED:
415 /* draw triangles */
416 glColor3f( 0.7, 0.7, 0.0 );
417 glCallList( list_start );
418
419 glLineWidth( 2.0 );
420 glCallList( list_start + 1 );
421 glLineWidth( 1.0 );
422
423 glFlush();
424 break;
425 }
426
427 glColor3f( 1.0, 1.0, 0.0 );
jtgafb833d1999-08-19 00:55:39 +0000428}
429
430void clear( void )
431{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000432 contour_cnt = 0;
433 contours[0].point_cnt = 0;
434 triangle_cnt = 0;
435
436 glutMouseFunc( mouse_clicked );
437
438 mode = DEFINE;
439
440 glDeleteLists( list_start, 2 );
441 list_start = 0;
jtgafb833d1999-08-19 00:55:39 +0000442}
443
444void quit( void )
445{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000446 exit( 0 );
jtgafb833d1999-08-19 00:55:39 +0000447}
448
Gareth Hugheseb459c61999-11-04 04:00:42 +0000449void menu_selected( int entry )
jtgafb833d1999-08-19 00:55:39 +0000450{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000451 switch ( entry )
452 {
453 case CLEAR:
454 clear();
455 break;
456 case TESSELATE:
457 tesse();
458 break;
459 case QUIT:
460 quit();
461 break;
462 }
463
464 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000465}
466
Gareth Hugheseb459c61999-11-04 04:00:42 +0000467void key_pressed( unsigned char key, int x, int y )
jtgafb833d1999-08-19 00:55:39 +0000468{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000469 (void) x;
470 (void) y;
471
472 switch ( key )
473 {
474 case 'c':
475 case 'C':
476 clear();
477 break;
478 case 't':
479 case 'T':
480 tesse();
481 break;
482 case 'q':
483 case 'Q':
484 quit();
485 break;
486 }
487
488 glutPostRedisplay();
jtgafb833d1999-08-19 00:55:39 +0000489}
490
Gareth Hugheseb459c61999-11-04 04:00:42 +0000491void myinit( void )
jtgafb833d1999-08-19 00:55:39 +0000492{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000493 /* clear background to gray */
494 glClearColor( 0.4, 0.4, 0.4, 0.0 );
495 glShadeModel( GL_FLAT );
496 glPolygonMode( GL_FRONT, GL_FILL );
jtgafb833d1999-08-19 00:55:39 +0000497
Gareth Hugheseb459c61999-11-04 04:00:42 +0000498 menu = glutCreateMenu( menu_selected );
499
500 glutAddMenuEntry( "clear", CLEAR );
501 glutAddMenuEntry( "tesselate", TESSELATE );
502 glutAddMenuEntry( "quit", QUIT );
503
504 glutAttachMenu( GLUT_RIGHT_BUTTON );
505
506 glutMouseFunc( mouse_clicked );
507 glutKeyboardFunc( key_pressed );
508
509 contour_cnt = 0;
510 mode = DEFINE;
jtgafb833d1999-08-19 00:55:39 +0000511}
512
Gareth Hugheseb459c61999-11-04 04:00:42 +0000513static void reshape( GLsizei w, GLsizei h )
jtgafb833d1999-08-19 00:55:39 +0000514{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000515 glViewport( 0, 0, w, h );
516
517 glMatrixMode( GL_PROJECTION );
518 glLoadIdentity();
519 glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
520
521 glMatrixMode( GL_MODELVIEW );
522 glLoadIdentity();
523
524 set_screen_wh( w, h );
jtgafb833d1999-08-19 00:55:39 +0000525}
526
527
528static void usage( void )
529{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000530 printf( "Use left mouse button to place vertices.\n" );
531 printf( "Press middle mouse button when done.\n" );
532 printf( "Select tesselate from the pop-up menu.\n" );
jtgafb833d1999-08-19 00:55:39 +0000533}
534
535
Gareth Hugheseb459c61999-11-04 04:00:42 +0000536/*
537 * Main Loop
538 * Open window with initial window size, title bar,
539 * RGBA display mode, and handle input events.
jtgafb833d1999-08-19 00:55:39 +0000540 */
Gareth Hugheseb459c61999-11-04 04:00:42 +0000541int main( int argc, char **argv )
jtgafb833d1999-08-19 00:55:39 +0000542{
Gareth Hugheseb459c61999-11-04 04:00:42 +0000543 usage();
544
545 glutInit( &argc, argv );
546 glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
547 glutInitWindowSize( 400, 400 );
548 glutCreateWindow( argv[0] );
549
550 myinit();
551
552 glutDisplayFunc( display );
553 glutReshapeFunc( reshape );
554
555 glutMainLoop();
556
557 return 0;
jtgafb833d1999-08-19 00:55:39 +0000558}