File indexing completed on 2024-04-21 14:46:25
0001 /* 0002 ** Author: Eric Veach, July 1994. 0003 ** 0004 */ 0005 0006 #include "gluos.h" 0007 #include <assert.h> 0008 #include <stddef.h> 0009 #include "mesh.h" 0010 #include "tess.h" 0011 #include "render.h" 0012 0013 #ifndef TRUE 0014 #define TRUE 1 0015 #endif 0016 #ifndef FALSE 0017 #define FALSE 0 0018 #endif 0019 0020 /* This structure remembers the information we need about a primitive 0021 * to be able to render it later, once we have determined which 0022 * primitive is able to use the most triangles. 0023 */ 0024 struct FaceCount 0025 { 0026 long size; /* number of triangles used */ 0027 GLUhalfEdge *eStart; /* edge where this primitive starts */ 0028 void (*render)(GLUtesselator *, GLUhalfEdge *, long); 0029 /* routine to render this primitive */ 0030 }; 0031 0032 static struct FaceCount MaximumFan(GLUhalfEdge *eOrig); 0033 static struct FaceCount MaximumStrip(GLUhalfEdge *eOrig); 0034 0035 static void RenderFan(GLUtesselator *tess, GLUhalfEdge *eStart, long size); 0036 static void RenderStrip(GLUtesselator *tess, GLUhalfEdge *eStart, long size); 0037 static void RenderTriangle(GLUtesselator *tess, GLUhalfEdge *eStart, long size); 0038 0039 static void RenderMaximumFaceGroup(GLUtesselator *tess, GLUface *fOrig); 0040 static void RenderLonelyTriangles(GLUtesselator *tess, GLUface *head); 0041 0042 /************************ Strips and Fans decomposition ******************/ 0043 0044 /* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle 0045 * fans, strips, and separate triangles. A substantial effort is made 0046 * to use as few rendering primitives as possible (ie. to make the fans 0047 * and strips as large as possible). 0048 * 0049 * The rendering output is provided as callbacks (see the api). 0050 */ 0051 void __gl_renderMesh(GLUtesselator *tess, GLUmesh *mesh) 0052 { 0053 GLUface *f; 0054 0055 /* Make a list of separate triangles so we can render them all at once */ 0056 tess->lonelyTriList = NULL; 0057 0058 for (f = mesh->fHead.next; f != &mesh->fHead; f = f->next) 0059 { 0060 f->marked = FALSE; 0061 } 0062 for (f = mesh->fHead.next; f != &mesh->fHead; f = f->next) 0063 { 0064 /* We examine all faces in an arbitrary order. Whenever we find 0065 * an unprocessed face F, we output a group of faces including F 0066 * whose size is maximum. 0067 */ 0068 if (f->inside && !f->marked) 0069 { 0070 RenderMaximumFaceGroup(tess, f); 0071 assert(f->marked); 0072 } 0073 } 0074 if (tess->lonelyTriList != NULL) 0075 { 0076 RenderLonelyTriangles(tess, tess->lonelyTriList); 0077 tess->lonelyTriList = NULL; 0078 } 0079 } 0080 0081 static void RenderMaximumFaceGroup(GLUtesselator *tess, GLUface *fOrig) 0082 { 0083 /* We want to find the largest triangle fan or strip of unmarked faces 0084 * which includes the given face fOrig. There are 3 possible fans 0085 * passing through fOrig (one centered at each vertex), and 3 possible 0086 * strips (one for each CCW permutation of the vertices). Our strategy 0087 * is to try all of these, and take the primitive which uses the most 0088 * triangles (a greedy approach). 0089 */ 0090 GLUhalfEdge *e = fOrig->anEdge; 0091 struct FaceCount max, newFace; 0092 0093 max.size = 1; 0094 max.eStart = e; 0095 max.render = &RenderTriangle; 0096 0097 if (!tess->flagBoundary) 0098 { 0099 newFace = MaximumFan(e); 0100 if (newFace.size > max.size) 0101 { 0102 max = newFace; 0103 } 0104 newFace = MaximumFan(e->Lnext); 0105 if (newFace.size > max.size) 0106 { 0107 max = newFace; 0108 } 0109 newFace = MaximumFan(e->Lprev); 0110 if (newFace.size > max.size) 0111 { 0112 max = newFace; 0113 } 0114 0115 newFace = MaximumStrip(e); 0116 if (newFace.size > max.size) 0117 { 0118 max = newFace; 0119 } 0120 newFace = MaximumStrip(e->Lnext); 0121 if (newFace.size > max.size) 0122 { 0123 max = newFace; 0124 } 0125 newFace = MaximumStrip(e->Lprev); 0126 if (newFace.size > max.size) 0127 { 0128 max = newFace; 0129 } 0130 } 0131 (*(max.render))(tess, max.eStart, max.size); 0132 } 0133 0134 /* Macros which keep track of faces we have marked temporarily, and allow 0135 * us to backtrack when necessary. With triangle fans, this is not 0136 * really necessary, since the only awkward case is a loop of triangles 0137 * around a single origin vertex. However with strips the situation is 0138 * more complicated, and we need a general tracking method like the 0139 * one here. 0140 */ 0141 #define Marked(f) (!(f)->inside || (f)->marked) 0142 0143 #define AddToTrail(f, t) ((f)->trail = (t), (t) = (f), (f)->marked = TRUE) 0144 0145 #define FreeTrail(t) \ 0146 do \ 0147 { \ 0148 while ((t) != NULL) \ 0149 { \ 0150 (t)->marked = FALSE; \ 0151 t = (t)->trail; \ 0152 } \ 0153 } while (0) /* absorb trailing semicolon */ 0154 0155 static struct FaceCount MaximumFan(GLUhalfEdge *eOrig) 0156 { 0157 /* eOrig->Lface is the face we want to render. We want to find the size 0158 * of a maximal fan around eOrig->Org. To do this we just walk around 0159 * the origin vertex as far as possible in both directions. 0160 */ 0161 struct FaceCount newFace = { 0, NULL, &RenderFan }; 0162 GLUface *trail = NULL; 0163 GLUhalfEdge *e; 0164 0165 for (e = eOrig; !Marked(e->Lface); e = e->Onext) 0166 { 0167 AddToTrail(e->Lface, trail); 0168 ++newFace.size; 0169 } 0170 for (e = eOrig; !Marked(e->Rface); e = e->Oprev) 0171 { 0172 AddToTrail(e->Rface, trail); 0173 ++newFace.size; 0174 } 0175 newFace.eStart = e; 0176 /*LINTED*/ 0177 FreeTrail(trail); 0178 return newFace; 0179 } 0180 0181 #define IsEven(n) (((n)&1) == 0) 0182 0183 static struct FaceCount MaximumStrip(GLUhalfEdge *eOrig) 0184 { 0185 /* Here we are looking for a maximal strip that contains the vertices 0186 * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the 0187 * reverse, such that all triangles are oriented CCW). 0188 * 0189 * Again we walk forward and backward as far as possible. However for 0190 * strips there is a twist: to get CCW orientations, there must be 0191 * an *even* number of triangles in the strip on one side of eOrig. 0192 * We walk the strip starting on a side with an even number of triangles; 0193 * if both side have an odd number, we are forced to shorten one side. 0194 */ 0195 struct FaceCount newFace = { 0, NULL, &RenderStrip }; 0196 long headSize = 0, tailSize = 0; 0197 GLUface *trail = NULL; 0198 GLUhalfEdge *e, *eTail, *eHead; 0199 0200 for (e = eOrig; !Marked(e->Lface); ++tailSize, e = e->Onext) 0201 { 0202 AddToTrail(e->Lface, trail); 0203 ++tailSize; 0204 e = e->Dprev; 0205 if (Marked(e->Lface)) 0206 break; 0207 AddToTrail(e->Lface, trail); 0208 } 0209 eTail = e; 0210 0211 for (e = eOrig; !Marked(e->Rface); ++headSize, e = e->Dnext) 0212 { 0213 AddToTrail(e->Rface, trail); 0214 ++headSize; 0215 e = e->Oprev; 0216 if (Marked(e->Rface)) 0217 break; 0218 AddToTrail(e->Rface, trail); 0219 } 0220 eHead = e; 0221 0222 newFace.size = tailSize + headSize; 0223 if (IsEven(tailSize)) 0224 { 0225 newFace.eStart = eTail->Sym; 0226 } 0227 else if (IsEven(headSize)) 0228 { 0229 newFace.eStart = eHead; 0230 } 0231 else 0232 { 0233 /* Both sides have odd length, we must shorten one of them. In fact, 0234 * we must start from eHead to guarantee inclusion of eOrig->Lface. 0235 */ 0236 --newFace.size; 0237 newFace.eStart = eHead->Onext; 0238 } 0239 /*LINTED*/ 0240 FreeTrail(trail); 0241 return newFace; 0242 } 0243 0244 static void RenderTriangle(GLUtesselator *tess, GLUhalfEdge *e, long size) 0245 { 0246 /* Just add the triangle to a triangle list, so we can render all 0247 * the separate triangles at once. 0248 */ 0249 assert(size == 1); 0250 AddToTrail(e->Lface, tess->lonelyTriList); 0251 } 0252 0253 static void RenderLonelyTriangles(GLUtesselator *tess, GLUface *f) 0254 { 0255 /* Now we render all the separate triangles which could not be 0256 * grouped into a triangle fan or strip. 0257 */ 0258 GLUhalfEdge *e; 0259 int newState; 0260 int edgeState = -1; /* force edge state output for first vertex */ 0261 0262 CALL_BEGIN_OR_BEGIN_DATA(GL_TRIANGLES); 0263 0264 for (; f != NULL; f = f->trail) 0265 { 0266 /* Loop once for each edge (there will always be 3 edges) */ 0267 0268 e = f->anEdge; 0269 do 0270 { 0271 if (tess->flagBoundary) 0272 { 0273 /* Set the "edge state" to TRUE just before we output the 0274 * first vertex of each edge on the polygon boundary. 0275 */ 0276 newState = !e->Rface->inside; 0277 if (edgeState != newState) 0278 { 0279 edgeState = newState; 0280 CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(edgeState); 0281 } 0282 } 0283 CALL_VERTEX_OR_VERTEX_DATA(e->Org->data); 0284 0285 e = e->Lnext; 0286 } while (e != f->anEdge); 0287 } 0288 CALL_END_OR_END_DATA(); 0289 } 0290 0291 static void RenderFan(GLUtesselator *tess, GLUhalfEdge *e, long size) 0292 { 0293 /* Render as many CCW triangles as possible in a fan starting from 0294 * edge "e". The fan *should* contain exactly "size" triangles 0295 * (otherwise we've goofed up somewhere). 0296 */ 0297 CALL_BEGIN_OR_BEGIN_DATA(GL_TRIANGLE_FAN); 0298 CALL_VERTEX_OR_VERTEX_DATA(e->Org->data); 0299 CALL_VERTEX_OR_VERTEX_DATA(e->Dst->data); 0300 0301 while (!Marked(e->Lface)) 0302 { 0303 e->Lface->marked = TRUE; 0304 --size; 0305 e = e->Onext; 0306 CALL_VERTEX_OR_VERTEX_DATA(e->Dst->data); 0307 } 0308 0309 assert(size == 0); 0310 CALL_END_OR_END_DATA(); 0311 } 0312 0313 static void RenderStrip(GLUtesselator *tess, GLUhalfEdge *e, long size) 0314 { 0315 /* Render as many CCW triangles as possible in a strip starting from 0316 * edge "e". The strip *should* contain exactly "size" triangles 0317 * (otherwise we've goofed up somewhere). 0318 */ 0319 CALL_BEGIN_OR_BEGIN_DATA(GL_TRIANGLE_STRIP); 0320 CALL_VERTEX_OR_VERTEX_DATA(e->Org->data); 0321 CALL_VERTEX_OR_VERTEX_DATA(e->Dst->data); 0322 0323 while (!Marked(e->Lface)) 0324 { 0325 e->Lface->marked = TRUE; 0326 --size; 0327 e = e->Dprev; 0328 CALL_VERTEX_OR_VERTEX_DATA(e->Org->data); 0329 if (Marked(e->Lface)) 0330 break; 0331 0332 e->Lface->marked = TRUE; 0333 --size; 0334 e = e->Onext; 0335 CALL_VERTEX_OR_VERTEX_DATA(e->Dst->data); 0336 } 0337 0338 assert(size == 0); 0339 CALL_END_OR_END_DATA(); 0340 } 0341 0342 /************************ Boundary contour decomposition ******************/ 0343 0344 /* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one 0345 * contour for each face marked "inside". The rendering output is 0346 * provided as callbacks (see the api). 0347 */ 0348 void __gl_renderBoundary(GLUtesselator *tess, GLUmesh *mesh) 0349 { 0350 GLUface *f; 0351 GLUhalfEdge *e; 0352 0353 for (f = mesh->fHead.next; f != &mesh->fHead; f = f->next) 0354 { 0355 if (f->inside) 0356 { 0357 CALL_BEGIN_OR_BEGIN_DATA(GL_LINE_LOOP); 0358 e = f->anEdge; 0359 do 0360 { 0361 CALL_VERTEX_OR_VERTEX_DATA(e->Org->data); 0362 e = e->Lnext; 0363 } while (e != f->anEdge); 0364 CALL_END_OR_END_DATA(); 0365 } 0366 } 0367 } 0368 0369 /************************ Quick-and-dirty decomposition ******************/ 0370 0371 #define SIGN_INCONSISTENT 2 0372 0373 static int ComputeNormal(GLUtesselator *tess, GLdouble norm[3], int check) 0374 /* 0375 * If check==FALSE, we compute the polygon normal and place it in norm[]. 0376 * If check==TRUE, we check that each triangle in the fan from v0 has a 0377 * consistent orientation with respect to norm[]. If triangles are 0378 * consistently oriented CCW, return 1; if CW, return -1; if all triangles 0379 * are degenerate return 0; otherwise (no consistent orientation) return 0380 * SIGN_INCONSISTENT. 0381 */ 0382 { 0383 CachedVertex *v0 = tess->cache; 0384 CachedVertex *vn = v0 + tess->cacheCount; 0385 CachedVertex *vc; 0386 GLdouble dot, xc, yc, zc, xp, yp, zp, n[3]; 0387 int sign = 0; 0388 0389 /* Find the polygon normal. It is important to get a reasonable 0390 * normal even when the polygon is self-intersecting (eg. a bowtie). 0391 * Otherwise, the computed normal could be very tiny, but perpendicular 0392 * to the true plane of the polygon due to numerical noise. Then all 0393 * the triangles would appear to be degenerate and we would incorrectly 0394 * decompose the polygon as a fan (or simply not render it at all). 0395 * 0396 * We use a sum-of-triangles normal algorithm rather than the more 0397 * efficient sum-of-trapezoids method (used in CheckOrientation() 0398 * in normal.c). This lets us explicitly reverse the signed area 0399 * of some triangles to get a reasonable normal in the self-intersecting 0400 * case. 0401 */ 0402 if (!check) 0403 { 0404 norm[0] = norm[1] = norm[2] = 0.0; 0405 } 0406 0407 vc = v0 + 1; 0408 xc = vc->coords[0] - v0->coords[0]; 0409 yc = vc->coords[1] - v0->coords[1]; 0410 zc = vc->coords[2] - v0->coords[2]; 0411 while (++vc < vn) 0412 { 0413 xp = xc; 0414 yp = yc; 0415 zp = zc; 0416 xc = vc->coords[0] - v0->coords[0]; 0417 yc = vc->coords[1] - v0->coords[1]; 0418 zc = vc->coords[2] - v0->coords[2]; 0419 0420 /* Compute (vp - v0) cross (vc - v0) */ 0421 n[0] = yp * zc - zp * yc; 0422 n[1] = zp * xc - xp * zc; 0423 n[2] = xp * yc - yp * xc; 0424 0425 dot = n[0] * norm[0] + n[1] * norm[1] + n[2] * norm[2]; 0426 if (!check) 0427 { 0428 /* Reverse the contribution of back-facing triangles to get 0429 * a reasonable normal for self-intersecting polygons (see above) 0430 */ 0431 if (dot >= 0) 0432 { 0433 norm[0] += n[0]; 0434 norm[1] += n[1]; 0435 norm[2] += n[2]; 0436 } 0437 else 0438 { 0439 norm[0] -= n[0]; 0440 norm[1] -= n[1]; 0441 norm[2] -= n[2]; 0442 } 0443 } 0444 else if (dot != 0) 0445 { 0446 /* Check the new orientation for consistency with previous triangles */ 0447 if (dot > 0) 0448 { 0449 if (sign < 0) 0450 return SIGN_INCONSISTENT; 0451 sign = 1; 0452 } 0453 else 0454 { 0455 if (sign > 0) 0456 return SIGN_INCONSISTENT; 0457 sign = -1; 0458 } 0459 } 0460 } 0461 return sign; 0462 } 0463 0464 /* __gl_renderCache( tess ) takes a single contour and tries to render it 0465 * as a triangle fan. This handles convex polygons, as well as some 0466 * non-convex polygons if we get lucky. 0467 * 0468 * Returns TRUE if the polygon was successfully rendered. The rendering 0469 * output is provided as callbacks (see the api). 0470 */ 0471 GLboolean __gl_renderCache(GLUtesselator *tess) 0472 { 0473 CachedVertex *v0 = tess->cache; 0474 CachedVertex *vn = v0 + tess->cacheCount; 0475 CachedVertex *vc; 0476 GLdouble norm[3]; 0477 int sign; 0478 0479 if (tess->cacheCount < 3) 0480 { 0481 /* Degenerate contour -- no output */ 0482 return TRUE; 0483 } 0484 0485 norm[0] = tess->normal[0]; 0486 norm[1] = tess->normal[1]; 0487 norm[2] = tess->normal[2]; 0488 if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) 0489 { 0490 ComputeNormal(tess, norm, FALSE); 0491 } 0492 0493 sign = ComputeNormal(tess, norm, TRUE); 0494 if (sign == SIGN_INCONSISTENT) 0495 { 0496 /* Fan triangles did not have a consistent orientation */ 0497 return FALSE; 0498 } 0499 if (sign == 0) 0500 { 0501 /* All triangles were degenerate */ 0502 return TRUE; 0503 } 0504 0505 /* Make sure we do the right thing for each winding rule */ 0506 switch (tess->windingRule) 0507 { 0508 case GLU_TESS_WINDING_ODD: 0509 case GLU_TESS_WINDING_NONZERO: 0510 break; 0511 case GLU_TESS_WINDING_POSITIVE: 0512 if (sign < 0) 0513 return TRUE; 0514 break; 0515 case GLU_TESS_WINDING_NEGATIVE: 0516 if (sign > 0) 0517 return TRUE; 0518 break; 0519 case GLU_TESS_WINDING_ABS_GEQ_TWO: 0520 return TRUE; 0521 } 0522 0523 CALL_BEGIN_OR_BEGIN_DATA(tess->boundaryOnly ? GL_LINE_LOOP : 0524 (tess->cacheCount > 3) ? GL_TRIANGLE_FAN : GL_TRIANGLES); 0525 0526 CALL_VERTEX_OR_VERTEX_DATA(v0->data); 0527 if (sign > 0) 0528 { 0529 for (vc = v0 + 1; vc < vn; ++vc) 0530 { 0531 CALL_VERTEX_OR_VERTEX_DATA(vc->data); 0532 } 0533 } 0534 else 0535 { 0536 for (vc = vn - 1; vc > v0; --vc) 0537 { 0538 CALL_VERTEX_OR_VERTEX_DATA(vc->data); 0539 } 0540 } 0541 CALL_END_OR_END_DATA(); 0542 return TRUE; 0543 }