132001f49Smrg
232001f49Smrg/*
332001f49Smrg * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
432001f49Smrg * Updated for GLU 1.3 tessellation by Gareth Hughes <gareth@valinux.com>
532001f49Smrg */
632001f49Smrg
732001f49Smrg#include <stdio.h>
832001f49Smrg#include <stdlib.h>
932001f49Smrg#include <string.h>
1032001f49Smrg#include "glut_wrap.h"
1132001f49Smrg
1232001f49Smrg#define MAX_POINTS	256
1332001f49Smrg#define MAX_CONTOURS	32
1432001f49Smrg#define MAX_TRIANGLES	256
1532001f49Smrg
1632001f49Smrg#ifdef GLU_VERSION_1_2
1732001f49Smrg
1832001f49Smrgtypedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
1932001f49Smrgtypedef enum{ DEFINE, TESSELATED } mode_type;
2032001f49Smrg
2132001f49Smrgstatic GLsizei		width, height;
2232001f49Smrgstatic GLuint		contour_cnt;
2332001f49Smrgstatic GLuint		triangle_cnt;
2432001f49Smrg
2532001f49Smrgstatic mode_type 	mode;
2632001f49Smrgstatic int		menu;
2732001f49Smrg
2832001f49Smrgstatic GLuint		list_start;
2932001f49Smrg
3032001f49Smrgstatic GLfloat		edge_color[3];
3132001f49Smrg
3232001f49Smrgstatic struct {
3332001f49Smrg   GLfloat	p[MAX_POINTS][2];
3432001f49Smrg   GLuint	point_cnt;
3532001f49Smrg} contours[MAX_CONTOURS];
3632001f49Smrg
3732001f49Smrgstatic struct {
3832001f49Smrg   GLsizei	no;
3932001f49Smrg   GLfloat	p[3][2];
4032001f49Smrg   GLclampf	color[3][3];
4132001f49Smrg} triangles[MAX_TRIANGLES];
4232001f49Smrg
4332001f49Smrg
4432001f49Smrg
4532001f49Smrgstatic void GLAPIENTRY error_callback( GLenum err )
4632001f49Smrg{
4732001f49Smrg   int		len, i;
4832001f49Smrg   char const	*str;
4932001f49Smrg
5032001f49Smrg   glColor3f( 0.9, 0.9, 0.9 );
5132001f49Smrg   glRasterPos2i( 5, 5 );
5232001f49Smrg
5332001f49Smrg   str = (const char *) gluErrorString( err );
5432001f49Smrg   len = strlen( str );
5532001f49Smrg
5632001f49Smrg   for ( i = 0 ; i < len ; i++ ) {
5732001f49Smrg      glutBitmapCharacter( GLUT_BITMAP_9_BY_15, str[i] );
5832001f49Smrg   }
5932001f49Smrg}
6032001f49Smrg
6132001f49Smrgstatic void GLAPIENTRY begin_callback( GLenum mode )
6232001f49Smrg{
6332001f49Smrg   /* Allow multiple triangles to be output inside the begin/end pair. */
6432001f49Smrg   triangle_cnt = 0;
6532001f49Smrg   triangles[triangle_cnt].no = 0;
6632001f49Smrg}
6732001f49Smrg
6832001f49Smrgstatic void GLAPIENTRY edge_callback( GLenum flag )
6932001f49Smrg{
7032001f49Smrg   /* Persist the edge flag across triangles. */
7132001f49Smrg   if ( flag == GL_TRUE ) {
7232001f49Smrg      edge_color[0] = 1.0;
7332001f49Smrg      edge_color[1] = 1.0;
7432001f49Smrg      edge_color[2] = 0.5;
7532001f49Smrg   } else {
7632001f49Smrg      edge_color[0] = 1.0;
7732001f49Smrg      edge_color[1] = 0.0;
7832001f49Smrg      edge_color[2] = 0.0;
7932001f49Smrg   }
8032001f49Smrg}
8132001f49Smrg
8232001f49Smrgstatic void GLAPIENTRY end_callback(void)
8332001f49Smrg{
8432001f49Smrg   GLuint	i;
8532001f49Smrg
8632001f49Smrg   glBegin( GL_LINES );
8732001f49Smrg
8832001f49Smrg   /* Output the three edges of each triangle as lines colored
8932001f49Smrg      according to their edge flag. */
9032001f49Smrg   for ( i = 0 ; i < triangle_cnt ; i++ ) {
9132001f49Smrg      glColor3f( triangles[i].color[0][0],
9232001f49Smrg		 triangles[i].color[0][1],
9332001f49Smrg		 triangles[i].color[0][2] );
9432001f49Smrg
9532001f49Smrg      glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
9632001f49Smrg      glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
9732001f49Smrg
9832001f49Smrg      glColor3f( triangles[i].color[1][0],
9932001f49Smrg		 triangles[i].color[1][1],
10032001f49Smrg		 triangles[i].color[1][2] );
10132001f49Smrg
10232001f49Smrg      glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
10332001f49Smrg      glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
10432001f49Smrg
10532001f49Smrg      glColor3f( triangles[i].color[2][0],
10632001f49Smrg		 triangles[i].color[2][1],
10732001f49Smrg		 triangles[i].color[2][2] );
10832001f49Smrg
10932001f49Smrg      glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
11032001f49Smrg      glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
11132001f49Smrg   }
11232001f49Smrg
11332001f49Smrg   glEnd();
11432001f49Smrg}
11532001f49Smrg
11632001f49Smrgstatic void GLAPIENTRY vertex_callback( void *data )
11732001f49Smrg{
11832001f49Smrg   GLsizei	no;
11932001f49Smrg   GLfloat	*p;
12032001f49Smrg
12132001f49Smrg   p = (GLfloat *) data;
12232001f49Smrg   no = triangles[triangle_cnt].no;
12332001f49Smrg
12432001f49Smrg   triangles[triangle_cnt].p[no][0] = p[0];
12532001f49Smrg   triangles[triangle_cnt].p[no][1] = p[1];
12632001f49Smrg
12732001f49Smrg   triangles[triangle_cnt].color[no][0] = edge_color[0];
12832001f49Smrg   triangles[triangle_cnt].color[no][1] = edge_color[1];
12932001f49Smrg   triangles[triangle_cnt].color[no][2] = edge_color[2];
13032001f49Smrg
13132001f49Smrg   /* After every three vertices, initialize the next triangle. */
13232001f49Smrg   if ( ++(triangles[triangle_cnt].no) == 3 ) {
13332001f49Smrg      triangle_cnt++;
13432001f49Smrg      triangles[triangle_cnt].no = 0;
13532001f49Smrg   }
13632001f49Smrg}
13732001f49Smrg
13832001f49Smrgstatic void GLAPIENTRY combine_callback( GLdouble coords[3],
13932001f49Smrg				       GLdouble *vertex_data[4],
14032001f49Smrg				       GLfloat weight[4], void **data )
14132001f49Smrg{
14232001f49Smrg   GLfloat	*vertex;
14332001f49Smrg
14432001f49Smrg   vertex = (GLfloat *) malloc( 2 * sizeof(GLfloat) );
14532001f49Smrg
14632001f49Smrg   vertex[0] = (GLfloat) coords[0];
14732001f49Smrg   vertex[1] = (GLfloat) coords[1];
14832001f49Smrg
14932001f49Smrg   *data = vertex;
15032001f49Smrg}
15132001f49Smrg
15232001f49Smrg
15332001f49Smrgstatic void set_screen_wh( GLsizei w, GLsizei h )
15432001f49Smrg{
15532001f49Smrg   width = w;
15632001f49Smrg   height = h;
15732001f49Smrg}
15832001f49Smrg
15932001f49Smrgstatic void tesse( void )
16032001f49Smrg{
16132001f49Smrg   GLUtesselator	*tobj;
16232001f49Smrg   GLdouble		data[3];
16332001f49Smrg   GLuint		i, j, point_cnt;
16432001f49Smrg
16532001f49Smrg   list_start = glGenLists( 2 );
16632001f49Smrg
16732001f49Smrg   tobj = gluNewTess();
16832001f49Smrg
16932001f49Smrg   if ( tobj != NULL ) {
17032001f49Smrg      gluTessNormal( tobj, 0.0, 0.0, 1.0 );
17132001f49Smrg      gluTessCallback( tobj, GLU_TESS_BEGIN, glBegin );
17232001f49Smrg      gluTessCallback( tobj, GLU_TESS_VERTEX, glVertex2fv );
17332001f49Smrg      gluTessCallback( tobj, GLU_TESS_END, glEnd );
17432001f49Smrg      gluTessCallback( tobj, GLU_TESS_ERROR, error_callback );
17532001f49Smrg      gluTessCallback( tobj, GLU_TESS_COMBINE, combine_callback );
17632001f49Smrg
17732001f49Smrg      glNewList( list_start, GL_COMPILE );
17832001f49Smrg      gluBeginPolygon( tobj );
17932001f49Smrg
18032001f49Smrg      for ( j = 0 ; j <= contour_cnt ; j++ ) {
18132001f49Smrg	 point_cnt = contours[j].point_cnt;
18232001f49Smrg	 gluNextContour( tobj, GLU_UNKNOWN );
18332001f49Smrg
18432001f49Smrg	 for ( i = 0 ; i < point_cnt ; i++ ) {
18532001f49Smrg	    data[0] = (GLdouble)( contours[j].p[i][0] );
18632001f49Smrg	    data[1] = (GLdouble)( contours[j].p[i][1] );
18732001f49Smrg	    data[2] = 0.0;
18832001f49Smrg	    gluTessVertex( tobj, data, contours[j].p[i] );
18932001f49Smrg	 }
19032001f49Smrg      }
19132001f49Smrg
19232001f49Smrg      gluEndPolygon( tobj );
19332001f49Smrg      glEndList();
19432001f49Smrg
19532001f49Smrg      gluTessCallback( tobj, GLU_TESS_BEGIN, begin_callback );
19632001f49Smrg      gluTessCallback( tobj, GLU_TESS_VERTEX, vertex_callback );
19732001f49Smrg      gluTessCallback( tobj, GLU_TESS_END, end_callback );
19832001f49Smrg      gluTessCallback( tobj, GLU_TESS_EDGE_FLAG, edge_callback );
19932001f49Smrg
20032001f49Smrg      glNewList( list_start + 1, GL_COMPILE );
20132001f49Smrg      gluBeginPolygon( tobj );
20232001f49Smrg
20332001f49Smrg      for ( j = 0 ; j <= contour_cnt ; j++ ) {
20432001f49Smrg	 point_cnt = contours[j].point_cnt;
20532001f49Smrg	 gluNextContour( tobj, GLU_UNKNOWN );
20632001f49Smrg
20732001f49Smrg	 for ( i = 0 ; i < point_cnt ; i++ ) {
20832001f49Smrg	    data[0] = (GLdouble)( contours[j].p[i][0] );
20932001f49Smrg	    data[1] = (GLdouble)( contours[j].p[i][1] );
21032001f49Smrg	    data[2] = 0.0;
21132001f49Smrg	    gluTessVertex( tobj, data, contours[j].p[i] );
21232001f49Smrg	 }
21332001f49Smrg      }
21432001f49Smrg
21532001f49Smrg      gluEndPolygon( tobj );
21632001f49Smrg      glEndList();
21732001f49Smrg
21832001f49Smrg      gluDeleteTess( tobj );
21932001f49Smrg
22032001f49Smrg      glutMouseFunc( NULL );
22132001f49Smrg      mode = TESSELATED;
22232001f49Smrg   }
22332001f49Smrg}
22432001f49Smrg
22532001f49Smrgstatic void left_down( int x1, int y1 )
22632001f49Smrg{
22732001f49Smrg   GLfloat	P[2];
22832001f49Smrg   GLuint	point_cnt;
22932001f49Smrg
23032001f49Smrg   /* translate GLUT into GL coordinates */
23132001f49Smrg
23232001f49Smrg   P[0] = x1;
23332001f49Smrg   P[1] = height - y1;
23432001f49Smrg
23532001f49Smrg   point_cnt = contours[contour_cnt].point_cnt;
23632001f49Smrg
23732001f49Smrg   contours[contour_cnt].p[point_cnt][0] = P[0];
23832001f49Smrg   contours[contour_cnt].p[point_cnt][1] = P[1];
23932001f49Smrg
24032001f49Smrg   glBegin( GL_LINES );
24132001f49Smrg
24232001f49Smrg   if ( point_cnt ) {
24332001f49Smrg      glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
24432001f49Smrg      glVertex2fv( P );
24532001f49Smrg   } else {
24632001f49Smrg      glVertex2fv( P );
24732001f49Smrg      glVertex2fv( P );
24832001f49Smrg   }
24932001f49Smrg
25032001f49Smrg   glEnd();
25132001f49Smrg   glFinish();
25232001f49Smrg
25332001f49Smrg   contours[contour_cnt].point_cnt++;
25432001f49Smrg}
25532001f49Smrg
25632001f49Smrgstatic void middle_down( int x1, int y1 )
25732001f49Smrg{
25832001f49Smrg   GLuint	point_cnt;
25932001f49Smrg   (void) x1;
26032001f49Smrg   (void) y1;
26132001f49Smrg
26232001f49Smrg   point_cnt = contours[contour_cnt].point_cnt;
26332001f49Smrg
26432001f49Smrg   if ( point_cnt > 2 ) {
26532001f49Smrg      glBegin( GL_LINES );
26632001f49Smrg
26732001f49Smrg      glVertex2fv( contours[contour_cnt].p[0] );
26832001f49Smrg      glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
26932001f49Smrg
27032001f49Smrg      contours[contour_cnt].p[point_cnt][0] = -1;
27132001f49Smrg
27232001f49Smrg      glEnd();
27332001f49Smrg      glFinish();
27432001f49Smrg
27532001f49Smrg      contour_cnt++;
27632001f49Smrg      contours[contour_cnt].point_cnt = 0;
27732001f49Smrg   }
27832001f49Smrg}
27932001f49Smrg
28032001f49Smrgstatic void mouse_clicked( int button, int state, int x, int y )
28132001f49Smrg{
28232001f49Smrg   x -= x%10;
28332001f49Smrg   y -= y%10;
28432001f49Smrg
28532001f49Smrg   switch ( button ) {
28632001f49Smrg   case GLUT_LEFT_BUTTON:
28732001f49Smrg      if ( state == GLUT_DOWN ) {
28832001f49Smrg	 left_down( x, y );
28932001f49Smrg      }
29032001f49Smrg      break;
29132001f49Smrg   case GLUT_MIDDLE_BUTTON:
29232001f49Smrg      if ( state == GLUT_DOWN ) {
29332001f49Smrg	 middle_down( x, y );
29432001f49Smrg      }
29532001f49Smrg      break;
29632001f49Smrg   }
29732001f49Smrg}
29832001f49Smrg
29932001f49Smrgstatic void display( void )
30032001f49Smrg{
30132001f49Smrg   GLuint i,j;
30232001f49Smrg   GLsizei ii, jj;
30332001f49Smrg   GLuint point_cnt;
30432001f49Smrg
30532001f49Smrg   glClear( GL_COLOR_BUFFER_BIT );
30632001f49Smrg
30732001f49Smrg   switch ( mode ) {
30832001f49Smrg   case DEFINE:
30932001f49Smrg      /* draw grid */
31032001f49Smrg      glColor3f( 0.6, 0.5, 0.5 );
31132001f49Smrg
31232001f49Smrg      glBegin( GL_LINES );
31332001f49Smrg
31432001f49Smrg      for ( ii = 0 ; ii < width ; ii += 10 ) {
31532001f49Smrg	 for ( jj = 0 ; jj < height ; jj += 10 ) {
31632001f49Smrg	    glVertex2i( 0, jj );
31732001f49Smrg	    glVertex2i( width, jj );
31832001f49Smrg	    glVertex2i( ii, height );
31932001f49Smrg	    glVertex2i( ii, 0 );
32032001f49Smrg	 }
32132001f49Smrg      }
32232001f49Smrg
32332001f49Smrg      glEnd();
32432001f49Smrg
32532001f49Smrg      glColor3f( 1.0, 1.0, 0.0 );
32632001f49Smrg
32732001f49Smrg      for ( i = 0 ; i <= contour_cnt ; i++ ) {
32832001f49Smrg	 point_cnt = contours[i].point_cnt;
32932001f49Smrg
33032001f49Smrg	 glBegin( GL_LINES );
33132001f49Smrg
33232001f49Smrg	 switch ( point_cnt ) {
33332001f49Smrg	 case 0:
33432001f49Smrg	    break;
33532001f49Smrg	 case 1:
33632001f49Smrg	    glVertex2fv( contours[i].p[0] );
33732001f49Smrg	    glVertex2fv( contours[i].p[0] );
33832001f49Smrg	    break;
33932001f49Smrg	 case 2:
34032001f49Smrg	    glVertex2fv( contours[i].p[0] );
34132001f49Smrg	    glVertex2fv( contours[i].p[1] );
34232001f49Smrg	    break;
34332001f49Smrg	 default:
34432001f49Smrg	    --point_cnt;
34532001f49Smrg	    for ( j = 0 ; j < point_cnt ; j++ ) {
34632001f49Smrg	       glVertex2fv( contours[i].p[j] );
34732001f49Smrg	       glVertex2fv( contours[i].p[j+1] );
34832001f49Smrg	    }
34932001f49Smrg	    if ( contours[i].p[j+1][0] == -1 ) {
35032001f49Smrg	       glVertex2fv( contours[i].p[0] );
35132001f49Smrg	       glVertex2fv( contours[i].p[j] );
35232001f49Smrg	    }
35332001f49Smrg	    break;
35432001f49Smrg	 }
35532001f49Smrg
35632001f49Smrg	 glEnd();
35732001f49Smrg      }
35832001f49Smrg
35932001f49Smrg      glFinish();
36032001f49Smrg      break;
36132001f49Smrg
36232001f49Smrg   case TESSELATED:
36332001f49Smrg      /* draw triangles */
36432001f49Smrg      glColor3f( 0.7, 0.7, 0.0 );
36532001f49Smrg      glCallList( list_start );
36632001f49Smrg
36732001f49Smrg      glLineWidth( 2.0 );
36832001f49Smrg      glCallList( list_start + 1 );
36932001f49Smrg      glLineWidth( 1.0 );
37032001f49Smrg
37132001f49Smrg      glFlush();
37232001f49Smrg      break;
37332001f49Smrg   }
37432001f49Smrg
37532001f49Smrg   glColor3f( 1.0, 1.0, 0.0 );
37632001f49Smrg}
37732001f49Smrg
37832001f49Smrgstatic void clear( void )
37932001f49Smrg{
38032001f49Smrg   contour_cnt = 0;
38132001f49Smrg   contours[0].point_cnt = 0;
38232001f49Smrg   triangle_cnt = 0;
38332001f49Smrg
38432001f49Smrg   glutMouseFunc( mouse_clicked );
38532001f49Smrg
38632001f49Smrg   mode = DEFINE;
38732001f49Smrg
38832001f49Smrg   glDeleteLists( list_start, 2 );
38932001f49Smrg   list_start = 0;
39032001f49Smrg}
39132001f49Smrg
39232001f49Smrgstatic void quit( void )
39332001f49Smrg{
39432001f49Smrg   exit( 0 );
39532001f49Smrg}
39632001f49Smrg
39732001f49Smrgstatic void menu_selected( int entry )
39832001f49Smrg{
39932001f49Smrg   switch ( entry ) {
40032001f49Smrg   case CLEAR:
40132001f49Smrg      clear();
40232001f49Smrg      break;
40332001f49Smrg   case TESSELATE:
40432001f49Smrg      tesse();
40532001f49Smrg      break;
40632001f49Smrg   case QUIT:
40732001f49Smrg      quit();
40832001f49Smrg      break;
40932001f49Smrg   }
41032001f49Smrg
41132001f49Smrg   glutPostRedisplay();
41232001f49Smrg}
41332001f49Smrg
41432001f49Smrgstatic void key_pressed( unsigned char key, int x, int y )
41532001f49Smrg{
41632001f49Smrg   (void) x;
41732001f49Smrg   (void) y;
41832001f49Smrg
41932001f49Smrg   switch ( key ) {
42032001f49Smrg   case 'c':
42132001f49Smrg   case 'C':
42232001f49Smrg      clear();
42332001f49Smrg      break;
42432001f49Smrg   case 't':
42532001f49Smrg   case 'T':
42632001f49Smrg      tesse();
42732001f49Smrg      break;
42832001f49Smrg   case 27:
42932001f49Smrg   case 'q':
43032001f49Smrg   case 'Q':
43132001f49Smrg      quit();
43232001f49Smrg      break;
43332001f49Smrg   }
43432001f49Smrg
43532001f49Smrg   glutPostRedisplay();
43632001f49Smrg}
43732001f49Smrg
43832001f49Smrgstatic void myinit( void )
43932001f49Smrg{
44032001f49Smrg   /* clear background to gray */
44132001f49Smrg   glClearColor( 0.4, 0.4, 0.4, 0.0 );
44232001f49Smrg   glShadeModel( GL_FLAT );
44332001f49Smrg   glPolygonMode( GL_FRONT, GL_FILL );
44432001f49Smrg
44532001f49Smrg   menu = glutCreateMenu( menu_selected );
44632001f49Smrg
44732001f49Smrg   glutAddMenuEntry( "clear", CLEAR );
44832001f49Smrg   glutAddMenuEntry( "tesselate", TESSELATE );
44932001f49Smrg   glutAddMenuEntry( "quit", QUIT );
45032001f49Smrg
45132001f49Smrg   glutAttachMenu( GLUT_RIGHT_BUTTON );
45232001f49Smrg
45332001f49Smrg   glutMouseFunc( mouse_clicked );
45432001f49Smrg   glutKeyboardFunc( key_pressed );
45532001f49Smrg
45632001f49Smrg   contour_cnt = 0;
45732001f49Smrg   mode = DEFINE;
45832001f49Smrg}
45932001f49Smrg
46032001f49Smrgstatic void reshape( GLsizei w, GLsizei h )
46132001f49Smrg{
46232001f49Smrg   glViewport( 0, 0, w, h );
46332001f49Smrg
46432001f49Smrg   glMatrixMode( GL_PROJECTION );
46532001f49Smrg   glLoadIdentity();
46632001f49Smrg   glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
46732001f49Smrg
46832001f49Smrg   glMatrixMode( GL_MODELVIEW );
46932001f49Smrg   glLoadIdentity();
47032001f49Smrg
47132001f49Smrg   set_screen_wh( w, h );
47232001f49Smrg}
47332001f49Smrg
47432001f49Smrg#endif
47532001f49Smrg
47632001f49Smrg
47732001f49Smrgstatic void usage( void )
47832001f49Smrg{
47932001f49Smrg   printf( "Use left mouse button to place vertices.\n" );
48032001f49Smrg   printf( "Press middle mouse button when done.\n" );
48132001f49Smrg   printf( "Select tesselate from the pop-up menu.\n" );
48232001f49Smrg}
48332001f49Smrg
48432001f49Smrg
48532001f49Smrgint main( int argc, char **argv )
48632001f49Smrg{
48732001f49Smrg   const char *version = (const char *) gluGetString( GLU_VERSION );
48832001f49Smrg   printf( "GLU version string: %s\n", version );
48932001f49Smrg   if ( strstr( version, "1.0" ) || strstr( version, "1.1" ) ) {
49032001f49Smrg      fprintf( stderr, "Sorry, this demo reqiures GLU 1.2 or later.\n" );
49132001f49Smrg      exit( 1 );
49232001f49Smrg   }
49332001f49Smrg
49432001f49Smrg   usage();
49532001f49Smrg
49632001f49Smrg   glutInitWindowSize( 400, 400 );
49732001f49Smrg   glutInit( &argc, argv );
49832001f49Smrg   glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
49932001f49Smrg   glutCreateWindow( argv[0] );
50032001f49Smrg
50132001f49Smrg   /* GH: Bit of a hack...
50232001f49Smrg    */
50332001f49Smrg#ifdef GLU_VERSION_1_2
50432001f49Smrg   myinit();
50532001f49Smrg
50632001f49Smrg   glutDisplayFunc( display );
50732001f49Smrg   glutReshapeFunc( reshape );
50832001f49Smrg
50932001f49Smrg   glutMainLoop();
51032001f49Smrg#endif
51132001f49Smrg
51232001f49Smrg   return 0;
51332001f49Smrg}
514