home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / demos / tessdemo.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  12KB  |  579 lines

  1. /* $Id: tessdemo.c,v 1.3.2.1 1999/11/16 11:09:09 gareth Exp $ */
  2.  
  3. /*
  4.  * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
  5.  * This demo isn't built by the Makefile because it needs GLUT.  After you've
  6.  * installed GLUT you can try this demo.
  7.  * Here's the command for IRIX, for example:
  8.    cc -g -ansi -prototypes -fullwarn -float -I../include -DSHM tess_demo.c -L../lib -lglut -lMesaGLU -lMesaGL -lm -lX11 -lXext -lXmu -lfpe -lXext -o tess_demo
  9.  */
  10.  
  11. /*
  12.  * Updated for GLU 1.3 tessellation by Gareth Hughes <garethh@bell-labs.com>
  13.  */
  14.  
  15. /*
  16.  * $Log: tessdemo.c,v $
  17.  * Revision 1.3.2.1  1999/11/16 11:09:09  gareth
  18.  * Added combine callback.  Converted vertices from ints to floats.
  19.  *
  20.  * Revision 1.3  1999/11/04 04:00:42  gareth
  21.  * Updated demo for new GLU 1.3 tessellation.  Added optimized rendering
  22.  * by saving the output of the tessellation into display lists.
  23.  *
  24.  * Revision 1.2  1999/09/19 20:09:00  tanner
  25.  *
  26.  * lots of autoconf updates
  27.  *
  28.  * Revision 1.1.1.1  1999/08/19 00:55:40  jtg
  29.  * Imported sources
  30.  *
  31.  * Revision 3.5  1999/03/28 18:24:37  brianp
  32.  * minor clean-up
  33.  *
  34.  * Revision 3.4  1999/02/14 03:37:07  brianp
  35.  * fixed callback problem
  36.  *
  37.  * Revision 3.3  1998/07/26 01:25:26  brianp
  38.  * removed include of gl.h and glu.h
  39.  *
  40.  * Revision 3.2  1998/06/29 02:37:30  brianp
  41.  * minor changes for Windows (Ted Jump)
  42.  *
  43.  * Revision 3.1  1998/06/09 01:53:49  brianp
  44.  * main() should return an int
  45.  *
  46.  * Revision 3.0  1998/02/14 18:42:29  brianp
  47.  * initial rev
  48.  *
  49.  */
  50.  
  51.  
  52. #include <GL/glut.h>
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56.  
  57. #define MAX_POINTS    256
  58. #define MAX_CONTOURS    32
  59. #define MAX_TRIANGLES    256
  60.  
  61. #ifndef GLCALLBACK
  62. #ifdef CALLBACK
  63. #define GLCALLBACK CALLBACK
  64. #else
  65. #define GLCALLBACK
  66. #endif
  67. #endif
  68.  
  69. typedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
  70. typedef enum{ DEFINE, TESSELATED } mode_type;
  71.  
  72. static GLsizei        width, height;
  73. static GLuint        contour_cnt;
  74. static GLuint        triangle_cnt;
  75.  
  76. static mode_type     mode;
  77. static int        menu;
  78.  
  79. static GLuint        list_start;
  80.  
  81. static GLfloat        edge_color[3];
  82.  
  83. static struct
  84. {
  85.    GLfloat    p[MAX_POINTS][2];
  86.    GLuint    point_cnt;
  87. } contours[MAX_CONTOURS];
  88.  
  89. static struct
  90. {
  91.    GLsizei    no;
  92.    GLfloat    p[3][2];
  93.    GLclampf    color[3][3];
  94. } triangles[MAX_TRIANGLES];
  95.  
  96.  
  97.  
  98. void GLCALLBACK error_callback( GLenum err )
  99. {
  100.    int        len, i;
  101.    char const    *str;
  102.  
  103.    glColor3f( 0.9, 0.9, 0.9 );
  104.    glRasterPos2i( 5, 5 );
  105.  
  106.    str = (const char *) gluErrorString( err );
  107.    len = strlen( str );
  108.  
  109.    for ( i = 0 ; i < len ; i++ ) {
  110.       glutBitmapCharacter( GLUT_BITMAP_9_BY_15, str[i] );
  111.    }
  112. }
  113.  
  114. void GLCALLBACK begin_callback( GLenum mode )
  115. {
  116.    /* Allow multiple triangles to be output inside the begin/end pair. */
  117.    triangle_cnt = 0;
  118.    triangles[triangle_cnt].no = 0;
  119. }
  120.  
  121. void GLCALLBACK edge_callback( GLenum flag )
  122. {
  123.    /* Persist the edge flag across triangles. */
  124.    if ( flag == GL_TRUE )
  125.    {
  126.       edge_color[0] = 1.0;
  127.       edge_color[1] = 1.0;
  128.       edge_color[2] = 0.5;
  129.    }
  130.    else
  131.    {
  132.       edge_color[0] = 1.0;
  133.       edge_color[1] = 0.0;
  134.       edge_color[2] = 0.0;
  135.    }
  136. }
  137.  
  138. void GLCALLBACK end_callback()
  139. {
  140.    GLint    i;
  141.  
  142.    glBegin( GL_LINES );
  143.  
  144.    /* Output the three edges of each triangle as lines colored
  145.       according to their edge flag. */
  146.    for ( i = 0 ; i < triangle_cnt ; i++ )
  147.    {
  148.       glColor3f( triangles[i].color[0][0],
  149.          triangles[i].color[0][1],
  150.          triangles[i].color[0][2] );
  151.  
  152.       glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
  153.       glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
  154.  
  155.       glColor3f( triangles[i].color[1][0],
  156.          triangles[i].color[1][1],
  157.          triangles[i].color[1][2] );
  158.  
  159.       glVertex2f( triangles[i].p[1][0], triangles[i].p[1][1] );
  160.       glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
  161.  
  162.       glColor3f( triangles[i].color[2][0],
  163.          triangles[i].color[2][1],
  164.          triangles[i].color[2][2] );
  165.  
  166.       glVertex2f( triangles[i].p[2][0], triangles[i].p[2][1] );
  167.       glVertex2f( triangles[i].p[0][0], triangles[i].p[0][1] );
  168.    }
  169.  
  170.    glEnd();
  171. }
  172.  
  173. void GLCALLBACK vertex_callback( void *data )
  174. {
  175.    GLsizei    no;
  176.    GLfloat    *p;
  177.  
  178.    p = (GLfloat *) data;
  179.    no = triangles[triangle_cnt].no;
  180.  
  181.    triangles[triangle_cnt].p[no][0] = p[0];
  182.    triangles[triangle_cnt].p[no][1] = p[1];
  183.  
  184.    triangles[triangle_cnt].color[no][0] = edge_color[0];
  185.    triangles[triangle_cnt].color[no][1] = edge_color[1];
  186.    triangles[triangle_cnt].color[no][2] = edge_color[2];
  187.  
  188.    /* After every three vertices, initialize the next triangle. */
  189.    if ( ++(triangles[triangle_cnt].no) == 3 )
  190.    {
  191.       triangle_cnt++;
  192.       triangles[triangle_cnt].no = 0;
  193.    }
  194. }
  195.  
  196. void GLCALLBACK combine_callback( GLdouble coords[3],
  197.                   GLdouble *vertex_data[4],
  198.                   GLfloat weight[4], void **data )
  199. {
  200.    GLfloat    *vertex;
  201.    int        i;
  202.  
  203.    vertex = (GLfloat *) malloc( 2 * sizeof(GLfloat) );
  204.  
  205.    vertex[0] = (GLfloat) coords[0];
  206.    vertex[1] = (GLfloat) coords[1];
  207.  
  208.    *data = vertex;
  209. }
  210.  
  211.  
  212. void set_screen_wh( GLsizei w, GLsizei h )
  213. {
  214.    width = w;
  215.    height = h;
  216. }
  217.  
  218. void tesse( void )
  219. {
  220.    GLUtesselator    *tobj;
  221.    GLdouble        data[3];
  222.    GLuint        i, j, point_cnt;
  223.  
  224.    list_start = glGenLists( 2 );
  225.  
  226.    tobj = gluNewTess();
  227.  
  228.    if ( tobj != NULL )
  229.    {
  230.       gluTessCallback( tobj, GLU_TESS_BEGIN, glBegin );
  231.       gluTessCallback( tobj, GLU_TESS_VERTEX, glVertex2fv );
  232.       gluTessCallback( tobj, GLU_TESS_END, glEnd );
  233.       gluTessCallback( tobj, GLU_TESS_ERROR, error_callback );
  234.       gluTessCallback( tobj, GLU_TESS_COMBINE, combine_callback );
  235.  
  236.       glNewList( list_start, GL_COMPILE );
  237.       gluBeginPolygon( tobj );
  238.  
  239.       for ( j = 0 ; j <= contour_cnt ; j++ )
  240.       {
  241.      point_cnt = contours[j].point_cnt;
  242.      gluNextContour( tobj, GLU_UNKNOWN );
  243.  
  244.      for ( i = 0 ; i < point_cnt ; i++ )
  245.      {
  246.         data[0] = (GLdouble)( contours[j].p[i][0] );
  247.         data[1] = (GLdouble)( contours[j].p[i][1] );
  248.         data[2] = 0.0;
  249.         gluTessVertex( tobj, data, contours[j].p[i] );
  250.      }
  251.       }
  252.  
  253.       gluEndPolygon( tobj );
  254.       glEndList();
  255.  
  256.       gluTessCallback( tobj, GLU_TESS_BEGIN, begin_callback );
  257.       gluTessCallback( tobj, GLU_TESS_VERTEX, vertex_callback );
  258.       gluTessCallback( tobj, GLU_TESS_END, end_callback );
  259.       gluTessCallback( tobj, GLU_TESS_EDGE_FLAG, edge_callback );
  260.  
  261.       glNewList( list_start + 1, GL_COMPILE );
  262.       gluBeginPolygon( tobj );
  263.  
  264.       for ( j = 0 ; j <= contour_cnt ; j++ )
  265.       {
  266.      point_cnt = contours[j].point_cnt;
  267.      gluNextContour( tobj, GLU_UNKNOWN );
  268.  
  269.      for ( i = 0 ; i < point_cnt ; i++ )
  270.      {
  271.         data[0] = (GLdouble)( contours[j].p[i][0] );
  272.         data[1] = (GLdouble)( contours[j].p[i][1] );
  273.         data[2] = 0.0;
  274.         gluTessVertex( tobj, data, contours[j].p[i] );
  275.      }
  276.       }
  277.  
  278.       gluEndPolygon( tobj );
  279.       glEndList();
  280.  
  281.       gluDeleteTess( tobj );
  282.  
  283.       glutMouseFunc( NULL );
  284.       mode = TESSELATED;
  285.    }
  286. }
  287.  
  288. void left_down( int x1, int y1 )
  289. {
  290.    GLfloat    P[2];
  291.    GLuint    point_cnt;
  292.  
  293.    /* translate GLUT into GL coordinates */
  294.  
  295.    P[0] = x1;
  296.    P[1] = height - y1;
  297.  
  298.    point_cnt = contours[contour_cnt].point_cnt;
  299.  
  300.    contours[contour_cnt].p[point_cnt][0] = P[0];
  301.    contours[contour_cnt].p[point_cnt][1] = P[1];
  302.  
  303.    glBegin( GL_LINES );
  304.  
  305.    if ( point_cnt )
  306.    {
  307.       glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
  308.       glVertex2fv( P );
  309.    }
  310.    else
  311.    {
  312.       glVertex2fv( P );
  313.       glVertex2fv( P );
  314.    }
  315.  
  316.    glEnd();
  317.    glFinish();
  318.  
  319.    contours[contour_cnt].point_cnt++;
  320. }
  321.  
  322. void middle_down( int x1, int y1 )
  323. {
  324.    GLuint    point_cnt;
  325.    (void) x1;
  326.    (void) y1;
  327.  
  328.    point_cnt = contours[contour_cnt].point_cnt;
  329.  
  330.    if ( point_cnt > 2 )
  331.    {
  332.       glBegin( GL_LINES );
  333.  
  334.       glVertex2fv( contours[contour_cnt].p[0] );
  335.       glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
  336.  
  337.       contours[contour_cnt].p[point_cnt][0] = -1;
  338.  
  339.       glEnd();
  340.       glFinish();
  341.  
  342.       contour_cnt++;
  343.       contours[contour_cnt].point_cnt = 0;
  344.    }
  345. }
  346.  
  347. void mouse_clicked( int button, int state, int x, int y )
  348. {
  349.    x -= x%10;
  350.    y -= y%10;
  351.  
  352.    switch ( button )
  353.    {
  354.    case GLUT_LEFT_BUTTON:
  355.       if ( state == GLUT_DOWN ) {
  356.      left_down( x, y );
  357.       }
  358.       break;
  359.    case GLUT_MIDDLE_BUTTON:
  360.       if ( state == GLUT_DOWN ) {
  361.      middle_down( x, y );
  362.       }
  363.       break;
  364.    }
  365. }
  366.  
  367. void display( void )
  368. {
  369.    GLuint i,j;
  370.    GLuint point_cnt;
  371.  
  372.    glClear( GL_COLOR_BUFFER_BIT );
  373.  
  374.    switch ( mode )
  375.    {
  376.    case DEFINE:
  377.       /* draw grid */
  378.       glColor3f( 0.6, 0.5, 0.5 );
  379.  
  380.       glBegin( GL_LINES );
  381.  
  382.       for ( i = 0 ; i < width ; i += 10 )
  383.       {
  384.      for ( j = 0 ; j < height ; j += 10 )
  385.      {
  386.         glVertex2i( 0, j );
  387.         glVertex2i( width, j );
  388.         glVertex2i( i, height );
  389.         glVertex2i( i, 0 );
  390.      }
  391.       }
  392.  
  393.       glColor3f( 1.0, 1.0, 0.0 );
  394.  
  395.       for ( i = 0 ; i <= contour_cnt ; i++ )
  396.       {
  397.      point_cnt = contours[i].point_cnt;
  398.  
  399.      glBegin( GL_LINES );
  400.  
  401.      switch ( point_cnt )
  402.      {
  403.      case 0:
  404.         break;
  405.      case 1:
  406.         glVertex2fv( contours[i].p[0] );
  407.         glVertex2fv( contours[i].p[0] );
  408.         break;
  409.      case 2:
  410.         glVertex2fv( contours[i].p[0] );
  411.         glVertex2fv( contours[i].p[1] );
  412.         break;
  413.      default:
  414.         --point_cnt;
  415.         for ( j = 0 ; j < point_cnt ; j++ )
  416.         {
  417.            glVertex2fv( contours[i].p[j] );
  418.            glVertex2fv( contours[i].p[j+1] );
  419.         }
  420.         if ( contours[i].p[j+1][0] == -1 )
  421.         {
  422.            glVertex2fv( contours[i].p[0] );
  423.            glVertex2fv( contours[i].p[j] );
  424.         }
  425.         break;
  426.      }
  427.  
  428.      glEnd();
  429.       }
  430.  
  431.       glFinish();
  432.       break;
  433.  
  434.    case TESSELATED:
  435.       /* draw triangles */
  436.       glColor3f( 0.7, 0.7, 0.0 );
  437.       glCallList( list_start );
  438.  
  439.       glLineWidth( 2.0 );
  440.       glCallList( list_start + 1 );
  441.       glLineWidth( 1.0 );
  442.  
  443.       glFlush();
  444.       break;
  445.    }
  446.  
  447.    glColor3f( 1.0, 1.0, 0.0 );
  448. }
  449.  
  450. void clear( void )
  451. {
  452.    contour_cnt = 0;
  453.    contours[0].point_cnt = 0;
  454.    triangle_cnt = 0;
  455.  
  456.    glutMouseFunc( mouse_clicked );
  457.  
  458.    mode = DEFINE;
  459.  
  460.    glDeleteLists( list_start, 2 );
  461.    list_start = 0;
  462. }
  463.  
  464. void quit( void )
  465. {
  466.    exit( 0 );
  467. }
  468.  
  469. void menu_selected( int entry )
  470. {
  471.    switch ( entry )
  472.    {
  473.    case CLEAR:
  474.       clear();
  475.       break;
  476.    case TESSELATE:
  477.       tesse();
  478.       break;
  479.    case QUIT:
  480.       quit();
  481.       break;
  482.    }
  483.  
  484.    glutPostRedisplay();
  485. }
  486.  
  487. void key_pressed( unsigned char key, int x, int y )
  488. {
  489.    (void) x;
  490.    (void) y;
  491.  
  492.    switch ( key )
  493.    {
  494.    case 'c':
  495.    case 'C':
  496.       clear();
  497.       break;
  498.    case 't':
  499.    case 'T':
  500.       tesse();
  501.       break;
  502.    case 'q':
  503.    case 'Q':
  504.       quit();
  505.       break;
  506.    }
  507.  
  508.    glutPostRedisplay();
  509. }
  510.  
  511. void myinit( void )
  512. {
  513.    /* clear background to gray */
  514.    glClearColor( 0.4, 0.4, 0.4, 0.0 );
  515.    glShadeModel( GL_FLAT );
  516.    glPolygonMode( GL_FRONT, GL_FILL );
  517.  
  518.    menu = glutCreateMenu( menu_selected );
  519.  
  520.    glutAddMenuEntry( "clear", CLEAR );
  521.    glutAddMenuEntry( "tesselate", TESSELATE );
  522.    glutAddMenuEntry( "quit", QUIT );
  523.  
  524.    glutAttachMenu( GLUT_RIGHT_BUTTON );
  525.  
  526.    glutMouseFunc( mouse_clicked );
  527.    glutKeyboardFunc( key_pressed );
  528.  
  529.    contour_cnt = 0;
  530.    mode = DEFINE;
  531. }
  532.  
  533. static void reshape( GLsizei w, GLsizei h )
  534. {
  535.    glViewport( 0, 0, w, h );
  536.  
  537.    glMatrixMode( GL_PROJECTION );
  538.    glLoadIdentity();
  539.    glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
  540.  
  541.    glMatrixMode( GL_MODELVIEW );
  542.    glLoadIdentity();
  543.  
  544.    set_screen_wh( w, h );
  545. }
  546.  
  547.  
  548. static void usage( void )
  549. {
  550.    printf( "Use left mouse button to place vertices.\n" );
  551.    printf( "Press middle mouse button when done.\n" );
  552.    printf( "Select tesselate from the pop-up menu.\n" );
  553. }
  554.  
  555.  
  556. /*
  557.  * Main Loop
  558.  * Open window with initial window size, title bar,
  559.  * RGBA display mode, and handle input events.
  560.  */
  561. int main( int argc, char **argv )
  562. {
  563.     usage();
  564.  
  565.     glutInit( &argc, argv );
  566.     glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
  567.     glutInitWindowSize( 400, 400 );
  568.     glutCreateWindow( argv[0] );
  569.  
  570.     myinit();
  571.  
  572.     glutDisplayFunc( display );
  573.     glutReshapeFunc( reshape );
  574.  
  575.     glutMainLoop();
  576.  
  577.     return 0;
  578. }
  579.