home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 2000 April & May / AMIGA_2000_04.iso / patches / mesa3.1 / mesa-3_1.lha / src-glu / tess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-07  |  28.1 KB  |  1,044 lines

  1. /* $Id: tess.c,v 1.20.2.7 1999/12/05 17:01:17 gareth Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  *
  7.  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27. /*****************************************************************************
  28.  *
  29.  * GLU 1.3 Polygon Tessellation by Gareth Hughes <garethh@bell-labs.com>
  30.  *
  31.  *****************************************************************************/
  32.  
  33. #include <stdarg.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <math.h>
  37.  
  38. #include "gluP.h"
  39.  
  40. #include "tess.h"
  41. #include "tess_macros.h"
  42. #include "tess_fist.h"
  43. #if 0
  44. #include "tess_grid.h"
  45. #endif
  46.  
  47.  
  48. #define TESS_CHECK_ERRORS(t)    if ( (t)->error != GLU_NO_ERROR ) goto cleanup
  49.  
  50. #ifdef DEBUG
  51. GLint        tess_dbg_level;
  52. #endif
  53.  
  54.  
  55. /*****************************************************************************
  56.  * tess_error_callback
  57.  *
  58.  * Internal error handler.  Call the user-registered error callback.
  59.  *
  60.  * 2nd arg changed from 'errno' to 'errnum' since MSVC defines errnum as
  61.  *  a macro (of all things) and thus breaks the build -tjump
  62.  *****************************************************************************/
  63. void tess_error_callback( GLUtesselator *tobj, GLenum errnum )
  64. {
  65.     if ( tobj->error == GLU_NO_ERROR )
  66.     {
  67.     tobj->error = errnum;
  68.     }
  69.  
  70.     if ( tobj->callbacks.errorData != NULL )
  71.     {
  72.     ( tobj->callbacks.errorData )( errnum, tobj->data );
  73.     }
  74.     else if ( tobj->callbacks.error != NULL )
  75.     {
  76.     ( tobj->callbacks.error )( errnum );
  77.     }
  78. }
  79.  
  80.  
  81. /*****************************************************************************
  82.  * init_callbacks
  83.  *****************************************************************************/
  84. static void init_callbacks( tess_callbacks_t *callbacks )
  85. {
  86.     callbacks->begin        = ( void (GLCALLBACK*)(GLenum) ) NULL;
  87.     callbacks->beginData    = ( void (GLCALLBACK*)(GLenum, void *) ) NULL;
  88.     callbacks->edgeFlag     = ( void (GLCALLBACK*)(GLboolean) ) NULL;
  89.     callbacks->edgeFlagData = ( void (GLCALLBACK*)(GLboolean, void *) ) NULL;
  90.     callbacks->vertex       = ( void (GLCALLBACK*)(void *) ) NULL;
  91.     callbacks->vertexData   = ( void (GLCALLBACK*)(void *, void *) ) NULL;
  92.     callbacks->end          = ( void (GLCALLBACK*)(void) ) NULL;
  93.     callbacks->endData      = ( void (GLCALLBACK*)(void *) ) NULL;
  94.     callbacks->error        = ( void (GLCALLBACK*)(GLenum) ) NULL;
  95.     callbacks->errorData    = ( void (GLCALLBACK*)(GLenum, void *) ) NULL;
  96.     callbacks->combine      = ( void (GLCALLBACK*)(GLdouble [3], void *[4],
  97.                            GLfloat [4], void **) ) NULL;
  98.     callbacks->combineData  = ( void (GLCALLBACK*)(GLdouble [3], void *[4],
  99.                            GLfloat [4], void **,
  100.                            void *) ) NULL;
  101. }
  102.  
  103.  
  104. /*****************************************************************************
  105.  * find_normal
  106.  *****************************************************************************/
  107. static GLenum find_normal( GLUtesselator *tobj )
  108. {
  109.     tess_contour_t    *contour = tobj->current_contour;
  110.     tess_vertex_t    *va, *vb, *vc;
  111.     GLdouble        a[3], b[3], c[3];
  112.  
  113.     MSG( 15, "      --> find_normal( tobj:%p )\n", tobj );
  114.  
  115.     if ( contour == NULL ) { return GLU_ERROR; }
  116.  
  117.     va = contour->vertices;
  118.     vb = va->next;
  119.  
  120.     /* If va and vb are the same point, keep looking for a different vertex. */
  121.  
  122.     while ( IS_EQUAL_3DV( va->coords, vb->coords ) && ( vb != va ) ) {
  123.     vb = vb->next;
  124.     }
  125.  
  126.     if ( vb == va ) {
  127.     /* FIXME: What error is this? */
  128.     tess_error_callback( tobj, GLU_TESS_ERROR7 );
  129.     }
  130.  
  131.     SUB_3V( a, vb->coords, va->coords );
  132.  
  133.     for ( vc = vb->next; vc != va; vc = vc->next )
  134.     {
  135.     SUB_3V( b, vc->coords, va->coords );
  136.  
  137.     CROSS_3V( c, a, b );
  138.  
  139.     if ( ! IS_ZERO_3DV( c ) )
  140.     {
  141.         MSG( 15, "            using (%.2f,%.2f) -> (%.2f,%.2f) -> (%.2f,%.2f)\n",
  142.          va->coords[X], va->coords[Y],
  143.          vb->coords[X], vb->coords[Y],
  144.          vc->coords[X], vc->coords[Y] );
  145.  
  146.         COPY_3V( contour->plane.normal, c );
  147.         NORMALIZE_3DV( contour->plane.normal );
  148.  
  149.         contour->plane.dist = - DOT_3V( contour->plane.normal,
  150.                         va->coords );
  151.  
  152.         MSG( 15, "      <-- find_normal( tobj:%p ) n: (%.2f, %.2f, %.2f)\n", tobj, contour->plane.normal[X], contour->plane.normal[Y], contour->plane.normal[Z] );
  153.         return GLU_NO_ERROR;
  154.     }
  155.     }
  156.     /* FIXME: What error is this? */
  157.     tess_error_callback( tobj, GLU_TESS_ERROR7 );
  158.  
  159.     return GLU_ERROR;
  160. }
  161.  
  162. /*****************************************************************************
  163.  * twice_contour_area
  164.  *
  165.  * Calculate the twice the signed area of the given contour.  Used to
  166.  * determine the contour's orientation amongst other things.
  167.  *****************************************************************************/
  168. GLdouble twice_contour_area( tess_contour_t *contour )
  169. {
  170.     tess_vertex_t    *vertex = contour->vertices;
  171.     GLdouble        area, x, y;
  172.  
  173.     area = 0.0;
  174.  
  175.     x = vertex->v[X];
  176.     y = vertex->v[Y];
  177.  
  178.     vertex = vertex->next;
  179.  
  180.     do
  181.     {
  182.     area += ( (vertex->v[X] - x) * (vertex->next->v[Y] - y) -
  183.           (vertex->v[Y] - y) * (vertex->next->v[X] - x) );
  184.     vertex = vertex->next;
  185.     }
  186.     while ( vertex != contour->vertices );
  187.  
  188.     return area;
  189. }
  190.  
  191. /*****************************************************************************
  192.  * project_current_contour
  193.  *
  194.  * Project the contour's vertices onto the tessellation plane.  We perform
  195.  * a complex rotation here to allow non-axis-aligned tessellation normals.
  196.  *****************************************************************************/
  197. static void project_current_contour( GLUtesselator *tobj )
  198. {
  199.     tess_contour_t    *current = tobj->current_contour;
  200.     tess_vertex_t    *vertex;
  201.     GLdouble        zaxis[3] = { 0.0, 0.0, 1.0 }, znormal[3], xnormal[3];
  202.     GLdouble        dot, rotx, roty;
  203.     GLint        i;
  204.  
  205.     MSG( 15, "      --> project_current_contour( tobj:%p )\n", tobj );
  206.  
  207.     if ( current == NULL ) { return; }
  208.  
  209.     /* Rotate the plane normal around the y-axis. */
  210.  
  211.     znormal[X] = current->plane.normal[X];
  212.     znormal[Y] = 0.0;
  213.     znormal[Z] = current->plane.normal[Z];
  214.  
  215.     dot = DOT_3V( znormal, zaxis );
  216.     current->roty = roty = acos( dot );
  217.  
  218.     /* Rotate the plane normal around the x-axis. */
  219.  
  220.     xnormal[X] = cos( roty ) * znormal[X] - sin( roty ) * znormal[Z];
  221.     xnormal[Y] = znormal[Y];
  222.     xnormal[Z] = sin( roty ) * znormal[X] + cos( roty ) * znormal[Z];
  223.  
  224.     dot = DOT_3V( xnormal, zaxis );
  225.     current->rotx = rotx = acos( dot );
  226.  
  227.     for ( vertex = current->vertices, i = 0;
  228.       i < current->num_vertices; vertex = vertex->next, i++ )
  229.     {
  230.     tess_plane_t    *plane = ¤t->plane;
  231.     GLdouble    proj[3], yrot[3], xrot[3];
  232.  
  233.     /* FIXME: This needs a cleanup, 'cos I'm sure it's inefficient. */
  234.  
  235.     proj[X] = vertex->coords[X] - plane->dist * plane->normal[X];
  236.     proj[Y] = vertex->coords[Y] - plane->dist * plane->normal[Y];
  237.     proj[Z] = vertex->coords[Z] - plane->dist * plane->normal[Z];
  238.  
  239.     yrot[X] = cos( roty ) * proj[X] - sin( roty ) * proj[Z];
  240.     yrot[Y] = proj[Y];
  241.     yrot[Z] = sin( roty ) * proj[X] + cos( roty ) * proj[Z];
  242.  
  243.     xrot[X] = yrot[X];
  244.     xrot[Y] = cos( rotx ) * yrot[Y] - sin( rotx ) * yrot[Z];
  245.     xrot[Z] = sin( rotx ) * yrot[Y] + cos( rotx ) * yrot[Z];
  246.  
  247.     vertex->v[X] = xrot[X];
  248.     vertex->v[Y] = xrot[Y];
  249.  
  250.     ACC_BBOX_2V( vertex->v, tobj->mins, tobj->maxs );
  251.     ACC_BBOX_2V( vertex->v, current->mins, current->maxs );
  252.     }
  253.  
  254.     current->area = twice_contour_area( current );
  255.     current->orientation = ( current->area >= 0.0 ) ? GLU_CCW : GLU_CW;
  256.  
  257.     MSG( 15, "            area: %.2f orientation: %s\n",
  258.      current->area, ( current->orientation == GLU_CCW ) ? "CCW" : "CW" );
  259.  
  260.     MSG( 15, "      <-- project_current_contour( tobj:%p )\n", tobj );
  261. }
  262.  
  263. /*****************************************************************************
  264.  * save_current_contour
  265.  *****************************************************************************/
  266. static GLenum save_current_contour( GLUtesselator *tobj )
  267. {
  268.     tess_contour_t    *current = tobj->current_contour;
  269.     tess_vertex_t    *vertex;
  270.     GLint        i;
  271.  
  272.     if ( current == NULL ) { return GLU_ERROR; }
  273.  
  274.     if ( tobj->contours == NULL )
  275.     {
  276.     tobj->contours = tobj->last_contour = current;
  277.     current->next = current->prev = NULL;
  278.  
  279.     tobj->orientation = current->orientation;
  280.     }
  281.     else
  282.     {
  283.     current->prev = tobj->last_contour;
  284.  
  285.     tobj->last_contour->next = current;
  286.     tobj->last_contour = current;
  287.  
  288.     current->next = NULL;
  289.     }
  290.  
  291.     for ( vertex = current->vertices, i = 0;
  292.       i < current->num_vertices; vertex = vertex->next, i++ )
  293.     {
  294.     vertex->edge_flag = GL_TRUE;
  295.     }
  296.  
  297.     current->type = GLU_UNKNOWN;
  298.  
  299.     tobj->num_contours++;
  300.     tobj->current_contour = NULL;
  301.  
  302.     return GLU_NO_ERROR;
  303. }
  304.  
  305. /*****************************************************************************
  306.  * inspect_current_contour
  307.  *****************************************************************************/
  308. static void inspect_current_contour( GLUtesselator *tobj )
  309. {
  310.     tess_contour_t    *current = tobj->current_contour;
  311.     GLdouble        origin[3] = { 0.0, 0.0, 0.0 };
  312.     GLboolean        calc_normal = GL_FALSE;
  313.  
  314.     MSG( 15, "    --> inspect_current_contour( tobj:%p )\n", tobj );
  315.  
  316.     if ( current->num_vertices < 3 )
  317.     {
  318.     MSG( 15, "          count %d < 3, deleting\n", current->num_vertices );
  319.     delete_contour( &tobj->current_contour );
  320.     return;
  321.     }
  322.  
  323.     current->last_vertex->next = current->vertices;
  324.     current->vertices->prev = current->last_vertex;
  325.  
  326.     MSG( 15, "          current normal: (%.2f, %.2f, %.2f)\n", current->plane.normal[X], current->plane.normal[Y], current->plane.normal[Z] );
  327.  
  328.     if ( IS_EQUAL_3DV( current->plane.normal, origin ) )
  329.     {
  330.     /* We haven't been given a normal, so let's take a guess. */
  331.     if ( find_normal( tobj ) == GLU_ERROR ) {
  332.         return;
  333.     }
  334.  
  335.     COPY_3V( tobj->plane.normal, current->plane.normal );
  336.     tobj->plane.dist = current->plane.dist;
  337.  
  338.     calc_normal = GL_TRUE;
  339.     }
  340.  
  341.     project_current_contour( tobj );
  342.  
  343.     if ( calc_normal && ( tobj->current_contour->orientation == GLU_CW ) )
  344.     {
  345.     MSG( 15, "          oops, let's try that again...\n" );
  346.  
  347.     /*
  348.      * FIXME: We've used a reflex angle to calculate the normal.  At
  349.      * the moment, we simply reverse the normal and re-project the
  350.      * contour, but this is sloooow...
  351.      */
  352.     NEG_3V( tobj->plane.normal );
  353.     NEG_3V( tobj->current_contour->plane.normal );
  354.  
  355.     project_current_contour( tobj );
  356.     }
  357.  
  358.     if ( save_current_contour( tobj ) == GLU_ERROR ) {
  359.     return;
  360.     }
  361.  
  362.     MSG( 15, "    <-- inspect_current_contour( tobj:%p )\n", tobj );
  363. }
  364.  
  365. /*****************************************************************************
  366.  * reverse_contour
  367.  *****************************************************************************/
  368. void reverse_contour( tess_contour_t *contour )
  369. {
  370.     tess_vertex_t    *current = contour->vertices;
  371.     GLint        i;
  372.  
  373.     for ( i = 0 ; i < contour->num_vertices ; i++ )
  374.     {
  375.     tess_vertex_t    *next = current->next;
  376.     tess_vertex_t    *prev = current->prev;
  377.  
  378.     current->next = prev;
  379.     current->prev = next;
  380.  
  381.     current = next;
  382.     }
  383.  
  384.     contour->orientation =
  385.     ( contour->orientation == GLU_CCW ) ? GLU_CW : GLU_CCW;
  386.  
  387.     contour->last_vertex = contour->vertices->prev;
  388. }
  389.  
  390. /*****************************************************************************
  391.  * orient_contours
  392.  *
  393.  * Sum the signed areas of the contours, and orient the contours such that
  394.  * this sum is nonnegative.
  395.  *****************************************************************************/
  396. static void orient_contours( GLUtesselator *tobj )
  397. {
  398.     tess_contour_t    *contour = tobj->contours;
  399.     GLdouble        sum = 0.0;
  400.     GLint        i;
  401.  
  402.     MSG( 15, "    --> orient_contours( tobj:%p )\n", tobj );
  403.  
  404.     /* Sum the signed areas of all contours */
  405.     for ( i = 0 ; i < tobj->num_contours ; i++ )
  406.     {
  407.     sum += contour->area;
  408.     contour = contour->next;
  409.     }
  410.  
  411.     MSG( 15, "          signed area: %.2f\n", sum );
  412.  
  413.     if ( sum < -GLU_TESS_EPSILON )
  414.     {
  415.     for ( i = 0 ; i < tobj->num_contours ; i++ )
  416.     {
  417.         contour->area = ABSD( contour->area );
  418.         reverse_contour( contour );
  419.  
  420.         contour = contour->next;
  421.     }
  422.     }
  423.     else
  424.     {
  425.     for ( i = 0 ; i < tobj->num_contours ; i++ )
  426.     {
  427.         contour->area = ABSD( contour->area );
  428.  
  429.         contour = contour->next;
  430.     }
  431.     }
  432.  
  433.     tobj->orientation = tobj->contours->orientation;
  434.  
  435.     MSG( 15, "    <-- orient_contours( tobj:%p ) orient: %s\n",
  436.      tobj, ( tobj->orientation == GLU_CCW ) ? "GLU_CCW" : "GLU_CW" );
  437. }
  438.  
  439.  
  440. /*****************************************************************************
  441.  * delete_contour
  442.  *
  443.  * Delete the given contour and set the pointer to NULL.
  444.  *****************************************************************************/
  445. void delete_contour( tess_contour_t **contour )
  446. {
  447.     tess_vertex_t    *vertex, *next;
  448.     GLint        i;
  449.  
  450.     if ( *contour == NULL ) { return; }
  451.  
  452.     vertex = (*contour)->vertices;
  453.  
  454.     for ( i = 0 ; i < (*contour)->num_vertices ; i++ )
  455.     {
  456.     next = vertex->next;
  457.     free( vertex );
  458.     vertex = next;
  459.     }
  460.  
  461.     free( *contour );
  462.     *contour = NULL;
  463. }
  464.  
  465. /*****************************************************************************
  466.  * delete_all_contours
  467.  *****************************************************************************/
  468. static void delete_all_contours( GLUtesselator *tobj )
  469. {
  470.     tess_contour_t    *current, *next_contour;
  471.     GLint        i;
  472.  
  473.     if ( tobj->current_contour != NULL ) {
  474.     delete_contour( &tobj->current_contour );
  475.     }
  476.  
  477.     for ( current = tobj->contours, i = 0 ; i < tobj->num_contours ; i++ )
  478.     {
  479.     tess_vertex_t    *vertex = current->vertices, *next_vertex;
  480.     GLint        j;
  481.  
  482.     for ( j = 0 ; j < current->num_vertices ; j ++ )
  483.     {
  484.         next_vertex = vertex->next;
  485.         free( vertex );
  486.         vertex = next_vertex;
  487.     }
  488.     next_contour = current->next;
  489.  
  490.     free( current );
  491.     current = next_contour;
  492.     }
  493.  
  494.     tobj->num_contours = tobj->num_vertices = 0;
  495.     tobj->contours = tobj->last_contour = NULL;
  496.  
  497.     CLEAR_BBOX_2DV( tobj->mins, tobj->maxs );
  498. }
  499.  
  500.  
  501. /*****************************************************************************
  502.  * tess_cleanup
  503.  *****************************************************************************/
  504. static void tess_cleanup( GLUtesselator *tobj )
  505. {
  506.     MSG( 15, "  -> tess_cleanup( tobj:%p )\n", tobj );
  507.  
  508.     if ( tobj->current_contour != NULL ) {
  509.     delete_contour( &tobj->current_contour );
  510.     }
  511.     if ( tobj->contours != NULL ) {
  512.     delete_all_contours( tobj );
  513.     }
  514.  
  515.     MSG( 15, "  <- tess_cleanup( tobj:%p )\n", tobj );
  516. }
  517.  
  518.  
  519. /*****************************************************************************
  520.  * tess_msg
  521.  *****************************************************************************/
  522. INLINE void tess_msg( GLint level, char *format, ... )
  523. {
  524. #ifdef DEBUG
  525.     va_list ap;
  526.     va_start( ap, format );
  527.  
  528.     if ( level <= tess_dbg_level ) {
  529.     vfprintf( DBG_STREAM, format, ap );
  530.     fflush( DBG_STREAM );
  531.     }
  532.  
  533.     va_end( ap );
  534. #endif
  535. }
  536.  
  537. INLINE void tess_info( char *file, GLint line )
  538. {
  539. #ifdef DEBUG
  540.     fprintf( DBG_STREAM, "%9.9s:%d:\t ", file, line );
  541. #endif
  542. }
  543.  
  544.  
  545.  
  546. /*****************************************************************************
  547.  *
  548.  *            GLU TESSELLATION FUNCTIONS
  549.  *
  550.  *****************************************************************************/
  551.  
  552.  
  553. /*****************************************************************************
  554.  * gluNewTess
  555.  *****************************************************************************/
  556. GLUtesselator* GLAPIENTRY gluNewTess( void )
  557. {
  558.     GLUtesselator *tobj;
  559.  
  560. #ifdef DEBUG
  561.     if ( getenv( "GLU_TESS_DBG_LEVEL" ) ) {
  562.     tess_dbg_level = atoi( getenv( "GLU_TESS_DBG_LEVEL" ) );
  563.     } else {
  564.     tess_dbg_level = DBG_LEVEL_BASE;
  565.     }
  566. #endif
  567.  
  568.     MSG( 15, "-> gluNewTess()\n" );
  569.  
  570.     tobj = malloc( sizeof(GLUtesselator) );
  571.     if ( tobj == NULL ) {
  572.     return NULL;
  573.     }
  574.  
  575.     init_callbacks( &tobj->callbacks );
  576.  
  577.     tobj->winding_rule = GLU_TESS_WINDING_ODD;
  578.     tobj->boundary_only = GL_FALSE;
  579.     tobj->tolerance = GLU_TESS_EPSILON;
  580.     tobj->orientation = GLU_UNKNOWN;
  581.  
  582.     tobj->data = NULL;
  583.  
  584.     tobj->num_contours = 0;
  585.     tobj->contours = tobj->last_contour = NULL;
  586.     tobj->current_contour = NULL;
  587.  
  588.     CLEAR_BBOX_2DV( tobj->mins, tobj->maxs );
  589.  
  590.     tobj->num_vertices = 0;
  591.     tobj->sorted_vertices = NULL;
  592. #if 0
  593.     tobj->grid = NULL;
  594. #endif
  595.     tobj->edge_flag = GL_FALSE;
  596.     tobj->label = 0;
  597.  
  598.     ZERO_3V( tobj->plane.normal );
  599.     tobj->plane.dist = 0.0;
  600.  
  601.     tobj->error = GLU_NO_ERROR;
  602.  
  603.     MSG( 15, "<- gluNewTess() tobj:%p\n", tobj );
  604.     return tobj;
  605. }
  606.  
  607.  
  608. /*****************************************************************************
  609.  * gluDeleteTess
  610.  *****************************************************************************/
  611. void GLAPIENTRY gluDeleteTess( GLUtesselator *tobj )
  612. {
  613.     MSG( 15, "-> gluDeleteTess( tobj:%p )\n", tobj );
  614.  
  615.     if ( ( tobj->error == GLU_NO_ERROR ) && ( tobj->num_contours > 0 ) )
  616.     {
  617.     /* gluEndPolygon was not called. */
  618.     tess_error_callback( tobj, GLU_TESS_ERROR3 );
  619.     }
  620.  
  621.     /* Delete all internal structures. */
  622.     tess_cleanup( tobj );
  623.     free( tobj );
  624.  
  625.     MSG( 15, "<- gluDeleteTess()\n" );
  626. }
  627.  
  628.  
  629. /*****************************************************************************
  630.  * gluTessBeginPolygon
  631.  *****************************************************************************/
  632. void GLAPIENTRY gluTessBeginPolygon( GLUtesselator *tobj, void *polygon_data )
  633. {
  634.     MSG( 15, "-> gluTessBeginPolygon( tobj:%p data:%p )\n", tobj, polygon_data );
  635.  
  636.     tobj->error = GLU_NO_ERROR;
  637.  
  638.     if ( tobj->current_contour != NULL )
  639.     {
  640.     /* gluEndPolygon was not called. */
  641.     tess_error_callback( tobj, GLU_TESS_ERROR3 );
  642.     tess_cleanup( tobj );
  643.     }
  644.  
  645.     tobj->data = polygon_data;
  646.     tobj->num_vertices = 0;
  647.     tobj->edge_flag = GL_FALSE;
  648.     tobj->label = 0;
  649.  
  650.     MSG( 15, "<- gluTessBeginPolygon( tobj:%p data:%p )\n", tobj, polygon_data );
  651. }
  652.  
  653.  
  654. /*****************************************************************************
  655.  * gluTessBeginContour
  656.  *****************************************************************************/
  657. void GLAPIENTRY gluTessBeginContour( GLUtesselator *tobj )
  658. {
  659.     MSG( 15, "  -> gluTessBeginContour( tobj:%p )\n", tobj );
  660.     TESS_CHECK_ERRORS( tobj );
  661.  
  662.     if ( tobj->current_contour != NULL )
  663.     {
  664.     /* gluTessEndContour was not called. */
  665.     tess_error_callback( tobj, GLU_TESS_ERROR4 );
  666.     return;
  667.     }
  668.  
  669.     tobj->current_contour = malloc( sizeof(tess_contour_t) );
  670.     if ( tobj->current_contour == NULL ) {
  671.     tess_error_callback( tobj, GLU_OUT_OF_MEMORY );
  672.     return;
  673.     }
  674.  
  675.     COPY_3V( tobj->current_contour->plane.normal, tobj->plane.normal );
  676.     tobj->current_contour->plane.dist = tobj->plane.dist;
  677.  
  678.     tobj->current_contour->area = 0.0;
  679.     tobj->current_contour->orientation = GLU_UNKNOWN;
  680.  
  681.     tobj->current_contour->label = 0;
  682.     tobj->current_contour->winding = 0;
  683.  
  684.     /*tobj->current_contour->rotx = tobj->current_contour->roty = 0.0;*/
  685.  
  686.     CLEAR_BBOX_2DV( tobj->current_contour->mins,
  687.             tobj->current_contour->maxs );
  688.  
  689.     tobj->current_contour->num_vertices = 0;
  690.     tobj->current_contour->vertices =
  691.     tobj->current_contour->last_vertex = NULL;
  692.  
  693.     tobj->current_contour->reflex_vertices = NULL;
  694.  
  695.  cleanup:
  696.     MSG( 15, "  <- gluTessBeginContour( tobj:%p )\n", tobj );
  697.     return;
  698. }
  699.  
  700.  
  701. /*****************************************************************************
  702.  * gluTessVertex
  703.  *****************************************************************************/
  704. void GLAPIENTRY gluTessVertex( GLUtesselator *tobj, GLdouble coords[3],
  705.                    void *vertex_data )
  706. {
  707.     tess_contour_t        *current = tobj->current_contour;
  708.     tess_vertex_t        *last_vertex;
  709.  
  710.     MSG( 15, "    -> gluTessVertex( tobj:%p coords:(%.2f,%.2f,%.2f) )\n", tobj, coords[0], coords[1], coords[2] );
  711.     TESS_CHECK_ERRORS( tobj );
  712.  
  713.     if ( current == NULL )
  714.     {
  715.     /* gluTessBeginContour was not called. */
  716.     tess_error_callback( tobj, GLU_TESS_ERROR2 );
  717.     return;
  718.     }
  719.  
  720.     tobj->num_vertices++;
  721.  
  722.     last_vertex = current->last_vertex;
  723.  
  724.     if ( last_vertex == NULL )
  725.     {
  726.     last_vertex = malloc( sizeof(tess_vertex_t) );
  727.     if ( last_vertex == NULL ) {
  728.         tess_error_callback( tobj, GLU_OUT_OF_MEMORY );
  729.         return;
  730.     }
  731.  
  732.     current->vertices = last_vertex;
  733.     current->last_vertex = last_vertex;
  734.  
  735.     last_vertex->index = -1;
  736.     last_vertex->data = vertex_data;
  737.  
  738.     last_vertex->coords[X] = coords[X];
  739.     last_vertex->coords[Y] = coords[Y];
  740.     last_vertex->coords[Z] = coords[Z];
  741.  
  742.     last_vertex->v[X] = 0.0;
  743.     last_vertex->v[Y] = 0.0;
  744.  
  745.     last_vertex->edge_flag = GL_TRUE;
  746.  
  747.     last_vertex->side = 0.0;
  748.  
  749.     last_vertex->next = NULL;
  750.     last_vertex->prev = NULL;
  751.  
  752.     current->num_vertices++;
  753.     }
  754.     else
  755.     {
  756.     tess_vertex_t    *vertex;
  757.  
  758.     vertex = malloc( sizeof(tess_vertex_t) );
  759.     if ( vertex == NULL ) {
  760.         tess_error_callback( tobj, GLU_OUT_OF_MEMORY );
  761.         return;
  762.     }
  763.  
  764.     vertex->index = -1;
  765.     vertex->data = vertex_data;
  766.  
  767.     vertex->coords[X] = coords[X];
  768.     vertex->coords[Y] = coords[Y];
  769.     vertex->coords[Z] = coords[Z];
  770.  
  771.     vertex->v[X] = 0.0;
  772.     vertex->v[Y] = 0.0;
  773.  
  774.     vertex->edge_flag = GL_TRUE;
  775.  
  776.     vertex->side = 0.0;
  777.  
  778.     vertex->next = NULL;
  779.     vertex->prev = last_vertex;
  780.  
  781.     current->num_vertices++;
  782.  
  783.     last_vertex->next = vertex;
  784.     current->last_vertex = vertex;
  785.     }
  786.  
  787.  cleanup:
  788.     MSG( 15, "    <- gluTessVertex( tobj:%p )\n", tobj );
  789.     return;
  790. }
  791.  
  792.  
  793. /*****************************************************************************
  794.  * gluTessEndContour
  795.  *****************************************************************************/
  796. void GLAPIENTRY gluTessEndContour( GLUtesselator *tobj )
  797. {
  798.     MSG( 15, "  -> gluTessEndContour( tobj:%p )\n", tobj );
  799.     TESS_CHECK_ERRORS( tobj );
  800.  
  801.     if ( tobj->current_contour == NULL )
  802.     {
  803.     /* gluTessBeginContour was not called. */
  804.     tess_error_callback( tobj, GLU_TESS_ERROR2 );
  805.     return;
  806.     }
  807.  
  808.     if ( tobj->current_contour->num_vertices > 0 ) {
  809.     inspect_current_contour( tobj );
  810.     } else {
  811.     delete_contour( &tobj->current_contour );
  812.     }
  813.  
  814.  cleanup:
  815.     MSG( 15, "  <- gluTessEndContour( tobj:%p )\n", tobj );
  816.     return;
  817. }
  818.  
  819.  
  820. /*****************************************************************************
  821.  * gluTessEndPolygon
  822.  *****************************************************************************/
  823. void GLAPIENTRY gluTessEndPolygon( GLUtesselator *tobj )
  824. {
  825.     MSG( 15, "-> gluTessEndPolygon( tobj:%p )\n", tobj );
  826.     TESS_CHECK_ERRORS( tobj );
  827.  
  828.     if ( tobj->current_contour != NULL )
  829.     {
  830.     /* gluTessBeginPolygon was not called. */
  831.     tess_error_callback( tobj, GLU_TESS_ERROR1 );
  832.     return;
  833.     }
  834.     TESS_CHECK_ERRORS( tobj );
  835.  
  836.     /*
  837.      * Ensure we have at least one contour to tessellate.  If we have none,
  838.      *  clean up and exit gracefully.
  839.      */
  840.     if ( tobj->num_contours == 0 ) {
  841.     tess_cleanup( tobj );
  842.     return;
  843.     }
  844.  
  845.     /* Wrap the contour list. */
  846.  
  847.     tobj->last_contour->next = tobj->contours;
  848.     tobj->contours->prev = tobj->last_contour;
  849.  
  850.     TESS_CHECK_ERRORS( tobj );
  851.  
  852.     /* Orient the contours correctly */
  853.     orient_contours( tobj );
  854.  
  855.     /*
  856.      * Before we tessellate the contours, ensure we have the appropriate
  857.      *  callbacks registered.  We at least need the begin, vertex and end
  858.      *  callbacks to do any meaningful work.
  859.      */
  860.     if ( ( ( tobj->callbacks.begin != NULL ) ||
  861.        ( tobj->callbacks.beginData != NULL ) ) &&
  862.      ( ( tobj->callbacks.vertex != NULL ) ||
  863.        ( tobj->callbacks.vertexData != NULL ) ) &&
  864.      ( ( tobj->callbacks.end != NULL ) ||
  865.        ( tobj->callbacks.endData != NULL ) ) )
  866.     {
  867.     fist_tessellation( tobj );
  868.     }
  869.  
  870.  cleanup:
  871.     delete_all_contours( tobj );
  872.     MSG( 15, "<- gluTessEndPolygon( tobj:%p )\n", tobj );
  873. }
  874.  
  875.  
  876. /*****************************************************************************
  877.  * gluTessCallback
  878.  *****************************************************************************/
  879. void GLAPIENTRY gluTessCallback( GLUtesselator *tobj, GLenum which,
  880.                  void (GLCALLBACK *fn)() )
  881. {
  882.     switch ( which )
  883.     {
  884.     /* Register the begin callbacks. */
  885.     case GLU_TESS_BEGIN:
  886.     tobj->callbacks.begin = (void (GLCALLBACK*)(GLenum)) fn;
  887.     break;
  888.     case GLU_TESS_BEGIN_DATA:
  889.     tobj->callbacks.beginData = (void (GLCALLBACK*)(GLenum, void *)) fn;
  890.     break;
  891.  
  892.     /* Register the edge flag callbacks. */
  893.     case GLU_TESS_EDGE_FLAG:
  894.     tobj->callbacks.edgeFlag = (void (GLCALLBACK*)(GLboolean)) fn;
  895.     break;
  896.     case GLU_TESS_EDGE_FLAG_DATA:
  897.     tobj->callbacks.edgeFlagData =
  898.         (void (GLCALLBACK*)(GLboolean, void *)) fn;
  899.     break;
  900.  
  901.     /* Register the vertex callbacks. */
  902.     case GLU_TESS_VERTEX:
  903.     tobj->callbacks.vertex = (void (GLCALLBACK*)(void *)) fn;
  904.     break;
  905.     case GLU_TESS_VERTEX_DATA:
  906.     tobj->callbacks.vertexData = (void (GLCALLBACK*)(void *, void *)) fn;
  907.     break;
  908.  
  909.     /* Register the end callbacks. */
  910.     case GLU_TESS_END:
  911.     tobj->callbacks.end = (void (GLCALLBACK*)(void)) fn;
  912.     break;
  913.     case GLU_TESS_END_DATA:
  914.     tobj->callbacks.endData = (void (GLCALLBACK*)(void *)) fn;
  915.     break;
  916.  
  917.     /* Register the error callbacks. */
  918.     case GLU_TESS_ERROR:
  919.     tobj->callbacks.error = (void (GLCALLBACK*)(GLenum)) fn;
  920.     break;
  921.     case GLU_TESS_ERROR_DATA:
  922.     tobj->callbacks.errorData = (void (GLCALLBACK*)(GLenum, void *)) fn;
  923.     break;
  924.  
  925.     /* Register the combine callbacks. */
  926.     case GLU_TESS_COMBINE:
  927.     tobj->callbacks.combine =
  928.         (void (GLCALLBACK*)(GLdouble[3], void *[4],
  929.                 GLfloat [4], void **)) fn;
  930.     break;
  931.     case GLU_TESS_COMBINE_DATA:
  932.     tobj->callbacks.combineData =
  933.         (void (GLCALLBACK*)(GLdouble[3], void *[4], GLfloat [4],
  934.                 void **, void *)) fn;
  935.     break;
  936.  
  937.     default:
  938.     MSG( 1, "  gluTessCallback( tobj:%p which:%d ) invalid enum\n", tobj, which );
  939.     tobj->error = GLU_INVALID_ENUM;
  940.     break;
  941.     }
  942. }
  943.  
  944.  
  945. /*****************************************************************************
  946.  * gluTessProperty
  947.  *
  948.  * Set the current value of the given property.
  949.  *****************************************************************************/
  950. void GLAPIENTRY gluTessProperty( GLUtesselator *tobj, GLenum which,
  951.                  GLdouble value )
  952. {
  953.     switch ( which )
  954.     {
  955.     case GLU_TESS_BOUNDARY_ONLY:
  956.     tobj->boundary_only = (GLboolean) value;
  957.     break;
  958.  
  959.     case GLU_TESS_TOLERANCE:
  960.     MSG( 15, "   gluTessProperty( tobj:%p ) tolerance: %0.9f\n", tobj, value );
  961.     tobj->tolerance = value;
  962.     break;
  963.  
  964.     case GLU_TESS_WINDING_RULE:
  965.     tobj->winding_rule = (GLenum) value;
  966.     break;
  967.  
  968.     default:
  969.     MSG( 1, "   gluTessProperty( tobj:%p which:%d ) invalid enum\n", tobj, which );
  970.     tobj->error = GLU_INVALID_ENUM;
  971.     break;
  972.     }
  973. }
  974.  
  975.  
  976. /*****************************************************************************
  977.  * gluGetTessProperty
  978.  *
  979.  * Return the current value of the given property.
  980.  *****************************************************************************/
  981. void GLAPIENTRY gluGetTessProperty( GLUtesselator *tobj, GLenum which,
  982.                     GLdouble *value )
  983. {
  984.     switch ( which )
  985.     {
  986.     case GLU_TESS_BOUNDARY_ONLY:
  987.     *value = tobj->boundary_only;
  988.     break;
  989.  
  990.     case GLU_TESS_TOLERANCE:
  991.     *value = tobj->tolerance;
  992.     break;
  993.  
  994.     case GLU_TESS_WINDING_RULE:
  995.     *value = tobj->winding_rule;
  996.     break;
  997.  
  998.     default:
  999.     MSG( 1, "   gluGetTessProperty( tobj:%p which:%d ) invalid enum\n", tobj, which );
  1000.     tobj->error = GLU_INVALID_ENUM;
  1001.     break;
  1002.     }
  1003. }
  1004.  
  1005.  
  1006. /*****************************************************************************
  1007.  * gluTessNormal
  1008.  *
  1009.  * Set the current tessellation normal.
  1010.  *****************************************************************************/
  1011. void GLAPIENTRY gluTessNormal( GLUtesselator *tobj, GLdouble x,
  1012.                    GLdouble y, GLdouble z )
  1013. {
  1014.     MSG( 15, "   gluTessNormal( tobj:%p n:(%.2f,%.2f,%.2f) )\n", tobj, x, y, z );
  1015.  
  1016.     ASSIGN_3V( tobj->plane.normal, x, y, z );
  1017. }
  1018.  
  1019.  
  1020.  
  1021. /*****************************************************************************
  1022.  *
  1023.  *            OBSOLETE TESSELLATION FUNCTIONS
  1024.  *
  1025.  *****************************************************************************/
  1026.  
  1027. void GLAPIENTRY gluBeginPolygon( GLUtesselator *tobj )
  1028. {
  1029.     gluTessBeginPolygon( tobj, NULL );
  1030.     gluTessBeginContour( tobj );
  1031. }
  1032.  
  1033. void GLAPIENTRY gluNextContour( GLUtesselator *tobj, GLenum type )
  1034. {
  1035.     gluTessEndContour( tobj );
  1036.     gluTessBeginContour( tobj );
  1037. }
  1038.  
  1039. void GLAPIENTRY gluEndPolygon( GLUtesselator *tobj )
  1040. {
  1041.     gluTessEndContour( tobj );
  1042.     gluTessEndPolygon( tobj );
  1043. }
  1044.