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>
12 #define MAX_POINTS 256
13 #define MAX_CONTOURS 32
14 #define MAX_TRIANGLES 256
18 #define GLCALLBACK CALLBACK
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
;
36 static GLuint list_start
;
38 static GLfloat edge_color
[3];
41 GLfloat p
[MAX_POINTS
][2];
43 } contours
[MAX_CONTOURS
];
49 } triangles
[MAX_TRIANGLES
];
53 static void GLCALLBACK
error_callback( GLenum err
)
58 glColor3f( 0.9, 0.9, 0.9 );
59 glRasterPos2i( 5, 5 );
61 str
= (const char *) gluErrorString( err
);
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. */
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
) {
90 static void GLCALLBACK
end_callback()
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] );
124 static void GLCALLBACK
vertex_callback( void *data
)
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 ) {
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
)
152 vertex
= (GLfloat
*) malloc( 2 * sizeof(GLfloat
) );
154 vertex
[0] = (GLfloat
) coords
[0];
155 vertex
[1] = (GLfloat
) coords
[1];
161 static void set_screen_wh( GLsizei w
, GLsizei h
)
167 typedef void (GLAPIENTRY
*callback_t
)();
169 static void tesse( void )
173 GLuint i
, j
, point_cnt
;
175 list_start
= glGenLists( 2 );
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] );
198 gluTessVertex( tobj
, data
, contours
[j
].p
[i
] );
202 gluEndPolygon( tobj
);
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] );
221 gluTessVertex( tobj
, data
, contours
[j
].p
[i
] );
225 gluEndPolygon( tobj
);
228 gluDeleteTess( tobj
);
230 glutMouseFunc( NULL
);
235 static void left_down( int x1
, int y1
)
240 /* translate GLUT into GL coordinates */
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];
253 glVertex2fv( contours
[contour_cnt
].p
[point_cnt
-1] );
263 contours
[contour_cnt
].point_cnt
++;
266 static void middle_down( int x1
, int y1
)
272 point_cnt
= contours
[contour_cnt
].point_cnt
;
274 if ( point_cnt
> 2 ) {
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;
286 contours
[contour_cnt
].point_cnt
= 0;
290 static void mouse_clicked( int button
, int state
, int x
, int y
)
296 case GLUT_LEFT_BUTTON
:
297 if ( state
== GLUT_DOWN
) {
301 case GLUT_MIDDLE_BUTTON
:
302 if ( state
== GLUT_DOWN
) {
309 static void display( void )
315 glClear( GL_COLOR_BUFFER_BIT
);
320 glColor3f( 0.6, 0.5, 0.5 );
324 for ( ii
= 0 ; ii
< width
; ii
+= 10 ) {
325 for ( jj
= 0 ; jj
< height
; jj
+= 10 ) {
327 glVertex2i( width
, jj
);
328 glVertex2i( ii
, height
);
335 glColor3f( 1.0, 1.0, 0.0 );
337 for ( i
= 0 ; i
<= contour_cnt
; i
++ ) {
338 point_cnt
= contours
[i
].point_cnt
;
342 switch ( point_cnt
) {
346 glVertex2fv( contours
[i
].p
[0] );
347 glVertex2fv( contours
[i
].p
[0] );
350 glVertex2fv( contours
[i
].p
[0] );
351 glVertex2fv( contours
[i
].p
[1] );
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
] );
374 glColor3f( 0.7, 0.7, 0.0 );
375 glCallList( list_start
);
378 glCallList( list_start
+ 1 );
385 glColor3f( 1.0, 1.0, 0.0 );
388 static void clear( void )
391 contours
[0].point_cnt
= 0;
394 glutMouseFunc( mouse_clicked
);
398 glDeleteLists( list_start
, 2 );
402 static void quit( void )
407 static void menu_selected( int entry
)
424 static void key_pressed( unsigned char key
, int x
, int y
)
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
);
470 static void reshape( GLsizei w
, GLsizei h
)
472 glViewport( 0, 0, w
, h
);
474 glMatrixMode( GL_PROJECTION
);
476 glOrtho( 0.0, (GLdouble
)w
, 0.0, (GLdouble
)h
, -1.0, 1.0 );
478 glMatrixMode( GL_MODELVIEW
);
481 set_screen_wh( w
, h
);
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" );
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
517 glutDisplayFunc( display
);
518 glutReshapeFunc( reshape
);