home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / Mesa-1.2.1 / src-glu / tess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-05  |  7.7 KB  |  330 lines

  1. /* tess.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: tess.c,v 1.9 1995/05/26 19:06:52 brianp Exp $
  26.  
  27. $Log: tess.c,v $
  28.  * Revision 1.9  1995/05/26  19:06:52  brianp
  29.  * replaced GLenum with GLUenum in tesselator error callback function
  30.  *
  31.  * Revision 1.8  1995/05/23  17:37:48  brianp
  32.  * added #ifndef NULL ...
  33.  *
  34.  * Revision 1.7  1995/05/22  16:56:20  brianp
  35.  * Release 1.2
  36.  *
  37.  * Revision 1.6  1995/05/16  19:17:21  brianp
  38.  * minor changes to allow compilation with real OpenGL headers
  39.  *
  40.  * Revision 1.5  1995/04/28  20:07:08  brianp
  41.  * renamed struct GLUtriangulatorObj to struct glu_triangulator_obj
  42.  *
  43.  * Revision 1.4  1995/04/28  16:20:04  brianp
  44.  * initial tess.c contributed by Bogdan Sikorski
  45.  *
  46.  */
  47.  
  48.  
  49. /*
  50.  * This file is part of the polygon tesselation code contributed by
  51.  * Bogdan Sikorski
  52.  */
  53.  
  54.  
  55. #include "tess.h"
  56. #include <math.h>
  57. #include <stdlib.h>
  58.  
  59. #ifndef NULL
  60. #  define NULL 0
  61. #endif
  62.  
  63.  
  64. extern void tess_test_polygon(GLUtriangulatorObj *);
  65. extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
  66. extern void tess_handle_holes(GLUtriangulatorObj *);
  67. extern void tess_tesselate(GLUtriangulatorObj *);
  68. extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
  69. static void delete_contours(GLUtriangulatorObj *);
  70.  
  71. void init_callbacks(tess_callbacks *callbacks)
  72. {
  73.    callbacks->begin = ( void (*)(GLenum) ) 0;
  74.    callbacks->edgeFlag = ( void (*)(GLboolean) ) 0;
  75.    callbacks->vertex = ( void (*)(void*) ) 0;
  76.    callbacks->end = ( void (*)(void) ) 0;
  77.    callbacks->error = ( void (*)(GLUenum) ) 0;
  78. }
  79.  
  80. void tess_call_user_error(GLUtriangulatorObj *tobj,
  81.     GLUenum gluerr)
  82. {
  83.     if(tobj->error==GLU_NO_ERROR)
  84.         tobj->error=gluerr;
  85.     if(tobj->callbacks.error!=NULL)
  86.         (tobj->callbacks.error)(gluerr);
  87. }
  88.  
  89. GLUtriangulatorObj* gluNewTess( void )
  90. {
  91.    GLUtriangulatorObj *tobj;
  92.  
  93.     if((tobj=(GLUtriangulatorObj *)
  94.         malloc(sizeof(struct GLUtriangulatorObj)))==NULL)
  95.         return NULL;
  96.     tobj->contours=tobj->last_contour=NULL;
  97.     init_callbacks(&tobj->callbacks);
  98.     tobj->error=GLU_NO_ERROR;
  99.     tobj->current_polygon=NULL;
  100.     tobj->contour_cnt=0;
  101.     return tobj;
  102. }
  103.  
  104.  
  105. void gluTessCallback( GLUtriangulatorObj *tobj, GLUenum which,
  106.               void (*fn)() )
  107. {
  108.     switch(which)
  109.     {
  110.         case GLU_BEGIN:
  111.             tobj->callbacks.begin = (void (*)(GLenum)) fn;
  112.             break;
  113.         case GLU_EDGE_FLAG:
  114.             tobj->callbacks.edgeFlag = (void (*)(GLboolean)) fn;
  115.             break;
  116.         case GLU_VERTEX:
  117.             tobj->callbacks.vertex = (void (*)(void *)) fn;
  118.             break;
  119.         case GLU_END:
  120.             tobj->callbacks.end=fn = (void (*)(void)) fn;
  121.             break;
  122.         case GLU_ERROR:
  123.             tobj->callbacks.error = (void (*)(GLUenum)) fn;
  124.             break;
  125.         default:
  126.             tobj->error=GLU_INVALID_ENUM;
  127.             break;
  128.     }
  129. }
  130.  
  131.  
  132.  
  133. void gluDeleteTess( GLUtriangulatorObj *tobj )
  134. {
  135.     if(tobj->error==GLU_NO_ERROR && tobj->contour_cnt)
  136.         /* was gluEndPolygon called? */
  137.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  138.     /* delete all internal structures */
  139.     delete_contours(tobj);
  140.     free(tobj);
  141. }
  142.  
  143.  
  144. void gluBeginPolygon( GLUtriangulatorObj *tobj )
  145. {
  146.     if(tobj->error!=GLU_NO_ERROR)
  147.         return;
  148.     if(tobj->current_polygon!=NULL)
  149.     {
  150.         /* gluEndPolygon was not called */
  151.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  152.         /* delete all internal structures */
  153.         delete_contours(tobj);
  154.     }
  155.     else
  156.     {
  157.         if((tobj->current_polygon=
  158.             (tess_polygon *)malloc(sizeof(tess_polygon)))==NULL)
  159.         {
  160.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  161.             return;
  162.         }
  163.         tobj->current_polygon->vertex_cnt=0;
  164.         tobj->current_polygon->vertices=
  165.             tobj->current_polygon->last_vertex=NULL;
  166.     }
  167. }
  168.  
  169.  
  170. void gluEndPolygon( GLUtriangulatorObj *tobj )
  171. {
  172.     tess_contour *contour_ptr;
  173.  
  174.     /* there was an error */
  175.     if(tobj->error!=GLU_NO_ERROR)
  176.         return;
  177.     /* check if gluBeginPolygon was called */
  178.     if(tobj->current_polygon==NULL)
  179.     {
  180.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  181.         return;
  182.     }
  183.     tess_test_polygon(tobj);
  184.     /* there was an error */
  185.     if(tobj->error!=GLU_NO_ERROR)
  186.         return;
  187.     /* any real contours? */
  188.     if(tobj->contour_cnt==0)
  189.     {
  190.         /* delete all internal structures */
  191.         delete_contours(tobj);
  192.         return;
  193.     }
  194.     tess_find_contour_hierarchies(tobj);
  195.     /* there was an error */
  196.     if(tobj->error!=GLU_NO_ERROR)
  197.         return;
  198.     tess_handle_holes(tobj);
  199.     /* there was an error */
  200.     if(tobj->error!=GLU_NO_ERROR)
  201.         return;
  202.     /* if no callbacks, nothing to do */
  203.     if(tobj->callbacks.begin!=NULL && tobj->callbacks.vertex!=NULL &&
  204.         tobj->callbacks.end!=NULL)
  205.     {
  206.         if(tobj->callbacks.edgeFlag==NULL)
  207.             tess_tesselate(tobj);
  208.         else
  209.             tess_tesselate_with_edge_flag(tobj);
  210.     }
  211.     /* delete all internal structures */
  212.     delete_contours(tobj);
  213. }
  214.  
  215.  
  216. void gluNextContour( GLUtriangulatorObj *tobj, GLUenum type )
  217. {
  218.     if(tobj->error!=GLU_NO_ERROR)
  219.         return;
  220.     if(tobj->current_polygon==NULL)
  221.     {
  222.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  223.         return;
  224.     }
  225.     /* first contour? */
  226.     if(tobj->current_polygon->vertex_cnt)
  227.         tess_test_polygon(tobj);
  228. }
  229.  
  230.  
  231. void gluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3], void *data )
  232. {
  233.     tess_polygon *polygon=tobj->current_polygon;
  234.     tess_vertex *last_vertex_ptr;
  235.  
  236.     if(tobj->error!=GLU_NO_ERROR)
  237.         return;
  238.     if(polygon==NULL)
  239.     {
  240.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  241.         return;
  242.     }
  243.     last_vertex_ptr=polygon->last_vertex;
  244.     if(last_vertex_ptr==NULL)
  245.     {
  246.         if((last_vertex_ptr=(tess_vertex *)
  247.             malloc(sizeof(tess_vertex)))==NULL)
  248.         {
  249.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  250.             return;
  251.         }
  252.         polygon->vertices=last_vertex_ptr;
  253.         polygon->last_vertex=last_vertex_ptr;
  254.         last_vertex_ptr->data=data;
  255.         last_vertex_ptr->location[0]=v[0];
  256.         last_vertex_ptr->location[1]=v[1];
  257.         last_vertex_ptr->location[2]=v[2];
  258.         last_vertex_ptr->next=NULL;
  259.         last_vertex_ptr->previous=NULL;
  260.         ++(polygon->vertex_cnt);
  261.     }
  262.     else
  263.     {
  264.         tess_vertex *vertex_ptr;
  265.  
  266.         /* same point twice? */
  267.         if(fabs(last_vertex_ptr->location[0]-v[0]) < EPSILON &&
  268.             fabs(last_vertex_ptr->location[1]-v[1]) < EPSILON &&
  269.             fabs(last_vertex_ptr->location[2]-v[2]) < EPSILON)
  270.         {
  271.             tess_call_user_error(tobj,GLU_TESS_ERROR6);
  272.             return;
  273.         }
  274.         if((vertex_ptr=(tess_vertex *)
  275.             malloc(sizeof(tess_vertex)))==NULL)
  276.         {
  277.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  278.             return;
  279.         }
  280.         vertex_ptr->data=data;
  281.         vertex_ptr->location[0]=v[0];
  282.         vertex_ptr->location[1]=v[1];
  283.         vertex_ptr->location[2]=v[2];
  284.         vertex_ptr->next=NULL;
  285.         vertex_ptr->previous=last_vertex_ptr;
  286.         ++(polygon->vertex_cnt);
  287.         last_vertex_ptr->next=vertex_ptr;
  288.         polygon->last_vertex=vertex_ptr;
  289.     }
  290. }
  291.  
  292.  
  293. static void delete_contours(GLUtriangulatorObj *tobj)
  294. {
  295.     tess_polygon *polygon=tobj->current_polygon;
  296.     tess_contour *contour,*contour_tmp;
  297.     tess_vertex *vertex,*vertex_tmp;
  298.  
  299.     /* remove current_polygon list - if exists due to detected error */
  300.     if(polygon!=NULL)
  301.     {
  302.         for(vertex=polygon->vertices;vertex!=polygon->last_vertex;)
  303.         {
  304.             vertex_tmp=vertex->next;
  305.             free(vertex);
  306.             vertex=vertex_tmp;
  307.         }
  308.         free(polygon);
  309.         tobj->current_polygon=NULL;
  310.     }
  311.     /* remove all contour data */
  312.     for(contour=tobj->contours;contour!=NULL;)
  313.     {
  314.         for(vertex=contour->vertices;vertex!=contour->last_vertex;)
  315.         {
  316.             vertex_tmp=vertex->next;
  317.             free(vertex);
  318.             vertex=vertex_tmp;
  319.         }
  320.         contour_tmp=contour->next;
  321.         free(contour);
  322.         contour=contour_tmp;
  323.     }
  324.     tobj->contours=tobj->last_contour=NULL;
  325.     tobj->contour_cnt=0;
  326. }
  327.  
  328.  
  329.  
  330.