1 /* $Id: tessdemo.c,v 1.13 2002/10/18 17:47:36 kschultz Exp $ */
4 * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
5 * Updated for GLU 1.3 tessellation by Gareth Hughes <gareth@valinux.com>
13 #define MAX_POINTS 256
14 #define MAX_CONTOURS 32
15 #define MAX_TRIANGLES 256
19 #define GLCALLBACK CALLBACK
25 #ifdef GLU_VERSION_1_2
27 typedef enum{ QUIT
, TESSELATE
, CLEAR
} menu_entries
;
28 typedef enum{ DEFINE
, TESSELATED
} mode_type
;
30 static GLsizei width
, height
;
31 static GLuint contour_cnt
;
32 static GLuint triangle_cnt
;
34 static mode_type mode
;
37 static GLuint list_start
;
39 static GLfloat edge_color
[3];
42 GLfloat p
[MAX_POINTS
][2];
44 } 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
) {
91 static void GLCALLBACK
end_callback()
97 /* Output the three edges of each triangle as lines colored
98 according to their edge flag. */
99 for ( i
= 0 ; i
< triangle_cnt
; i
++ ) {
100 glColor3f( triangles
[i
].color
[0][0],
101 triangles
[i
].color
[0][1],
102 triangles
[i
].color
[0][2] );
104 glVertex2f( triangles
[i
].p
[0][0], triangles
[i
].p
[0][1] );
105 glVertex2f( triangles
[i
].p
[1][0], triangles
[i
].p
[1][1] );
107 glColor3f( triangles
[i
].color
[1][0],
108 triangles
[i
].color
[1][1],
109 triangles
[i
].color
[1][2] );
111 glVertex2f( triangles
[i
].p
[1][0], triangles
[i
].p
[1][1] );
112 glVertex2f( triangles
[i
].p
[2][0], triangles
[i
].p
[2][1] );
114 glColor3f( triangles
[i
].color
[2][0],
115 triangles
[i
].color
[2][1],
116 triangles
[i
].color
[2][2] );
118 glVertex2f( triangles
[i
].p
[2][0], triangles
[i
].p
[2][1] );
119 glVertex2f( triangles
[i
].p
[0][0], triangles
[i
].p
[0][1] );
125 static void GLCALLBACK
vertex_callback( void *data
)
130 p
= (GLfloat
*) data
;
131 no
= triangles
[triangle_cnt
].no
;
133 triangles
[triangle_cnt
].p
[no
][0] = p
[0];
134 triangles
[triangle_cnt
].p
[no
][1] = p
[1];
136 triangles
[triangle_cnt
].color
[no
][0] = edge_color
[0];
137 triangles
[triangle_cnt
].color
[no
][1] = edge_color
[1];
138 triangles
[triangle_cnt
].color
[no
][2] = edge_color
[2];
140 /* After every three vertices, initialize the next triangle. */
141 if ( ++(triangles
[triangle_cnt
].no
) == 3 ) {
143 triangles
[triangle_cnt
].no
= 0;
147 static void GLCALLBACK
combine_callback( GLdouble coords
[3],
148 GLdouble
*vertex_data
[4],
149 GLfloat weight
[4], void **data
)
153 vertex
= (GLfloat
*) malloc( 2 * sizeof(GLfloat
) );
155 vertex
[0] = (GLfloat
) coords
[0];
156 vertex
[1] = (GLfloat
) coords
[1];
162 static void set_screen_wh( GLsizei w
, GLsizei h
)
168 typedef void (GLAPIENTRY
*callback_t
)();
170 static void tesse( void )
174 GLuint i
, j
, point_cnt
;
176 list_start
= glGenLists( 2 );
180 if ( tobj
!= NULL
) {
181 gluTessNormal( tobj
, 0.0, 0.0, 1.0 );
182 gluTessCallback( tobj
, GLU_TESS_BEGIN
, (callback_t
) glBegin
);
183 gluTessCallback( tobj
, GLU_TESS_VERTEX
, (callback_t
) glVertex2fv
);
184 gluTessCallback( tobj
, GLU_TESS_END
, (callback_t
) glEnd
);
185 gluTessCallback( tobj
, GLU_TESS_ERROR
, (callback_t
) error_callback
);
186 gluTessCallback( tobj
, GLU_TESS_COMBINE
, (callback_t
) combine_callback
);
188 glNewList( list_start
, GL_COMPILE
);
189 gluBeginPolygon( tobj
);
191 for ( j
= 0 ; j
<= contour_cnt
; j
++ ) {
192 point_cnt
= contours
[j
].point_cnt
;
193 gluNextContour( tobj
, GLU_UNKNOWN
);
195 for ( i
= 0 ; i
< point_cnt
; i
++ ) {
196 data
[0] = (GLdouble
)( contours
[j
].p
[i
][0] );
197 data
[1] = (GLdouble
)( contours
[j
].p
[i
][1] );
199 gluTessVertex( tobj
, data
, contours
[j
].p
[i
] );
203 gluEndPolygon( tobj
);
206 gluTessCallback( tobj
, GLU_TESS_BEGIN
, (callback_t
) begin_callback
);
207 gluTessCallback( tobj
, GLU_TESS_VERTEX
, (callback_t
) vertex_callback
);
208 gluTessCallback( tobj
, GLU_TESS_END
, (callback_t
) end_callback
);
209 gluTessCallback( tobj
, GLU_TESS_EDGE_FLAG
, (callback_t
) edge_callback
);
211 glNewList( list_start
+ 1, GL_COMPILE
);
212 gluBeginPolygon( tobj
);
214 for ( j
= 0 ; j
<= contour_cnt
; j
++ ) {
215 point_cnt
= contours
[j
].point_cnt
;
216 gluNextContour( tobj
, GLU_UNKNOWN
);
218 for ( i
= 0 ; i
< point_cnt
; i
++ ) {
219 data
[0] = (GLdouble
)( contours
[j
].p
[i
][0] );
220 data
[1] = (GLdouble
)( contours
[j
].p
[i
][1] );
222 gluTessVertex( tobj
, data
, contours
[j
].p
[i
] );
226 gluEndPolygon( tobj
);
229 gluDeleteTess( tobj
);
231 glutMouseFunc( NULL
);
236 static void left_down( int x1
, int y1
)
241 /* translate GLUT into GL coordinates */
246 point_cnt
= contours
[contour_cnt
].point_cnt
;
248 contours
[contour_cnt
].p
[point_cnt
][0] = P
[0];
249 contours
[contour_cnt
].p
[point_cnt
][1] = P
[1];
254 glVertex2fv( contours
[contour_cnt
].p
[point_cnt
-1] );
264 contours
[contour_cnt
].point_cnt
++;
267 static void middle_down( int x1
, int y1
)
273 point_cnt
= contours
[contour_cnt
].point_cnt
;
275 if ( point_cnt
> 2 ) {
278 glVertex2fv( contours
[contour_cnt
].p
[0] );
279 glVertex2fv( contours
[contour_cnt
].p
[point_cnt
-1] );
281 contours
[contour_cnt
].p
[point_cnt
][0] = -1;
287 contours
[contour_cnt
].point_cnt
= 0;
291 static void mouse_clicked( int button
, int state
, int x
, int y
)
297 case GLUT_LEFT_BUTTON
:
298 if ( state
== GLUT_DOWN
) {
302 case GLUT_MIDDLE_BUTTON
:
303 if ( state
== GLUT_DOWN
) {
310 static void display( void )
316 glClear( GL_COLOR_BUFFER_BIT
);
321 glColor3f( 0.6, 0.5, 0.5 );
325 for ( ii
= 0 ; ii
< width
; ii
+= 10 ) {
326 for ( jj
= 0 ; jj
< height
; jj
+= 10 ) {
328 glVertex2i( width
, jj
);
329 glVertex2i( ii
, height
);
336 glColor3f( 1.0, 1.0, 0.0 );
338 for ( i
= 0 ; i
<= contour_cnt
; i
++ ) {
339 point_cnt
= contours
[i
].point_cnt
;
343 switch ( point_cnt
) {
347 glVertex2fv( contours
[i
].p
[0] );
348 glVertex2fv( contours
[i
].p
[0] );
351 glVertex2fv( contours
[i
].p
[0] );
352 glVertex2fv( contours
[i
].p
[1] );
356 for ( j
= 0 ; j
< point_cnt
; j
++ ) {
357 glVertex2fv( contours
[i
].p
[j
] );
358 glVertex2fv( contours
[i
].p
[j
+1] );
360 if ( contours
[i
].p
[j
+1][0] == -1 ) {
361 glVertex2fv( contours
[i
].p
[0] );
362 glVertex2fv( contours
[i
].p
[j
] );
375 glColor3f( 0.7, 0.7, 0.0 );
376 glCallList( list_start
);
379 glCallList( list_start
+ 1 );
386 glColor3f( 1.0, 1.0, 0.0 );
389 static void clear( void )
392 contours
[0].point_cnt
= 0;
395 glutMouseFunc( mouse_clicked
);
399 glDeleteLists( list_start
, 2 );
403 static void quit( void )
408 static void menu_selected( int entry
)
425 static void key_pressed( unsigned char key
, int x
, int y
)
449 static void myinit( void )
451 /* clear background to gray */
452 glClearColor( 0.4, 0.4, 0.4, 0.0 );
453 glShadeModel( GL_FLAT
);
454 glPolygonMode( GL_FRONT
, GL_FILL
);
456 menu
= glutCreateMenu( menu_selected
);
458 glutAddMenuEntry( "clear", CLEAR
);
459 glutAddMenuEntry( "tesselate", TESSELATE
);
460 glutAddMenuEntry( "quit", QUIT
);
462 glutAttachMenu( GLUT_RIGHT_BUTTON
);
464 glutMouseFunc( mouse_clicked
);
465 glutKeyboardFunc( key_pressed
);
471 static void reshape( GLsizei w
, GLsizei h
)
473 glViewport( 0, 0, w
, h
);
475 glMatrixMode( GL_PROJECTION
);
477 glOrtho( 0.0, (GLdouble
)w
, 0.0, (GLdouble
)h
, -1.0, 1.0 );
479 glMatrixMode( GL_MODELVIEW
);
482 set_screen_wh( w
, h
);
488 static void usage( void )
490 printf( "Use left mouse button to place vertices.\n" );
491 printf( "Press middle mouse button when done.\n" );
492 printf( "Select tesselate from the pop-up menu.\n" );
496 int main( int argc
, char **argv
)
498 const char *version
= (const char *) gluGetString( GLU_VERSION
);
499 printf( "GLU version string: %s\n", version
);
500 if ( strstr( version
, "1.0" ) || strstr( version
, "1.1" ) ) {
501 fprintf( stderr
, "Sorry, this demo reqiures GLU 1.2 or later.\n" );
507 glutInit( &argc
, argv
);
508 glutInitDisplayMode( GLUT_SINGLE
| GLUT_RGB
);
509 glutInitWindowSize( 400, 400 );
510 glutCreateWindow( argv
[0] );
512 /* GH: Bit of a hack...
514 #ifdef GLU_VERSION_1_2
517 glutDisplayFunc( display
);
518 glutReshapeFunc( reshape
);