File indexing completed on 2024-04-14 14:11:11

0001 /*
0002 ** Author: Eric Veach, July 1994.
0003 **
0004 */
0005 
0006 #ifndef __tess_h_
0007 #define __tess_h_
0008 
0009 #include "glu.h"
0010 #include <setjmp.h>
0011 #include "mesh.h"
0012 #include "dict.h"
0013 #include "priorityq.h"
0014 
0015 /* The begin/end calls must be properly nested.  We keep track of
0016  * the current state to enforce the ordering.
0017  */
0018 enum TessState
0019 {
0020     T_DORMANT,
0021     T_IN_POLYGON,
0022     T_IN_CONTOUR
0023 };
0024 
0025 /* We cache vertex data for single-contour polygons so that we can
0026  * try a quick-and-dirty decomposition first.
0027  */
0028 #define TESS_MAX_CACHE 100
0029 
0030 typedef struct CachedVertex
0031 {
0032     GLdouble coords[3];
0033     void *data;
0034 } CachedVertex;
0035 
0036 struct GLUtesselator
0037 {
0038     /*** state needed for collecting the input data ***/
0039 
0040     enum TessState state; /* what begin/end calls have we seen? */
0041 
0042     GLUhalfEdge *lastEdge; /* lastEdge->Org is the most recent vertex */
0043     GLUmesh *mesh;         /* stores the input contours, and eventually
0044                                    the tessellation itself */
0045 
0046     void(GLAPIENTRY *callError)(GLenum errnum);
0047 
0048     /*** state needed for projecting onto the sweep plane ***/
0049 
0050     GLdouble normal[3]; /* user-specified normal (if provided) */
0051     GLdouble sUnit[3];  /* unit vector in s-direction (debugging) */
0052     GLdouble tUnit[3];  /* unit vector in t-direction (debugging) */
0053 
0054     /*** state needed for the line sweep ***/
0055 
0056     GLdouble relTolerance; /* tolerance for merging features */
0057     GLenum windingRule;    /* rule for determining polygon interior */
0058     GLboolean fatalError;  /* fatal error: needed combine callback */
0059 
0060     Dict *dict;       /* edge dictionary for sweep line */
0061     PriorityQ *pq;    /* priority queue of vertex events */
0062     GLUvertex *event; /* current sweep event being processed */
0063 
0064     void(GLAPIENTRY *callCombine)(GLdouble coords[3], void *data[4], GLfloat weight[4], void **outData);
0065 
0066     /*** state needed for rendering callbacks (see render.c) ***/
0067 
0068     GLboolean flagBoundary; /* mark boundary edges (use EdgeFlag) */
0069     GLboolean boundaryOnly; /* Extract contours, not triangles */
0070     GLUface *lonelyTriList;
0071     /* list of triangles which could not be rendered as strips or fans */
0072 
0073     void(GLAPIENTRY *callBegin)(GLenum type);
0074     void(GLAPIENTRY *callEdgeFlag)(GLboolean boundaryEdge);
0075     void(GLAPIENTRY *callVertex)(void *data);
0076     void(GLAPIENTRY *callEnd)(void);
0077     void(GLAPIENTRY *callMesh)(GLUmesh *mesh);
0078 
0079     /*** state needed to cache single-contour polygons for renderCache() */
0080 
0081     GLboolean emptyCache;               /* empty cache on next vertex() call */
0082     int cacheCount;                     /* number of cached vertices */
0083     CachedVertex cache[TESS_MAX_CACHE]; /* the vertex data */
0084 
0085     /*** rendering callbacks that also pass polygon data  ***/
0086     void(GLAPIENTRY *callBeginData)(GLenum type, void *polygonData);
0087     void(GLAPIENTRY *callEdgeFlagData)(GLboolean boundaryEdge, void *polygonData);
0088     void(GLAPIENTRY *callVertexData)(void *data, void *polygonData);
0089     void(GLAPIENTRY *callEndData)(void *polygonData);
0090     void(GLAPIENTRY *callErrorData)(GLenum errnum, void *polygonData);
0091     void(GLAPIENTRY *callCombineData)(GLdouble coords[3], void *data[4], GLfloat weight[4], void **outData,
0092                                       void *polygonData);
0093 
0094     jmp_buf env; /* place to jump to when memAllocs fail */
0095 
0096     void *polygonData; /* client data for current polygon */
0097 };
0098 
0099 void GLAPIENTRY __gl_noBeginData(GLenum type, void *polygonData);
0100 void GLAPIENTRY __gl_noEdgeFlagData(GLboolean boundaryEdge, void *polygonData);
0101 void GLAPIENTRY __gl_noVertexData(void *data, void *polygonData);
0102 void GLAPIENTRY __gl_noEndData(void *polygonData);
0103 void GLAPIENTRY __gl_noErrorData(GLenum errnum, void *polygonData);
0104 void GLAPIENTRY __gl_noCombineData(GLdouble coords[3], void *data[4], GLfloat weight[4], void **outData,
0105                                    void *polygonData);
0106 
0107 #define CALL_BEGIN_OR_BEGIN_DATA(a)                     \
0108     if (tess->callBeginData != &__gl_noBeginData)       \
0109         (*tess->callBeginData)((a), tess->polygonData); \
0110     else                                                \
0111         (*tess->callBegin)((a));
0112 
0113 #define CALL_VERTEX_OR_VERTEX_DATA(a)                    \
0114     if (tess->callVertexData != &__gl_noVertexData)      \
0115         (*tess->callVertexData)((a), tess->polygonData); \
0116     else                                                 \
0117         (*tess->callVertex)((a));
0118 
0119 #define CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(a)                \
0120     if (tess->callEdgeFlagData != &__gl_noEdgeFlagData)    \
0121         (*tess->callEdgeFlagData)((a), tess->polygonData); \
0122     else                                                   \
0123         (*tess->callEdgeFlag)((a));
0124 
0125 #define CALL_END_OR_END_DATA()                   \
0126     if (tess->callEndData != &__gl_noEndData)    \
0127         (*tess->callEndData)(tess->polygonData); \
0128     else                                         \
0129         (*tess->callEnd)();
0130 
0131 #define CALL_COMBINE_OR_COMBINE_DATA(a, b, c, d)                         \
0132     if (tess->callCombineData != &__gl_noCombineData)                    \
0133         (*tess->callCombineData)((a), (b), (c), (d), tess->polygonData); \
0134     else                                                                 \
0135         (*tess->callCombine)((a), (b), (c), (d));
0136 
0137 #define CALL_ERROR_OR_ERROR_DATA(a)                     \
0138     if (tess->callErrorData != &__gl_noErrorData)       \
0139         (*tess->callErrorData)((a), tess->polygonData); \
0140     else                                                \
0141         (*tess->callError)((a));
0142 
0143 #endif