/************************************************************************** * * * Copyright (C) 1989, Silicon Graphics, Inc. * * * * These coded instructions, statements, and computer programs contain * * unpublished proprietary information of Silicon Graphics, Inc., and * * are protected by Federal copyright law. They may not be disclosed * * to third parties or copied or duplicated in any form, in whole or * * in part, without the prior written consent of Silicon Graphics, Inc. * * * **************************************************************************/ /* interface.c */ /* Derrick Burns - 1989 */ #include #include #include #ifndef NT #include #else #include "winmem.h" #include "bufpool.h" #endif #include "monotone.h" static void do_out_finish(GLUtriangulatorObj *); static void __gluTessEndContour(GLUtriangulatorObj *tobj); GLUtriangulatorObj * APIENTRY gluNewTess(void) { GLUtriangulatorObj *tobj; tobj = (GLUtriangulatorObj *) malloc(sizeof(GLUtriangulatorObj)); tobj->init = 0; tobj->minit = 0; tobj->in_poly = 0; tobj->doingTriangles = 0; tobj->tritype = GL_TRIANGLES; tobj->vpool = 0; tobj->raypool = 0; tobj->begin = NULL; tobj->end = NULL; tobj->vertex = NULL; tobj->error = NULL; tobj->edgeflag = NULL; tobj->parray = (Vert **)NULL; tobj->inBegin = GL_FALSE; tobj->s = 0; tobj->t = 0; return tobj; } void APIENTRY gluTessCallback(GLUtriangulatorObj *tobj, GLenum which, void (CALLBACK *fn)()) { switch(which) { case GLU_BEGIN: #ifndef NT tobj->begin = (void (*)(GLenum)) fn; #else tobj->begin = (GLUtessBeginProc) fn; #endif break; case GLU_VERTEX: #ifndef NT tobj->vertex = (void (*)(void *)) fn; #else tobj->vertex = (GLUtessVertexProc) fn; #endif break; case GLU_END: #ifndef NT tobj->end = (void (*)(void)) fn; #else tobj->end = (GLUtessEndProc) fn; #endif break; case GLU_ERROR: #ifndef NT tobj->error = (void (*)(GLenum)) fn; #else tobj->error = (GLUtessErrorProc) fn; #endif break; case GLU_EDGE_FLAG: #ifndef NT tobj->edgeflag = (void (*)(GLboolean)) fn; #else tobj->edgeflag = (GLUtessEdgeFlagProc) fn; #endif break; default: /* XXX */ break; } } void APIENTRY gluDeleteTess(GLUtriangulatorObj *t) { #ifdef NT extern void __gl_free_pool( Pool * ); #endif __gl_free_priorityq(t); if (t->raypool) __gl_free_pool(t->raypool); if (t->vpool) __gl_free_pool(t->vpool); __gl_clear_triangulate(t); __gl_clear_sort(t); free(t); } /*--------------------------------------------------------------------------- * gluBeginPolygon - called before each input polygon *--------------------------------------------------------------------------- */ void APIENTRY gluBeginPolygon(GLUtriangulatorObj *tobj) { if(setjmp(tobj->in_env) != 0) return; if (tobj->in_poly++) { __gl_in_error(tobj, 1); } /* 17 arbitrarily */ __gl_init_priorityq(tobj, 17); __gl_init_verts(tobj); __gl_init_raylist(tobj); tobj->nloops = 0; tobj->maxarea = (float)0.0; tobj->head = 0; tobj->looptype = GLU_EXTERIOR; } /*--------------------------------------------------------------------------- * gluEndPolygon - called after each input polygon *--------------------------------------------------------------------------- */ void APIENTRY gluEndPolygon(GLUtriangulatorObj *tobj) { #ifdef NT extern void __gl_setpriority_priorityq( GLUtriangulatorObj *, int, int); #endif if(setjmp(tobj->in_env) != 0) return; if (--tobj->in_poly) { __gl_in_error(tobj, 2); } if (tobj->head) { __gluTessEndContour(tobj); } /* Set edge flag to -1 so that if the user wants edge flag info, we ** specify an edge flag for the first edge regardless (then we only ** report changes). */ tobj->currentEdgeFlag = (GLboolean) -1; __gl_setpriority_priorityq(tobj, tobj->s, tobj->t); __gl_monotonize(tobj); do_out_finish(tobj); __gl_free_verts(tobj); __gl_free_priorityq(tobj); __gl_free_raylist(tobj); } static void do_out_finish(GLUtriangulatorObj *tobj) { if (tobj->doingTriangles) { if (tobj->end) { (*tobj->end)(); tobj->inBegin = GL_FALSE; } tobj->doingTriangles = 0; } } /*--------------------------------------------------------------------------- * gluNextContour - called before each input boundary loop *--------------------------------------------------------------------------- */ void APIENTRY gluNextContour(GLUtriangulatorObj *tobj, GLenum type) { if(setjmp(tobj->in_env) != 0) return; if(!tobj->in_poly) { __gl_in_error(tobj, 2); } if (tobj->head) { __gluTessEndContour(tobj); } tobj->head = 0; tobj->looptype = type; } /*--------------------------------------------------------------------------- * gluTessEndContour - called after each input boundary loop *--------------------------------------------------------------------------- */ static void __gluTessEndContour(GLUtriangulatorObj *tobj) { double xyarea, xzarea, yzarea; Vert *v; tobj->nloops++; xyarea = xzarea = yzarea = 0.0; v = tobj->head; do { xyarea += v->v[0] * v->next->v[1] - v->v[1] * v->next->v[0]; xzarea += v->v[0] * v->next->v[2] - v->v[2] * v->next->v[0]; yzarea += v->v[1] * v->next->v[2] - v->v[2] * v->next->v[1]; v = v->next; } while(v != tobj->head); if(xyarea < 0.0) { if(-xyarea > tobj->maxarea) { tobj->maxarea = -xyarea; tobj->s = 1; tobj->t = 0; } } else { if(xyarea > tobj->maxarea) { tobj->maxarea = xyarea; tobj->s = 0; tobj->t = 1; } } if(xzarea < 0.0) { if(-xzarea > tobj->maxarea) { tobj->maxarea = -xzarea; tobj->s = 2; tobj->t = 0; } } else { if(xzarea > tobj->maxarea) { tobj->maxarea = xzarea; tobj->s = 0; tobj->t = 2; } } if(yzarea < 0.0) { if(-yzarea > tobj->maxarea) { tobj->maxarea = -yzarea; tobj->s = 2; tobj->t = 1; } } else { if(yzarea > tobj->maxarea) { tobj->maxarea = yzarea; tobj->s = 1; tobj->t = 2; } } __gl_unclassify_all(tobj->head); } /*--------------------------------------------------------------------------- * gluTessVertex - called for each input vertex *--------------------------------------------------------------------------- */ void APIENTRY gluTessVertex(GLUtriangulatorObj *tobj, GLdouble v[3], void *data) { Vert *vert; if(setjmp(tobj->in_env) != 0) return; if(!tobj->in_poly) { __gl_in_error(tobj, 2); } vert = __gl_new_vert(tobj); vert->myid = vert; vert->v[0] = v[0]; vert->v[1] = v[1]; vert->v[2] = v[2]; vert->ray = 0; vert->data = data; #ifdef ADDED vert->added = 0; #endif if(tobj->head == 0) { tobj->head = vert->prev = vert->next = vert; } else { vert->prev = tobj->head->prev; vert->next = tobj->head; vert->prev->next = vert; vert->next->prev = vert; } __gl_add_priorityq(tobj, vert); } /*---------------------------------------------------------------------------- * in_error - data input error, free all storage *---------------------------------------------------------------------------- */ void __gl_in_error(GLUtriangulatorObj *tobj, GLenum which) { __gl_clear_sort(tobj); __gl_clear_triangulate(tobj); __gl_free_raylist(tobj); __gl_free_verts(tobj); __gl_free_priorityq(tobj); __gl_cleanup(tobj); tobj->in_poly = 0; if (tobj->error) { (*tobj->error)(which + (GLU_TESS_ERROR1 - 1)); } longjmp(tobj->in_env, (int) which); }