home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src-glu / tess.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  8KB  |  336 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.12 1995/09/19 13:43:51 brianp Exp $
  26.  
  27. $Log: tess.c,v $
  28.  * Revision 1.12  1995/09/19  13:43:51  brianp
  29.  * removed #include "gluP.h" per Bogdan Sikorski
  30.  *
  31.  * Revision 1.11  1995/08/04  13:09:59  brianp
  32.  * include gluP.h to define NULL, just in case
  33.  *
  34.  * Revision 1.10  1995/07/28  21:35:49  brianp
  35.  * changed all GLUenum to GLenum
  36.  *
  37.  * Revision 1.9  1995/05/26  19:06:52  brianp
  38.  * replaced GLenum with GLUenum in tesselator error callback function
  39.  *
  40.  * Revision 1.8  1995/05/23  17:37:48  brianp
  41.  * added #ifndef NULL ...
  42.  *
  43.  * Revision 1.7  1995/05/22  16:56:20  brianp
  44.  * Release 1.2
  45.  *
  46.  * Revision 1.6  1995/05/16  19:17:21  brianp
  47.  * minor changes to allow compilation with real OpenGL headers
  48.  *
  49.  * Revision 1.5  1995/04/28  20:07:08  brianp
  50.  * renamed struct GLUtriangulatorObj to struct glu_triangulator_obj
  51.  *
  52.  * Revision 1.4  1995/04/28  16:20:04  brianp
  53.  * initial tess.c contributed by Bogdan Sikorski
  54.  *
  55.  */
  56.  
  57.  
  58. /*
  59.  * This file is part of the polygon tesselation code contributed by
  60.  * Bogdan Sikorski
  61.  */
  62.  
  63.  
  64. #include <math.h>
  65. #include <stdlib.h>
  66. #include "tess.h"
  67.  
  68.  
  69.  
  70. extern void tess_test_polygon(GLUtriangulatorObj *);
  71. extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
  72. extern void tess_handle_holes(GLUtriangulatorObj *);
  73. extern void tess_tesselate(GLUtriangulatorObj *);
  74. extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
  75. static void delete_contours(GLUtriangulatorObj *);
  76.  
  77. void init_callbacks(tess_callbacks *callbacks)
  78. {
  79.    callbacks->begin = ( void (*)(GLenum) ) 0;
  80.    callbacks->edgeFlag = ( void (*)(GLboolean) ) 0;
  81.    callbacks->vertex = ( void (*)(void*) ) 0;
  82.    callbacks->end = ( void (*)(void) ) 0;
  83.    callbacks->error = ( void (*)(GLenum) ) 0;
  84. }
  85.  
  86. void tess_call_user_error(GLUtriangulatorObj *tobj,
  87.     GLenum gluerr)
  88. {
  89.     if(tobj->error==GLU_NO_ERROR)
  90.         tobj->error=gluerr;
  91.     if(tobj->callbacks.error!=NULL)
  92.         (tobj->callbacks.error)(gluerr);
  93. }
  94.  
  95. GLUtriangulatorObj* gluNewTess( void )
  96. {
  97.    GLUtriangulatorObj *tobj;
  98.  
  99.     if((tobj=(GLUtriangulatorObj *)
  100.         malloc(sizeof(struct GLUtriangulatorObj)))==NULL)
  101.         return NULL;
  102.     tobj->contours=tobj->last_contour=NULL;
  103.     init_callbacks(&tobj->callbacks);
  104.     tobj->error=GLU_NO_ERROR;
  105.     tobj->current_polygon=NULL;
  106.     tobj->contour_cnt=0;
  107.     return tobj;
  108. }
  109.  
  110.  
  111. void gluTessCallback( GLUtriangulatorObj *tobj, GLenum which,
  112.               void (*fn)() )
  113. {
  114.     switch(which)
  115.     {
  116.         case GLU_BEGIN:
  117.             tobj->callbacks.begin = (void (*)(GLenum)) fn;
  118.             break;
  119.         case GLU_EDGE_FLAG:
  120.             tobj->callbacks.edgeFlag = (void (*)(GLboolean)) fn;
  121.             break;
  122.         case GLU_VERTEX:
  123.             tobj->callbacks.vertex = (void (*)(void *)) fn;
  124.             break;
  125.         case GLU_END:
  126.             tobj->callbacks.end=fn = (void (*)(void)) fn;
  127.             break;
  128.         case GLU_ERROR:
  129.             tobj->callbacks.error = (void (*)(GLenum)) fn;
  130.             break;
  131.         default:
  132.             tobj->error=GLU_INVALID_ENUM;
  133.             break;
  134.     }
  135. }
  136.  
  137.  
  138.  
  139. void gluDeleteTess( GLUtriangulatorObj *tobj )
  140. {
  141.     if(tobj->error==GLU_NO_ERROR && tobj->contour_cnt)
  142.         /* was gluEndPolygon called? */
  143.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  144.     /* delete all internal structures */
  145.     delete_contours(tobj);
  146.     free(tobj);
  147. }
  148.  
  149.  
  150. void gluBeginPolygon( GLUtriangulatorObj *tobj )
  151. {
  152.     if(tobj->error!=GLU_NO_ERROR)
  153.         return;
  154.     if(tobj->current_polygon!=NULL)
  155.     {
  156.         /* gluEndPolygon was not called */
  157.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  158.         /* delete all internal structures */
  159.         delete_contours(tobj);
  160.     }
  161.     else
  162.     {
  163.         if((tobj->current_polygon=
  164.             (tess_polygon *)malloc(sizeof(tess_polygon)))==NULL)
  165.         {
  166.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  167.             return;
  168.         }
  169.         tobj->current_polygon->vertex_cnt=0;
  170.         tobj->current_polygon->vertices=
  171.             tobj->current_polygon->last_vertex=NULL;
  172.     }
  173. }
  174.  
  175.  
  176. void gluEndPolygon( GLUtriangulatorObj *tobj )
  177. {
  178.     tess_contour *contour_ptr;
  179.  
  180.     /* there was an error */
  181.     if(tobj->error!=GLU_NO_ERROR)
  182.         return;
  183.     /* check if gluBeginPolygon was called */
  184.     if(tobj->current_polygon==NULL)
  185.     {
  186.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  187.         return;
  188.     }
  189.     tess_test_polygon(tobj);
  190.     /* there was an error */
  191.     if(tobj->error!=GLU_NO_ERROR)
  192.         return;
  193.     /* any real contours? */
  194.     if(tobj->contour_cnt==0)
  195.     {
  196.         /* delete all internal structures */
  197.         delete_contours(tobj);
  198.         return;
  199.     }
  200.     tess_find_contour_hierarchies(tobj);
  201.     /* there was an error */
  202.     if(tobj->error!=GLU_NO_ERROR)
  203.         return;
  204.     tess_handle_holes(tobj);
  205.     /* there was an error */
  206.     if(tobj->error!=GLU_NO_ERROR)
  207.         return;
  208.     /* if no callbacks, nothing to do */
  209.     if(tobj->callbacks.begin!=NULL && tobj->callbacks.vertex!=NULL &&
  210.         tobj->callbacks.end!=NULL)
  211.     {
  212.         if(tobj->callbacks.edgeFlag==NULL)
  213.             tess_tesselate(tobj);
  214.         else
  215.             tess_tesselate_with_edge_flag(tobj);
  216.     }
  217.     /* delete all internal structures */
  218.     delete_contours(tobj);
  219. }
  220.  
  221.  
  222. void gluNextContour( GLUtriangulatorObj *tobj, GLenum type )
  223. {
  224.     if(tobj->error!=GLU_NO_ERROR)
  225.         return;
  226.     if(tobj->current_polygon==NULL)
  227.     {
  228.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  229.         return;
  230.     }
  231.     /* first contour? */
  232.     if(tobj->current_polygon->vertex_cnt)
  233.         tess_test_polygon(tobj);
  234. }
  235.  
  236.  
  237. void gluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3], void *data )
  238. {
  239.     tess_polygon *polygon=tobj->current_polygon;
  240.     tess_vertex *last_vertex_ptr;
  241.  
  242.     if(tobj->error!=GLU_NO_ERROR)
  243.         return;
  244.     if(polygon==NULL)
  245.     {
  246.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  247.         return;
  248.     }
  249.     last_vertex_ptr=polygon->last_vertex;
  250.     if(last_vertex_ptr==NULL)
  251.     {
  252.         if((last_vertex_ptr=(tess_vertex *)
  253.             malloc(sizeof(tess_vertex)))==NULL)
  254.         {
  255.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  256.             return;
  257.         }
  258.         polygon->vertices=last_vertex_ptr;
  259.         polygon->last_vertex=last_vertex_ptr;
  260.         last_vertex_ptr->data=data;
  261.         last_vertex_ptr->location[0]=v[0];
  262.         last_vertex_ptr->location[1]=v[1];
  263.         last_vertex_ptr->location[2]=v[2];
  264.         last_vertex_ptr->next=NULL;
  265.         last_vertex_ptr->previous=NULL;
  266.         ++(polygon->vertex_cnt);
  267.     }
  268.     else
  269.     {
  270.         tess_vertex *vertex_ptr;
  271.  
  272.         /* same point twice? */
  273.         if(fabs(last_vertex_ptr->location[0]-v[0]) < EPSILON &&
  274.             fabs(last_vertex_ptr->location[1]-v[1]) < EPSILON &&
  275.             fabs(last_vertex_ptr->location[2]-v[2]) < EPSILON)
  276.         {
  277.             tess_call_user_error(tobj,GLU_TESS_ERROR6);
  278.             return;
  279.         }
  280.         if((vertex_ptr=(tess_vertex *)
  281.             malloc(sizeof(tess_vertex)))==NULL)
  282.         {
  283.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  284.             return;
  285.         }
  286.         vertex_ptr->data=data;
  287.         vertex_ptr->location[0]=v[0];
  288.         vertex_ptr->location[1]=v[1];
  289.         vertex_ptr->location[2]=v[2];
  290.         vertex_ptr->next=NULL;
  291.         vertex_ptr->previous=last_vertex_ptr;
  292.         ++(polygon->vertex_cnt);
  293.         last_vertex_ptr->next=vertex_ptr;
  294.         polygon->last_vertex=vertex_ptr;
  295.     }
  296. }
  297.  
  298.  
  299. static void delete_contours(GLUtriangulatorObj *tobj)
  300. {
  301.     tess_polygon *polygon=tobj->current_polygon;
  302.     tess_contour *contour,*contour_tmp;
  303.     tess_vertex *vertex,*vertex_tmp;
  304.  
  305.     /* remove current_polygon list - if exists due to detected error */
  306.     if(polygon!=NULL)
  307.     {
  308.         for(vertex=polygon->vertices;vertex!=polygon->last_vertex;)
  309.         {
  310.             vertex_tmp=vertex->next;
  311.             free(vertex);
  312.             vertex=vertex_tmp;
  313.         }
  314.         free(polygon);
  315.         tobj->current_polygon=NULL;
  316.     }
  317.     /* remove all contour data */
  318.     for(contour=tobj->contours;contour!=NULL;)
  319.     {
  320.         for(vertex=contour->vertices;vertex!=contour->last_vertex;)
  321.         {
  322.             vertex_tmp=vertex->next;
  323.             free(vertex);
  324.             vertex=vertex_tmp;
  325.         }
  326.         contour_tmp=contour->next;
  327.         free(contour);
  328.         contour=contour_tmp;
  329.     }
  330.     tobj->contours=tobj->last_contour=NULL;
  331.     tobj->contour_cnt=0;
  332. }
  333.  
  334.  
  335.  
  336.