1 #define property _property
8 #define TESS_CALLBACK_FUNCTION_PROTOTYPE void (__stdcall*)(void)
10 #define TESS_CALLBACK_FUNCTION_PROTOTYPE void *
14 void * eC_malloc(unsigned int size) { return new byte[size]; }
15 void * eC_realloc(void * pointer, unsigned int size) { return renew pointer byte[size]; }
16 void eC_free(void * pointer) { delete pointer; }
20 static Array<Vector3D> vertices { };
22 static GLUtesselator * butterburTesselator = null;
24 static double ccw(Pointf a, Pointf b, Pointf c)
26 return (((double)b.x - (double)a.x) * ((double)c.y - (double)a.y) - ((double)c.x - (double)a.x) * ((double)b.y - (double)a.y));
29 static bool selfIntersects(Array<Pointf> points)
32 for(i = 0; i < points.count; i++)
34 Pointf * ap = &points[i], * aq = &points[(i < points.count-1) ? i + 1 : 0];
35 for(j = 0; j < points.count; j++)
37 Pointf * bp = &points[j], * bq = &points[(j < points.count-1) ? j + 1 : 0];
38 if(ap != bp && ap != bq && aq != bp && aq != bq)
40 double a = ccw(ap, aq, bp);
41 double b = ccw(ap, aq, bq);
42 double c = ccw(bp, bq, ap);
43 double d = ccw(bp, bq, aq);
45 #define roundoffDouble 0.00000000001
47 if(Abs(a) < roundoffDouble) a = 0;
48 if(Abs(b) < roundoffDouble) b = 0;
49 if(Abs(c) < roundoffDouble) c = 0;
50 if(Abs(d) < roundoffDouble) d = 0;
52 if(Sgn(a) * Sgn(b) < 0 && Sgn(c) * Sgn(d) < 0)
75 Array<CombineVertex> combineVertices;
76 Array<TessPrim> primitives;
77 Array<uint> triIndices;
78 Array<uint> tmpIndices;
82 class CombineVertex : struct
88 static void CALLBACK tessPrimBegin(GLenum which, TessPrimData tesselatorData)
90 tesselatorData.which = which == GL_TRIANGLES ? triangles : which == GL_TRIANGLE_STRIP ? triangleStrip : triangleFan;
91 if(which != GL_TRIANGLES)
93 tesselatorData.tmpIndices.size = 0;
94 if(tesselatorData.primitives.size + 1 > tesselatorData.primitives.minAllocSize)
95 tesselatorData.primitives.minAllocSize += tesselatorData.primitives.minAllocSize / 2;
99 static void CALLBACK tessPrimVertex(Pointf * point, TessPrimData tesselatorData)
104 if(tesselatorData.which == triangles)
106 if(tesselatorData.triIndices.size + 1 > tesselatorData.triIndices.minAllocSize)
107 tesselatorData.triIndices.minAllocSize += tesselatorData.triIndices.minAllocSize / 2;
108 indices = tesselatorData.triIndices.array;
112 if(tesselatorData.tmpIndices.size + 1 > tesselatorData.tmpIndices.minAllocSize)
113 tesselatorData.tmpIndices.minAllocSize += tesselatorData.tmpIndices.minAllocSize / 2;
114 indices = tesselatorData.tmpIndices.array;
117 if(point >= &tesselatorData.output[0] && point < &tesselatorData.output[tesselatorData.output.count])
118 index = point - &tesselatorData.output[0];
121 CombineVertex vertex = (CombineVertex)point;
122 index = tesselatorData.output.count + vertex.id;
125 if(tesselatorData.which == triangles)
127 uint ix = tesselatorData.triIndices.size;
128 tesselatorData.triIndices.size++;
133 uint ix = tesselatorData.tmpIndices.size;
134 tesselatorData.tmpIndices.size++;
139 static void CALLBACK tessPrimEnd(TessPrimData tesselatorData)
141 if(tesselatorData.which != triangles)
144 uint ix = tesselatorData.primitives.size;
145 tesselatorData.primitives.size++;
146 prim = &tesselatorData.primitives[ix];
147 prim->type = tesselatorData.which;
148 prim->count = tesselatorData.tmpIndices.count;
149 prim->indices = new uint32[prim->count];
150 memcpy(prim->indices, &tesselatorData.tmpIndices[0], sizeof(uint) * prim->count);
154 static void CALLBACK tessPrimCombine(GLdouble coords[3], Pointf *d[4],
155 GLfloat w[4], Pointf **dataOut,
156 TessPrimData tesselatorData)
160 position = { (float)coords[0], (float)coords[1] };
161 id = tesselatorData.combineVertices.count;
163 *dataOut = &vertex.position;
164 tesselatorData.combineVertices.Add(vertex);
167 void tesselatePolygon(Array<Pointf> area, Array<Pointf> * outputPtr, Array<TessPrim> * primitivesPtr)
171 int totalCount = area.count;
173 Array<Pointf> output { };
174 Array<TessPrim> primitives { minAllocSize = 16 };
175 Array<CombineVertex> combineVertices { };
177 static TessPrimData tesselatorData;
181 output.size = totalCount;
182 destPoints = &output[0];
184 tesselatorData.primitives = primitives;
185 tesselatorData.combineVertices = combineVertices;
186 tesselatorData.tmpIndices = { minAllocSize = 16 };
187 tesselatorData.triIndices = { minAllocSize = 16 };
188 tesselatorData.output = output;
190 vertices.size = totalCount;
195 for(i = 0; i < n; i++, d++)
197 destPoints[d] = area[i];
198 vertices[d] = { area[i].x, area[i].y };
202 if(!butterburTesselator)
204 butterburTesselator = gluNewTess();
206 gluTessCallback(butterburTesselator, GLU_TESS_BEGIN_DATA, (TESS_CALLBACK_FUNCTION_PROTOTYPE)(void *)tessPrimBegin);
207 gluTessCallback(butterburTesselator, GLU_TESS_END_DATA, (TESS_CALLBACK_FUNCTION_PROTOTYPE)(void *)tessPrimEnd);
208 gluTessCallback(butterburTesselator, GLU_TESS_VERTEX_DATA, (TESS_CALLBACK_FUNCTION_PROTOTYPE)(void *)tessPrimVertex);
209 gluTessCallback(butterburTesselator, GLU_TESS_COMBINE_DATA, (TESS_CALLBACK_FUNCTION_PROTOTYPE)(void *)tessPrimCombine);
211 gluTessProperty(butterburTesselator, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
212 gluTessProperty(butterburTesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
215 gluTessBeginPolygon(butterburTesselator, &tesselatorData);
220 if(n && !selfIntersects(area))
222 gluTessBeginContour(butterburTesselator);
224 for(i = 0; i < n; i++, d++)
225 gluTessVertex(butterburTesselator, (double *)&vertices[d], &destPoints[d]);
226 gluTessEndContour(butterburTesselator);
231 gluTessEndPolygon(butterburTesselator);
233 if(combineVertices.count)
236 int count = output.count;
238 output.size = count + combineVertices.count;
239 for(c = 0; c < combineVertices.count; c++)
241 CombineVertex vertex = combineVertices[c];
242 output[count++] = vertex.position;
246 delete combineVertices;
248 if(tesselatorData.triIndices && tesselatorData.triIndices.count)
250 uint ix = primitives.size;
253 prim = &primitives[ix];
254 prim->type = triangles;
255 prim->count = tesselatorData.triIndices.count;
256 prim->indices = new uint[prim->count];
257 memcpy(prim->indices, &tesselatorData.triIndices[0], sizeof(uint) * prim->count);
260 primitives.minAllocSize = 0;
261 delete tesselatorData.triIndices;
262 delete tesselatorData.tmpIndices;
265 *primitivesPtr = primitives;