330 lines
8.2 KiB
C
330 lines
8.2 KiB
C
|
/**************************************************************************
|
||
|
* *
|
||
|
* 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 <glos.h>
|
||
|
#include <GL/gl.h>
|
||
|
#include <GL/glu.h>
|
||
|
|
||
|
#ifndef NT
|
||
|
#include <stdlib.h>
|
||
|
#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);
|
||
|
}
|