docs: detect when too many varying vars are used
[mesa/nouveau-pmpeg.git] / progs / demos / tessdemo.c
blobf71cea127448ca09e15ad2c416950db21969cbc1
2 /*
3 * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
4 * Updated for GLU 1.3 tessellation by Gareth Hughes <gareth@valinux.com>
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <GL/glut.h>
12 #define MAX_POINTS 256
13 #define MAX_CONTOURS 32
14 #define MAX_TRIANGLES 256
16 #ifndef GLCALLBACK
17 #ifdef CALLBACK
18 #define GLCALLBACK CALLBACK
19 #else
20 #define GLCALLBACK
21 #endif
22 #endif
24 #ifdef GLU_VERSION_1_2
26 typedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
27 typedef enum{ DEFINE, TESSELATED } mode_type;
29 static GLsizei width, height;
30 static GLuint contour_cnt;
31 static GLuint triangle_cnt;
33 static mode_type mode;
34 static int menu;
36 static GLuint list_start;
38 static GLfloat edge_color[3];
40 static struct {
41 GLfloat p[MAX_POINTS][2];
42 GLuint point_cnt;
43 } contours[MAX_CONTOURS];
45 static struct {
46 GLsizei no;
47 GLfloat p[3][2];
48 GLclampf color[3][3];
49 } triangles[MAX_TRIANGLES];
53 static void GLCALLBACK error_callback( GLenum err )
55 int len, i;
56 char const *str;
58 glColor3f( 0.9, 0.9, 0.9 );
59 glRasterPos2i( 5, 5 );
61 str = (const char *) gluErrorString( err );
62 len = strlen( str );
64 for ( i = 0 ; i < len ; i++ ) {
65 glutBitmapCharacter( GLUT_BITMAP_9_BY_15, str[i] );
69 static void GLCALLBACK begin_callback( GLenum mode )
71 /* Allow multiple triangles to be output inside the begin/end pair. */
72 triangle_cnt = 0;
73 triangles[triangle_cnt].no = 0;
76 static void GLCALLBACK edge_callback( GLenum flag )
78 /* Persist the edge flag across triangles. */
79 if ( flag == GL_TRUE ) {
80 edge_color[0] = 1.0;
81 edge_color[1] = 1.0;
82 edge_color[2] = 0.5;
83 } else {
84 edge_color[0] = 1.0;
85 edge_color[1] = 0.0;
86 edge_color[2] = 0.0;
90 static void GLCALLBACK end_callback()
92 GLuint i;
94 glBegin( GL_LINES );
96 /* Output the three edges of each triangle as lines colored
97 according to their edge flag. */
98 for ( i = 0 ; i < triangle_cnt ; i++ ) {
99 glColor3f( triangles[i].color[0][0],
100 triangles[i].color[0][1],
101 triangles[i].color[0][2] );
103 glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
104 glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
106 glColor3f( triangles[i].color[1][0],
107 triangles[i].color[1][1],
108 triangles[i].color[1][2] );
110 glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
111 glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
113 glColor3f( triangles[i].color[2][0],
114 triangles[i].color[2][1],
115 triangles[i].color[2][2] );
117 glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
118 glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
121 glEnd();
124 static void GLCALLBACK vertex_callback( void *data )
126 GLsizei no;
127 GLfloat *p;
129 p = (GLfloat *) data;
130 no = triangles[triangle_cnt].no;
132 triangles[triangle_cnt].p[no][0] = p[0];
133 triangles[triangle_cnt].p[no][1] = p[1];
135 triangles[triangle_cnt].color[no][0] = edge_color[0];
136 triangles[triangle_cnt].color[no][1] = edge_color[1];
137 triangles[triangle_cnt].color[no][2] = edge_color[2];
139 /* After every three vertices, initialize the next triangle. */
140 if ( ++(triangles[triangle_cnt].no) == 3 ) {
141 triangle_cnt++;
142 triangles[triangle_cnt].no = 0;
146 static void GLCALLBACK combine_callback( GLdouble coords[3],
147 GLdouble *vertex_data[4],
148 GLfloat weight[4], void **data )
150 GLfloat *vertex;
152 vertex = (GLfloat *) malloc( 2 * sizeof(GLfloat) );
154 vertex[0] = (GLfloat) coords[0];
155 vertex[1] = (GLfloat) coords[1];
157 *data = vertex;
161 static void set_screen_wh( GLsizei w, GLsizei h )
163 width = w;
164 height = h;
167 typedef void (GLAPIENTRY *callback_t)();
169 static void tesse( void )
171 GLUtesselator *tobj;
172 GLdouble data[3];
173 GLuint i, j, point_cnt;
175 list_start = glGenLists( 2 );
177 tobj = gluNewTess();
179 if ( tobj != NULL ) {
180 gluTessNormal( tobj, 0.0, 0.0, 1.0 );
181 gluTessCallback( tobj, GLU_TESS_BEGIN, (callback_t) glBegin );
182 gluTessCallback( tobj, GLU_TESS_VERTEX, (callback_t) glVertex2fv );
183 gluTessCallback( tobj, GLU_TESS_END, (callback_t) glEnd );
184 gluTessCallback( tobj, GLU_TESS_ERROR, (callback_t) error_callback );
185 gluTessCallback( tobj, GLU_TESS_COMBINE, (callback_t) combine_callback );
187 glNewList( list_start, GL_COMPILE );
188 gluBeginPolygon( tobj );
190 for ( j = 0 ; j <= contour_cnt ; j++ ) {
191 point_cnt = contours[j].point_cnt;
192 gluNextContour( tobj, GLU_UNKNOWN );
194 for ( i = 0 ; i < point_cnt ; i++ ) {
195 data[0] = (GLdouble)( contours[j].p[i][0] );
196 data[1] = (GLdouble)( contours[j].p[i][1] );
197 data[2] = 0.0;
198 gluTessVertex( tobj, data, contours[j].p[i] );
202 gluEndPolygon( tobj );
203 glEndList();
205 gluTessCallback( tobj, GLU_TESS_BEGIN, (callback_t) begin_callback );
206 gluTessCallback( tobj, GLU_TESS_VERTEX, (callback_t) vertex_callback );
207 gluTessCallback( tobj, GLU_TESS_END, (callback_t) end_callback );
208 gluTessCallback( tobj, GLU_TESS_EDGE_FLAG, (callback_t) edge_callback );
210 glNewList( list_start + 1, GL_COMPILE );
211 gluBeginPolygon( tobj );
213 for ( j = 0 ; j <= contour_cnt ; j++ ) {
214 point_cnt = contours[j].point_cnt;
215 gluNextContour( tobj, GLU_UNKNOWN );
217 for ( i = 0 ; i < point_cnt ; i++ ) {
218 data[0] = (GLdouble)( contours[j].p[i][0] );
219 data[1] = (GLdouble)( contours[j].p[i][1] );
220 data[2] = 0.0;
221 gluTessVertex( tobj, data, contours[j].p[i] );
225 gluEndPolygon( tobj );
226 glEndList();
228 gluDeleteTess( tobj );
230 glutMouseFunc( NULL );
231 mode = TESSELATED;
235 static void left_down( int x1, int y1 )
237 GLfloat P[2];
238 GLuint point_cnt;
240 /* translate GLUT into GL coordinates */
242 P[0] = x1;
243 P[1] = height - y1;
245 point_cnt = contours[contour_cnt].point_cnt;
247 contours[contour_cnt].p[point_cnt][0] = P[0];
248 contours[contour_cnt].p[point_cnt][1] = P[1];
250 glBegin( GL_LINES );
252 if ( point_cnt ) {
253 glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
254 glVertex2fv( P );
255 } else {
256 glVertex2fv( P );
257 glVertex2fv( P );
260 glEnd();
261 glFinish();
263 contours[contour_cnt].point_cnt++;
266 static void middle_down( int x1, int y1 )
268 GLuint point_cnt;
269 (void) x1;
270 (void) y1;
272 point_cnt = contours[contour_cnt].point_cnt;
274 if ( point_cnt > 2 ) {
275 glBegin( GL_LINES );
277 glVertex2fv( contours[contour_cnt].p[0] );
278 glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
280 contours[contour_cnt].p[point_cnt][0] = -1;
282 glEnd();
283 glFinish();
285 contour_cnt++;
286 contours[contour_cnt].point_cnt = 0;
290 static void mouse_clicked( int button, int state, int x, int y )
292 x -= x%10;
293 y -= y%10;
295 switch ( button ) {
296 case GLUT_LEFT_BUTTON:
297 if ( state == GLUT_DOWN ) {
298 left_down( x, y );
300 break;
301 case GLUT_MIDDLE_BUTTON:
302 if ( state == GLUT_DOWN ) {
303 middle_down( x, y );
305 break;
309 static void display( void )
311 GLuint i,j;
312 GLsizei ii, jj;
313 GLuint point_cnt;
315 glClear( GL_COLOR_BUFFER_BIT );
317 switch ( mode ) {
318 case DEFINE:
319 /* draw grid */
320 glColor3f( 0.6, 0.5, 0.5 );
322 glBegin( GL_LINES );
324 for ( ii = 0 ; ii < width ; ii += 10 ) {
325 for ( jj = 0 ; jj < height ; jj += 10 ) {
326 glVertex2i( 0, jj );
327 glVertex2i( width, jj );
328 glVertex2i( ii, height );
329 glVertex2i( ii, 0 );
333 glEnd();
335 glColor3f( 1.0, 1.0, 0.0 );
337 for ( i = 0 ; i <= contour_cnt ; i++ ) {
338 point_cnt = contours[i].point_cnt;
340 glBegin( GL_LINES );
342 switch ( point_cnt ) {
343 case 0:
344 break;
345 case 1:
346 glVertex2fv( contours[i].p[0] );
347 glVertex2fv( contours[i].p[0] );
348 break;
349 case 2:
350 glVertex2fv( contours[i].p[0] );
351 glVertex2fv( contours[i].p[1] );
352 break;
353 default:
354 --point_cnt;
355 for ( j = 0 ; j < point_cnt ; j++ ) {
356 glVertex2fv( contours[i].p[j] );
357 glVertex2fv( contours[i].p[j+1] );
359 if ( contours[i].p[j+1][0] == -1 ) {
360 glVertex2fv( contours[i].p[0] );
361 glVertex2fv( contours[i].p[j] );
363 break;
366 glEnd();
369 glFinish();
370 break;
372 case TESSELATED:
373 /* draw triangles */
374 glColor3f( 0.7, 0.7, 0.0 );
375 glCallList( list_start );
377 glLineWidth( 2.0 );
378 glCallList( list_start + 1 );
379 glLineWidth( 1.0 );
381 glFlush();
382 break;
385 glColor3f( 1.0, 1.0, 0.0 );
388 static void clear( void )
390 contour_cnt = 0;
391 contours[0].point_cnt = 0;
392 triangle_cnt = 0;
394 glutMouseFunc( mouse_clicked );
396 mode = DEFINE;
398 glDeleteLists( list_start, 2 );
399 list_start = 0;
402 static void quit( void )
404 exit( 0 );
407 static void menu_selected( int entry )
409 switch ( entry ) {
410 case CLEAR:
411 clear();
412 break;
413 case TESSELATE:
414 tesse();
415 break;
416 case QUIT:
417 quit();
418 break;
421 glutPostRedisplay();
424 static void key_pressed( unsigned char key, int x, int y )
426 (void) x;
427 (void) y;
429 switch ( key ) {
430 case 'c':
431 case 'C':
432 clear();
433 break;
434 case 't':
435 case 'T':
436 tesse();
437 break;
438 case 27:
439 case 'q':
440 case 'Q':
441 quit();
442 break;
445 glutPostRedisplay();
448 static void myinit( void )
450 /* clear background to gray */
451 glClearColor( 0.4, 0.4, 0.4, 0.0 );
452 glShadeModel( GL_FLAT );
453 glPolygonMode( GL_FRONT, GL_FILL );
455 menu = glutCreateMenu( menu_selected );
457 glutAddMenuEntry( "clear", CLEAR );
458 glutAddMenuEntry( "tesselate", TESSELATE );
459 glutAddMenuEntry( "quit", QUIT );
461 glutAttachMenu( GLUT_RIGHT_BUTTON );
463 glutMouseFunc( mouse_clicked );
464 glutKeyboardFunc( key_pressed );
466 contour_cnt = 0;
467 mode = DEFINE;
470 static void reshape( GLsizei w, GLsizei h )
472 glViewport( 0, 0, w, h );
474 glMatrixMode( GL_PROJECTION );
475 glLoadIdentity();
476 glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
478 glMatrixMode( GL_MODELVIEW );
479 glLoadIdentity();
481 set_screen_wh( w, h );
484 #endif
487 static void usage( void )
489 printf( "Use left mouse button to place vertices.\n" );
490 printf( "Press middle mouse button when done.\n" );
491 printf( "Select tesselate from the pop-up menu.\n" );
495 int main( int argc, char **argv )
497 const char *version = (const char *) gluGetString( GLU_VERSION );
498 printf( "GLU version string: %s\n", version );
499 if ( strstr( version, "1.0" ) || strstr( version, "1.1" ) ) {
500 fprintf( stderr, "Sorry, this demo reqiures GLU 1.2 or later.\n" );
501 exit( 1 );
504 usage();
506 glutInit( &argc, argv );
507 glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
508 glutInitWindowPosition(0, 0);
509 glutInitWindowSize( 400, 400 );
510 glutCreateWindow( argv[0] );
512 /* GH: Bit of a hack...
514 #ifdef GLU_VERSION_1_2
515 myinit();
517 glutDisplayFunc( display );
518 glutReshapeFunc( reshape );
520 glutMainLoop();
521 #endif
523 return 0;