Warning, file /education/kstars/kstars/libtess/src/tessellate.c was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 #include "glu.h" 0002 #include "tess.h" 0003 #include <stdio.h> 0004 #include <stdlib.h> 0005 0006 /******************************************************************************/ 0007 0008 typedef struct Triangle 0009 { 0010 int v[3]; 0011 struct Triangle *prev; 0012 } Triangle; 0013 0014 typedef struct Vertex 0015 { 0016 double pt[3]; 0017 int index; 0018 struct Vertex *prev; 0019 } Vertex; 0020 0021 typedef struct TessContext 0022 { 0023 Triangle *latest_t; 0024 int n_tris; 0025 0026 Vertex *v_prev; 0027 Vertex *v_prevprev; 0028 Vertex *latest_v; 0029 GLenum current_mode; 0030 int odd_even_strip; 0031 0032 void (*vertex_cb)(Vertex *, struct TessContext *); 0033 } TessContext; 0034 0035 void skip_vertex(Vertex *v, TessContext *ctx); 0036 0037 /******************************************************************************/ 0038 0039 TessContext *new_tess_context() 0040 { 0041 TessContext *result = (TessContext *)malloc(sizeof(struct TessContext)); 0042 result->latest_t = NULL; 0043 result->latest_v = NULL; 0044 result->n_tris = 0; 0045 result->v_prev = NULL; 0046 result->v_prevprev = NULL; 0047 result->v_prev = NULL; 0048 result->v_prev = NULL; 0049 result->vertex_cb = &skip_vertex; 0050 result->odd_even_strip = 0; 0051 return result; 0052 } 0053 0054 void destroy_tess_context(TessContext *ctx) 0055 { 0056 free(ctx); 0057 } 0058 0059 Vertex *new_vertex(TessContext *ctx, double x, double y) 0060 { 0061 Vertex *result = (Vertex *)malloc(sizeof(Vertex)); 0062 result->prev = ctx->latest_v; 0063 result->pt[0] = x; 0064 result->pt[1] = y; 0065 result->pt[2] = 0; 0066 0067 if (ctx->latest_v == NULL) 0068 { 0069 result->index = 0; 0070 } 0071 else 0072 { 0073 result->index = ctx->latest_v->index + 1; 0074 } 0075 return ctx->latest_v = result; 0076 } 0077 0078 Triangle *new_triangle(TessContext *ctx, int v1, int v2, int v3) 0079 { 0080 Triangle *result = (Triangle *)malloc(sizeof(Triangle)); 0081 result->prev = ctx->latest_t; 0082 result->v[0] = v1; 0083 result->v[1] = v2; 0084 result->v[2] = v3; 0085 ctx->n_tris++; 0086 return ctx->latest_t = result; 0087 } 0088 0089 /******************************************************************************/ 0090 0091 void skip_vertex(Vertex *v, TessContext *ctx){}; 0092 0093 void fan_vertex(Vertex *v, TessContext *ctx) 0094 { 0095 if (ctx->v_prevprev == NULL) 0096 { 0097 ctx->v_prevprev = v; 0098 return; 0099 } 0100 if (ctx->v_prev == NULL) 0101 { 0102 ctx->v_prev = v; 0103 return; 0104 } 0105 new_triangle(ctx, ctx->v_prevprev->index, ctx->v_prev->index, v->index); 0106 ctx->v_prev = v; 0107 } 0108 0109 void strip_vertex(Vertex *v, TessContext *ctx) 0110 { 0111 if (ctx->v_prev == NULL) 0112 { 0113 ctx->v_prev = v; 0114 return; 0115 } 0116 if (ctx->v_prevprev == NULL) 0117 { 0118 ctx->v_prevprev = v; 0119 return; 0120 } 0121 if (ctx->odd_even_strip) 0122 { 0123 new_triangle(ctx, ctx->v_prevprev->index, ctx->v_prev->index, v->index); 0124 } 0125 else 0126 { 0127 new_triangle(ctx, ctx->v_prev->index, ctx->v_prevprev->index, v->index); 0128 } 0129 ctx->odd_even_strip = !ctx->odd_even_strip; 0130 0131 ctx->v_prev = ctx->v_prevprev; 0132 ctx->v_prevprev = v; 0133 } 0134 0135 void triangle_vertex(Vertex *v, TessContext *ctx) 0136 { 0137 if (ctx->v_prevprev == NULL) 0138 { 0139 ctx->v_prevprev = v; 0140 return; 0141 } 0142 if (ctx->v_prev == NULL) 0143 { 0144 ctx->v_prev = v; 0145 return; 0146 } 0147 new_triangle(ctx, ctx->v_prevprev->index, ctx->v_prev->index, v->index); 0148 ctx->v_prev = ctx->v_prevprev = NULL; 0149 } 0150 0151 void vertex(void *vertex_data, void *poly_data) 0152 { 0153 Vertex *ptr = (Vertex *)vertex_data; 0154 TessContext *ctx = (TessContext *)poly_data; 0155 ctx->vertex_cb(ptr, ctx); 0156 } 0157 0158 void begin(GLenum which, void *poly_data) 0159 { 0160 TessContext *ctx = (TessContext *)poly_data; 0161 ctx->v_prev = ctx->v_prevprev = NULL; 0162 ctx->odd_even_strip = 0; 0163 switch (which) 0164 { 0165 case GL_TRIANGLES: 0166 ctx->vertex_cb = &triangle_vertex; 0167 break; 0168 case GL_TRIANGLE_STRIP: 0169 ctx->vertex_cb = &strip_vertex; 0170 break; 0171 case GL_TRIANGLE_FAN: 0172 ctx->vertex_cb = &fan_vertex; 0173 break; 0174 default: 0175 fprintf(stderr, "ERROR, can't handle %d\n", (int)which); 0176 ctx->vertex_cb = &skip_vertex; 0177 } 0178 } 0179 0180 void combine(const GLdouble newVertex[3], const void *neighborVertex[4], const GLfloat neighborWeight[4], 0181 void **outData, void *polyData) 0182 { 0183 TessContext *ctx = (TessContext *)polyData; 0184 Vertex *result = new_vertex(ctx, newVertex[0], newVertex[1]); 0185 *outData = result; 0186 } 0187 0188 void write_output(TessContext *ctx, double **coordinates_out, int **tris_out, int *vc, int *tc) 0189 { 0190 int n_verts = 1 + ctx->latest_v->index; 0191 *vc = n_verts; 0192 int n_tris_copy = ctx->n_tris; 0193 *tc = ctx->n_tris; 0194 *coordinates_out = malloc(n_verts * sizeof(double) * 2); 0195 *tris_out = (ctx->n_tris ? malloc(ctx->n_tris * sizeof(int) * 3) : NULL); 0196 0197 while (ctx->latest_v) 0198 { 0199 (*coordinates_out)[2 * ctx->latest_v->index] = ctx->latest_v->pt[0]; 0200 (*coordinates_out)[2 * ctx->latest_v->index + 1] = ctx->latest_v->pt[1]; 0201 Vertex *prev = ctx->latest_v->prev; 0202 free(ctx->latest_v); 0203 ctx->latest_v = prev; 0204 } 0205 0206 while (ctx->latest_t) 0207 { 0208 (*tris_out)[3 * (n_tris_copy - 1)] = ctx->latest_t->v[0]; 0209 (*tris_out)[3 * (n_tris_copy - 1) + 1] = ctx->latest_t->v[1]; 0210 (*tris_out)[3 * (n_tris_copy - 1) + 2] = ctx->latest_t->v[2]; 0211 Triangle *prev = ctx->latest_t->prev; 0212 free(ctx->latest_t); 0213 ctx->latest_t = prev; 0214 n_tris_copy--; 0215 } 0216 } 0217 0218 void tessellate(double **verts, int *nverts, int **tris, int *ntris, const double **contoursbegin, 0219 const double **contoursend) 0220 { 0221 const double *contourbegin, *contourend; 0222 Vertex *current_vertex; 0223 GLUtesselator *tess; 0224 TessContext *ctx; 0225 0226 tess = gluNewTess(); 0227 ctx = new_tess_context(); 0228 gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); 0229 gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid(*)()) & vertex); 0230 gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid(*)()) & begin); 0231 gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (GLvoid(*)()) & combine); 0232 0233 gluTessBeginPolygon(tess, ctx); 0234 do 0235 { 0236 contourbegin = *contoursbegin++; 0237 contourend = *contoursbegin; 0238 gluTessBeginContour(tess); 0239 while (contourbegin != contourend) 0240 { 0241 current_vertex = new_vertex(ctx, contourbegin[0], contourbegin[1]); 0242 contourbegin += 2; 0243 gluTessVertex(tess, current_vertex->pt, current_vertex); 0244 } 0245 gluTessEndContour(tess); 0246 } while (contoursbegin != (contoursend - 1)); 0247 gluTessEndPolygon(tess); 0248 0249 write_output(ctx, verts, tris, nverts, ntris); 0250 destroy_tess_context(ctx); 0251 gluDeleteTess(tess); 0252 }