tessellate.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "glu.h"
  2. #include "tess.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. /******************************************************************************/
  6. typedef struct Triangle {
  7. int v[3];
  8. struct Triangle *prev;
  9. } Triangle;
  10. typedef struct Vertex {
  11. double pt[3];
  12. int index;
  13. struct Vertex *prev;
  14. } Vertex;
  15. typedef struct TessContext {
  16. Triangle *latest_t;
  17. int n_tris;
  18. Vertex *v_prev;
  19. Vertex *v_prevprev;
  20. Vertex *latest_v;
  21. GLenum current_mode;
  22. int odd_even_strip;
  23. void (*vertex_cb)(Vertex *, struct TessContext *);
  24. } TessContext;
  25. void skip_vertex(Vertex *v, TessContext *ctx);
  26. /******************************************************************************/
  27. TessContext *new_tess_context()
  28. {
  29. TessContext *result = (TessContext *)malloc(sizeof (struct TessContext));
  30. result->latest_t = NULL;
  31. result->latest_v = NULL;
  32. result->n_tris = 0;
  33. result->v_prev = NULL;
  34. result->v_prevprev = NULL;
  35. result->v_prev = NULL;
  36. result->v_prev = NULL;
  37. result->vertex_cb = &skip_vertex;
  38. result->odd_even_strip = 0;
  39. return result;
  40. }
  41. void destroy_tess_context(TessContext *ctx)
  42. {
  43. free(ctx);
  44. }
  45. Vertex *new_vertex(TessContext *ctx, double x, double y)
  46. {
  47. Vertex *result = (Vertex *)malloc(sizeof(Vertex));
  48. result->prev = ctx->latest_v;
  49. result->pt[0] = x;
  50. result->pt[1] = y;
  51. result->pt[2] = 0;
  52. if (ctx->latest_v == NULL) {
  53. result->index = 0;
  54. } else {
  55. result->index = ctx->latest_v->index+1;
  56. }
  57. return ctx->latest_v = result;
  58. }
  59. Triangle *new_triangle(TessContext *ctx, int v1, int v2, int v3)
  60. {
  61. Triangle *result = (Triangle *)malloc(sizeof(Triangle));
  62. result->prev = ctx->latest_t;
  63. result->v[0] = v1;
  64. result->v[1] = v2;
  65. result->v[2] = v3;
  66. ctx->n_tris++;
  67. return ctx->latest_t = result;
  68. }
  69. /******************************************************************************/
  70. void skip_vertex(Vertex *v, TessContext *ctx) {};
  71. void fan_vertex(Vertex *v, TessContext *ctx) {
  72. if (ctx->v_prevprev == NULL) {
  73. ctx->v_prevprev = v;
  74. return;
  75. }
  76. if (ctx->v_prev == NULL) {
  77. ctx->v_prev = v;
  78. return;
  79. }
  80. new_triangle(ctx, ctx->v_prevprev->index, ctx->v_prev->index, v->index);
  81. ctx->v_prev = v;
  82. }
  83. void strip_vertex(Vertex *v, TessContext *ctx)
  84. {
  85. if (ctx->v_prev == NULL) {
  86. ctx->v_prev = v;
  87. return;
  88. }
  89. if (ctx->v_prevprev == NULL) {
  90. ctx->v_prevprev = v;
  91. return;
  92. }
  93. if (ctx->odd_even_strip) {
  94. new_triangle(ctx, ctx->v_prevprev->index, ctx->v_prev->index, v->index);
  95. } else {
  96. new_triangle(ctx, ctx->v_prev->index, ctx->v_prevprev->index, v->index);
  97. }
  98. ctx->odd_even_strip = !ctx->odd_even_strip;
  99. ctx->v_prev = ctx->v_prevprev;
  100. ctx->v_prevprev = v;
  101. }
  102. void triangle_vertex(Vertex *v, TessContext *ctx) {
  103. if (ctx->v_prevprev == NULL) {
  104. ctx->v_prevprev = v;
  105. return;
  106. }
  107. if (ctx->v_prev == NULL) {
  108. ctx->v_prev = v;
  109. return;
  110. }
  111. new_triangle(ctx, ctx->v_prevprev->index, ctx->v_prev->index, v->index);
  112. ctx->v_prev = ctx->v_prevprev = NULL;
  113. }
  114. void vertex(void *vertex_data, void *poly_data)
  115. {
  116. Vertex *ptr = (Vertex *)vertex_data;
  117. TessContext *ctx = (TessContext *)poly_data;
  118. ctx->vertex_cb(ptr, ctx);
  119. }
  120. void begin(GLenum which, void *poly_data)
  121. {
  122. TessContext *ctx = (TessContext *)poly_data;
  123. ctx->v_prev = ctx->v_prevprev = NULL;
  124. ctx->odd_even_strip = 0;
  125. switch (which) {
  126. case GL_TRIANGLES: ctx->vertex_cb = &triangle_vertex; break;
  127. case GL_TRIANGLE_STRIP: ctx->vertex_cb = &strip_vertex; break;
  128. case GL_TRIANGLE_FAN: ctx->vertex_cb = &fan_vertex; break;
  129. default:
  130. fprintf(stderr, "ERROR, can't handle %d\n", (int)which);
  131. ctx->vertex_cb = &skip_vertex;
  132. }
  133. }
  134. void combine(const GLdouble newVertex[3],
  135. const void *neighborVertex[4],
  136. const GLfloat neighborWeight[4], void **outData, void *polyData)
  137. {
  138. TessContext *ctx = (TessContext *)polyData;
  139. Vertex *result = new_vertex(ctx, newVertex[0], newVertex[1]);
  140. *outData = result;
  141. }
  142. void write_output(TessContext *ctx, double **coordinates_out, int **tris_out, int *vc, int *tc)
  143. {
  144. int n_verts = 1 + ctx->latest_v->index;
  145. *vc = n_verts;
  146. int n_tris_copy = ctx->n_tris;
  147. *tc = ctx->n_tris;
  148. *coordinates_out = malloc(n_verts * sizeof(double) * 2);
  149. *tris_out = (ctx->n_tris ? malloc(ctx->n_tris * sizeof(int) * 3) : NULL);
  150. while (ctx->latest_v) {
  151. (*coordinates_out)[2*ctx->latest_v->index] = ctx->latest_v->pt[0];
  152. (*coordinates_out)[2*ctx->latest_v->index+1] = ctx->latest_v->pt[1];
  153. Vertex *prev = ctx->latest_v->prev;
  154. free(ctx->latest_v);
  155. ctx->latest_v = prev;
  156. }
  157. while (ctx->latest_t) {
  158. (*tris_out)[3*(n_tris_copy-1)] = ctx->latest_t->v[0];
  159. (*tris_out)[3*(n_tris_copy-1)+1] = ctx->latest_t->v[1];
  160. (*tris_out)[3*(n_tris_copy-1)+2] = ctx->latest_t->v[2];
  161. Triangle *prev = ctx->latest_t->prev;
  162. free(ctx->latest_t);
  163. ctx->latest_t = prev;
  164. n_tris_copy--;
  165. }
  166. }
  167. void tessellate
  168. (double **verts,
  169. int *nverts,
  170. int **tris,
  171. int *ntris,
  172. const double **contoursbegin,
  173. const double **contoursend)
  174. {
  175. const double *contourbegin, *contourend;
  176. Vertex *current_vertex;
  177. GLUtesselator *tess;
  178. TessContext *ctx;
  179. tess = gluNewTess();
  180. ctx = new_tess_context();
  181. gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (*) ()) &vertex);
  182. gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (*) ()) &begin);
  183. gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (GLvoid (*) ()) &combine);
  184. gluTessBeginPolygon(tess, ctx);
  185. do {
  186. contourbegin = *contoursbegin++;
  187. contourend = *contoursbegin;
  188. gluTessBeginContour(tess);
  189. while (contourbegin != contourend) {
  190. current_vertex = new_vertex(ctx, contourbegin[0], contourbegin[1]);
  191. contourbegin += 2;
  192. gluTessVertex(tess, current_vertex->pt, current_vertex);
  193. }
  194. gluTessEndContour(tess);
  195. } while (contoursbegin != (contoursend - 1));
  196. gluTessEndPolygon(tess);
  197. write_output(ctx, verts, tris, nverts, ntris);
  198. destroy_tess_context(ctx);
  199. gluDeleteTess(tess);
  200. }