home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src-glu / tess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  10.5 KB  |  343 lines

  1. /* $Id: tess.c,v 1.6 1997/09/17 01:51:48 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1997  Brian Paul
  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.  * $Log: tess.c,v $
  26.  * Revision 1.6  1997/09/17 01:51:48  brianp
  27.  * changed glu*Callback() functions to match prototype in glu.h
  28.  *
  29.  * Revision 1.5  1997/07/24 01:28:44  brianp
  30.  * changed precompiled header symbol from PCH to PC_HEADER
  31.  *
  32.  * Revision 1.4  1997/05/28 02:29:38  brianp
  33.  * added support for precompiled headers (PCH), inserted APIENTRY keyword
  34.  *
  35.  * Revision 1.3  1996/11/12 01:23:02  brianp
  36.  * added test to prevent free(vertex) when vertex==NULL in delete_contours()
  37.  *
  38.  * Revision 1.2  1996/10/22 22:57:19  brianp
  39.  * better error handling in gluBegin/EndPolygon() from Erich Eder
  40.  *
  41.  * Revision 1.1  1996/09/27 01:19:39  brianp
  42.  * Initial revision
  43.  *
  44.  */
  45.  
  46.  
  47. /*
  48.  * This file is part of the polygon tesselation code contributed by
  49.  * Bogdan Sikorski
  50.  */
  51.  
  52.  
  53. #ifdef PC_HEADER
  54. #include "all.h"
  55. #else
  56. #include <math.h>
  57. #include <stdlib.h>
  58. #include "tess.h"
  59. #endif
  60.  
  61.  
  62.  
  63. extern void tess_test_polygon(GLUtriangulatorObj *);
  64. extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
  65. extern void tess_handle_holes(GLUtriangulatorObj *);
  66. extern void tess_tesselate(GLUtriangulatorObj *);
  67. extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
  68. static void delete_contours(GLUtriangulatorObj *);
  69.  
  70. void init_callbacks(tess_callbacks *callbacks)
  71. {
  72.    callbacks->begin = ( void (*)(GLenum) ) 0;
  73.    callbacks->edgeFlag = ( void (*)(GLboolean) ) 0;
  74.    callbacks->vertex = ( void (*)(void*) ) 0;
  75.    callbacks->end = ( void (*)(void) ) 0;
  76.    callbacks->error = ( void (*)(GLenum) ) 0;
  77. }
  78.  
  79. void tess_call_user_error(GLUtriangulatorObj *tobj,
  80.         GLenum gluerr)
  81. {
  82.         if(tobj->error==GLU_NO_ERROR)
  83.                 tobj->error=gluerr;
  84.         if(tobj->callbacks.error!=NULL)
  85.                 (tobj->callbacks.error)(gluerr);
  86. }
  87.  
  88. GLUtriangulatorObj* APIENTRY gluNewTess( void )
  89. {
  90.    GLUtriangulatorObj *tobj;
  91.  
  92.         if((tobj=(GLUtriangulatorObj *)
  93.                 malloc(sizeof(struct GLUtriangulatorObj)))==NULL)
  94.                 return NULL;
  95.         tobj->contours=tobj->last_contour=NULL;
  96.         init_callbacks(&tobj->callbacks);
  97.         tobj->error=GLU_NO_ERROR;
  98.         tobj->current_polygon=NULL;
  99.         tobj->contour_cnt=0;
  100.         return tobj;
  101. }
  102.  
  103.  
  104. void APIENTRY gluTessCallback( GLUtriangulatorObj *tobj, GLenum which,
  105.                                void (CALLBACK *fn)() )
  106. {
  107.         switch(which)
  108.         {
  109.                 case GLU_BEGIN:
  110.                         tobj->callbacks.begin = (void (*)(GLenum)) fn;
  111.                         break;
  112.                 case GLU_EDGE_FLAG:
  113.                         tobj->callbacks.edgeFlag = (void (*)(GLboolean)) fn;
  114.                         break;
  115.                 case GLU_VERTEX:
  116.                         tobj->callbacks.vertex = (void (*)(void *)) fn;
  117.                         break;
  118.                 case GLU_END:
  119. #ifndef __STORM__
  120.                         tobj->callbacks.end=fn = (void (*)(void)) fn;
  121. #else
  122.                         tobj->callbacks.end= (void (*)(void)) fn;
  123. #endif
  124.                         break;
  125.                 case GLU_ERROR:
  126.                         tobj->callbacks.error = (void (*)(GLenum)) fn;
  127.                         break;
  128.                 default:
  129.                         tobj->error=GLU_INVALID_ENUM;
  130.                         break;
  131.         }
  132. }
  133.  
  134.  
  135.  
  136. void APIENTRY gluDeleteTess( GLUtriangulatorObj *tobj )
  137. {
  138.         if(tobj->error==GLU_NO_ERROR && tobj->contour_cnt)
  139.                 /* was gluEndPolygon called? */
  140.                 tess_call_user_error(tobj,GLU_TESS_ERROR1);
  141.         /* delete all internal structures */
  142.         delete_contours(tobj);
  143.         free(tobj);
  144. }
  145.  
  146.  
  147. void APIENTRY gluBeginPolygon( GLUtriangulatorObj *tobj )
  148. {
  149. /*
  150.         if(tobj->error!=GLU_NO_ERROR)
  151.                 return;
  152. */
  153.         tobj->error = GLU_NO_ERROR;
  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 APIENTRY gluEndPolygon( GLUtriangulatorObj *tobj )
  177. {
  178.         /*tess_contour *contour_ptr;*/
  179.  
  180.         /* there was an error */
  181.         if(tobj->error!=GLU_NO_ERROR) goto end;
  182.  
  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) goto end;
  192.  
  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) goto end;
  203.  
  204.         tess_handle_holes(tobj);
  205.         /* there was an error */
  206.         if(tobj->error!=GLU_NO_ERROR) goto end;
  207.  
  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.  
  218. end:
  219.         /* delete all internal structures */
  220.         delete_contours(tobj);
  221. }
  222.  
  223.  
  224. void APIENTRY gluNextContour( GLUtriangulatorObj *tobj, GLenum type )
  225. {
  226.         if(tobj->error!=GLU_NO_ERROR)
  227.                 return;
  228.         if(tobj->current_polygon==NULL)
  229.         {
  230.                 tess_call_user_error(tobj,GLU_TESS_ERROR2);
  231.                 return;
  232.         }
  233.         /* first contour? */
  234.         if(tobj->current_polygon->vertex_cnt)
  235.                 tess_test_polygon(tobj);
  236. }
  237.  
  238.  
  239. void APIENTRY gluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3], void *data )
  240. {
  241.         tess_polygon *polygon=tobj->current_polygon;
  242.         tess_vertex *last_vertex_ptr;
  243.  
  244.         if(tobj->error!=GLU_NO_ERROR)
  245.                 return;
  246.         if(polygon==NULL)
  247.         {
  248.                 tess_call_user_error(tobj,GLU_TESS_ERROR2);
  249.                 return;
  250.         }
  251.         last_vertex_ptr=polygon->last_vertex;
  252.         if(last_vertex_ptr==NULL)
  253.         {
  254.                 if((last_vertex_ptr=(tess_vertex *)
  255.                         malloc(sizeof(tess_vertex)))==NULL)
  256.                 {
  257.                         tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  258.                         return;
  259.                 }
  260.                 polygon->vertices=last_vertex_ptr;
  261.                 polygon->last_vertex=last_vertex_ptr;
  262.                 last_vertex_ptr->data=data;
  263.                 last_vertex_ptr->location[0]=v[0];
  264.                 last_vertex_ptr->location[1]=v[1];
  265.                 last_vertex_ptr->location[2]=v[2];
  266.                 last_vertex_ptr->next=NULL;
  267.                 last_vertex_ptr->previous=NULL;
  268.                 ++(polygon->vertex_cnt);
  269.         }
  270.         else
  271.         {
  272.                 tess_vertex *vertex_ptr;
  273.  
  274.                 /* same point twice? */
  275.                 if(fabs(last_vertex_ptr->location[0]-v[0]) < EPSILON &&
  276.                         fabs(last_vertex_ptr->location[1]-v[1]) < EPSILON &&
  277.                         fabs(last_vertex_ptr->location[2]-v[2]) < EPSILON)
  278.                 {
  279.                         tess_call_user_error(tobj,GLU_TESS_ERROR6);
  280.                         return;
  281.                 }
  282.                 if((vertex_ptr=(tess_vertex *)
  283.                         malloc(sizeof(tess_vertex)))==NULL)
  284.                 {
  285.                         tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  286.                         return;
  287.                 }
  288.                 vertex_ptr->data=data;
  289.                 vertex_ptr->location[0]=v[0];
  290.                 vertex_ptr->location[1]=v[1];
  291.                 vertex_ptr->location[2]=v[2];
  292.                 vertex_ptr->next=NULL;
  293.                 vertex_ptr->previous=last_vertex_ptr;
  294.                 ++(polygon->vertex_cnt);
  295.                 last_vertex_ptr->next=vertex_ptr;
  296.                 polygon->last_vertex=vertex_ptr;
  297.         }
  298. }
  299.  
  300.  
  301. static void delete_contours(GLUtriangulatorObj *tobj)
  302. {
  303.         tess_polygon *polygon=tobj->current_polygon;
  304.         tess_contour *contour,*contour_tmp;
  305.         tess_vertex *vertex,*vertex_tmp;
  306.  
  307.         /* remove current_polygon list - if exists due to detected error */
  308.         if(polygon!=NULL)
  309.         {
  310.                 if (polygon->vertices)
  311.                 {
  312.                         for(vertex=polygon->vertices;vertex!=polygon->last_vertex;)
  313.                         {
  314.                                 vertex_tmp=vertex->next;
  315.                                 free(vertex);
  316.                                 vertex=vertex_tmp;
  317.                         }
  318.                         free(vertex);
  319.                 }
  320.                 free(polygon);
  321.                 tobj->current_polygon=NULL;
  322.         }
  323.         /* remove all contour data */
  324.         for(contour=tobj->contours;contour!=NULL;)
  325.         {
  326.                 for(vertex=contour->vertices;vertex!=contour->last_vertex;)
  327.                 {
  328.                         vertex_tmp=vertex->next;
  329.                         free(vertex);
  330.                         vertex=vertex_tmp;
  331.                 }
  332.                 free(vertex);
  333.                 contour_tmp=contour->next;
  334.                 free(contour);
  335.                 contour=contour_tmp;
  336.         }
  337.         tobj->contours=tobj->last_contour=NULL;
  338.         tobj->contour_cnt=0;
  339. }
  340.  
  341.  
  342.  
  343.