1 /* $Id: tessdemo.c,v 1.7 2000/06/27 17:04:43 brianp Exp $ */
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>
13 #define MAX_POINTS 256
14 #define MAX_CONTOURS 32
15 #define MAX_TRIANGLES 256
19 #define GLCALLBACK CALLBACK
25 typedef enum{ QUIT
, TESSELATE
, CLEAR
} menu_entries
;
26 typedef enum{ DEFINE
, TESSELATED
} mode_type
;
28 static GLsizei width
, height
;
29 static GLuint contour_cnt
;
30 static GLuint triangle_cnt
;
32 static mode_type mode
;
35 static GLuint list_start
;
37 static GLfloat edge_color
[3];
41 GLfloat p
[MAX_POINTS
][2];
43 } contours
[MAX_CONTOURS
];
50 } triangles
[MAX_TRIANGLES
];
54 static void GLCALLBACK
error_callback( GLenum err
)
59 glColor3f( 0.9, 0.9, 0.9 );
60 glRasterPos2i( 5, 5 );
62 str
= (const char *) gluErrorString( err
);
65 for ( i
= 0 ; i
< len
; i
++ ) {
66 glutBitmapCharacter( GLUT_BITMAP_9_BY_15
, str
[i
] );
70 static void GLCALLBACK
begin_callback( GLenum mode
)
72 /* Allow multiple triangles to be output inside the begin/end pair. */
74 triangles
[triangle_cnt
].no
= 0;
77 static void GLCALLBACK
edge_callback( GLenum flag
)
79 /* Persist the edge flag across triangles. */
80 if ( flag
== GL_TRUE
)
94 static void GLCALLBACK
end_callback()
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
++ )
104 glColor3f( triangles
[i
].color
[0][0],
105 triangles
[i
].color
[0][1],
106 triangles
[i
].color
[0][2] );
108 glVertex2f( triangles
[i
].p
[0][0], triangles
[i
].p
[0][1] );
109 glVertex2f( triangles
[i
].p
[1][0], triangles
[i
].p
[1][1] );
111 glColor3f( triangles
[i
].color
[1][0],
112 triangles
[i
].color
[1][1],
113 triangles
[i
].color
[1][2] );
115 glVertex2f( triangles
[i
].p
[1][0], triangles
[i
].p
[1][1] );
116 glVertex2f( triangles
[i
].p
[2][0], triangles
[i
].p
[2][1] );
118 glColor3f( triangles
[i
].color
[2][0],
119 triangles
[i
].color
[2][1],
120 triangles
[i
].color
[2][2] );
122 glVertex2f( triangles
[i
].p
[2][0], triangles
[i
].p
[2][1] );
123 glVertex2f( triangles
[i
].p
[0][0], triangles
[i
].p
[0][1] );
129 static void GLCALLBACK
vertex_callback( void *data
)
134 p
= (GLfloat
*) data
;
135 no
= triangles
[triangle_cnt
].no
;
137 triangles
[triangle_cnt
].p
[no
][0] = p
[0];
138 triangles
[triangle_cnt
].p
[no
][1] = p
[1];
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];
144 /* After every three vertices, initialize the next triangle. */
145 if ( ++(triangles
[triangle_cnt
].no
) == 3 )
148 triangles
[triangle_cnt
].no
= 0;
152 static void GLCALLBACK
combine_callback( GLdouble coords
[3],
153 GLdouble
*vertex_data
[4],
154 GLfloat weight
[4], void **data
)
158 vertex
= (GLfloat
*) malloc( 2 * sizeof(GLfloat
) );
160 vertex
[0] = (GLfloat
) coords
[0];
161 vertex
[1] = (GLfloat
) coords
[1];
167 static void set_screen_wh( GLsizei w
, GLsizei h
)
173 static void tesse( void )
177 GLuint i
, j
, point_cnt
;
179 list_start
= glGenLists( 2 );
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
);
192 glNewList( list_start
, GL_COMPILE
);
193 gluBeginPolygon( tobj
);
195 for ( j
= 0 ; j
<= contour_cnt
; j
++ )
197 point_cnt
= contours
[j
].point_cnt
;
198 gluNextContour( tobj
, GLU_UNKNOWN
);
200 for ( i
= 0 ; i
< point_cnt
; i
++ )
202 data
[0] = (GLdouble
)( contours
[j
].p
[i
][0] );
203 data
[1] = (GLdouble
)( contours
[j
].p
[i
][1] );
205 gluTessVertex( tobj
, data
, contours
[j
].p
[i
] );
209 gluEndPolygon( tobj
);
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
);
217 glNewList( list_start
+ 1, GL_COMPILE
);
218 gluBeginPolygon( tobj
);
220 for ( j
= 0 ; j
<= contour_cnt
; j
++ )
222 point_cnt
= contours
[j
].point_cnt
;
223 gluNextContour( tobj
, GLU_UNKNOWN
);
225 for ( i
= 0 ; i
< point_cnt
; i
++ )
227 data
[0] = (GLdouble
)( contours
[j
].p
[i
][0] );
228 data
[1] = (GLdouble
)( contours
[j
].p
[i
][1] );
230 gluTessVertex( tobj
, data
, contours
[j
].p
[i
] );
234 gluEndPolygon( tobj
);
237 gluDeleteTess( tobj
);
239 glutMouseFunc( NULL
);
244 static void left_down( int x1
, int y1
)
249 /* translate GLUT into GL coordinates */
254 point_cnt
= contours
[contour_cnt
].point_cnt
;
256 contours
[contour_cnt
].p
[point_cnt
][0] = P
[0];
257 contours
[contour_cnt
].p
[point_cnt
][1] = P
[1];
263 glVertex2fv( contours
[contour_cnt
].p
[point_cnt
-1] );
275 contours
[contour_cnt
].point_cnt
++;
278 static void middle_down( int x1
, int y1
)
284 point_cnt
= contours
[contour_cnt
].point_cnt
;
290 glVertex2fv( contours
[contour_cnt
].p
[0] );
291 glVertex2fv( contours
[contour_cnt
].p
[point_cnt
-1] );
293 contours
[contour_cnt
].p
[point_cnt
][0] = -1;
299 contours
[contour_cnt
].point_cnt
= 0;
303 static void mouse_clicked( int button
, int state
, int x
, int y
)
310 case GLUT_LEFT_BUTTON
:
311 if ( state
== GLUT_DOWN
) {
315 case GLUT_MIDDLE_BUTTON
:
316 if ( state
== GLUT_DOWN
) {
323 static void display( void )
328 glClear( GL_COLOR_BUFFER_BIT
);
334 glColor3f( 0.6, 0.5, 0.5 );
338 for ( i
= 0 ; i
< width
; i
+= 10 )
340 for ( j
= 0 ; j
< height
; j
+= 10 )
343 glVertex2i( width
, j
);
344 glVertex2i( i
, height
);
351 glColor3f( 1.0, 1.0, 0.0 );
353 for ( i
= 0 ; i
<= contour_cnt
; i
++ )
355 point_cnt
= contours
[i
].point_cnt
;
364 glVertex2fv( contours
[i
].p
[0] );
365 glVertex2fv( contours
[i
].p
[0] );
368 glVertex2fv( contours
[i
].p
[0] );
369 glVertex2fv( contours
[i
].p
[1] );
373 for ( j
= 0 ; j
< point_cnt
; j
++ )
375 glVertex2fv( contours
[i
].p
[j
] );
376 glVertex2fv( contours
[i
].p
[j
+1] );
378 if ( contours
[i
].p
[j
+1][0] == -1 )
380 glVertex2fv( contours
[i
].p
[0] );
381 glVertex2fv( contours
[i
].p
[j
] );
394 glColor3f( 0.7, 0.7, 0.0 );
395 glCallList( list_start
);
398 glCallList( list_start
+ 1 );
405 glColor3f( 1.0, 1.0, 0.0 );
408 static void clear( void )
411 contours
[0].point_cnt
= 0;
414 glutMouseFunc( mouse_clicked
);
418 glDeleteLists( list_start
, 2 );
422 static void quit( void )
427 static void menu_selected( int entry
)
445 static void key_pressed( unsigned char key
, int x
, int y
)
469 static void myinit( void )
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
);
476 menu
= glutCreateMenu( menu_selected
);
478 glutAddMenuEntry( "clear", CLEAR
);
479 glutAddMenuEntry( "tesselate", TESSELATE
);
480 glutAddMenuEntry( "quit", QUIT
);
482 glutAttachMenu( GLUT_RIGHT_BUTTON
);
484 glutMouseFunc( mouse_clicked
);
485 glutKeyboardFunc( key_pressed
);
491 static void reshape( GLsizei w
, GLsizei h
)
493 glViewport( 0, 0, w
, h
);
495 glMatrixMode( GL_PROJECTION
);
497 glOrtho( 0.0, (GLdouble
)w
, 0.0, (GLdouble
)h
, -1.0, 1.0 );
499 glMatrixMode( GL_MODELVIEW
);
502 set_screen_wh( w
, h
);
506 static void usage( void )
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" );
516 * Open window with initial window size, title bar,
517 * RGBA display mode, and handle input events.
519 int main( int argc
, char **argv
)
523 glutInit( &argc
, argv
);
524 glutInitDisplayMode( GLUT_SINGLE
| GLUT_RGB
);
525 glutInitWindowSize( 400, 400 );
526 glutCreateWindow( argv
[0] );
530 glutDisplayFunc( display
);
531 glutReshapeFunc( reshape
);