diff --git a/dsc.h b/dsc.h index 23a1663..787ca39 100644 --- a/dsc.h +++ b/dsc.h @@ -45,8 +45,6 @@ public: static Vector From(hParam x, hParam y, hParam z); static Vector AtIntersectionOfPlanes(Vector n1, double d1, Vector n2, double d2); - static bool LinesIntersect(Vector a0, Vector da, Vector b0, Vector db, - double *ta, double *tb); bool Equals(Vector v); Vector Plus(Vector b); diff --git a/polygon.cpp b/polygon.cpp index 24df779..0655569 100644 --- a/polygon.cpp +++ b/polygon.cpp @@ -314,246 +314,62 @@ bool SPolygon::AllPointsInPlane(Vector *notCoplanarAt) { return true; } -bool SPolygon::IntersectsPolygon(Vector ga, Vector gb) { - int i, j; - for(i = 0; i < l.n; i++) { - SContour *sc = &(l.elem[i]); - for(j = 0; j < sc->l.n; j++) { - Vector pa = sc->l.elem[j].p, - pb = sc->l.elem[WRAP(j+1, (sc->l.n - 1))].p; - // So do the lines from (ga to gb) and (pa to pb) intersect? - Vector dp = pb.Minus(pa), dg = gb.Minus(ga); - double tp, tg; - if(!Vector::LinesIntersect(pa, dp, ga, dg, &tp, &tg)) { - continue; - } - - // So check if the line segments intersect - double lp = dp.Magnitude(), lg = dg.Magnitude(); - tp *= lp; - tg *= lg; - - if(tg > LENGTH_EPS && tg < (lg - LENGTH_EPS) && - tp > LENGTH_EPS && tp < (lp - LENGTH_EPS)) - { - return true; - } - } - } - return false; -} - -bool SPolygon::VisibleVertices(SContour *outer, SContour *inner, - SEdgeList *extras, int *vo, int *vi) +static int TriMode, TriVertexCount; +static Vector Tri1, TriNMinus1, TriNMinus2; +static Vector TriNormal; +static SMesh *TriMesh; +static STriMeta TriMeta; +static void GLX_CALLBACK TriBegin(int mode) { - int i, j, k; - - double lmin = 1e12; - for(i = 0; i < outer->l.n; i++) { - Vector op = outer->l.elem[i].p; - - for(j = 0; j < inner->l.n; j++) { - Vector ip = inner->l.elem[j].p; - - if(IntersectsPolygon(op, ip)) goto dontuse; - - for(k = 0; k < extras->l.n; k++) { - SEdge *se = &(extras->l.elem[k]); - - if(ip.Equals(se->a) || ip.Equals(se->b) || - op.Equals(se->a) || op.Equals(se->b)) - { - goto dontuse; - } - - Vector dt = ip.Minus(op), de = (se->b).Minus(se->a); - double te, tt; - if(!Vector::LinesIntersect(op, dt, se->a, de, &tt, &te)) - continue; - - double le = de.Magnitude(), lt = dt.Magnitude(); - tt *= lt; - te *= le; - if(tt > LENGTH_EPS && tt < (lt - LENGTH_EPS) && - te > LENGTH_EPS && te < (le - LENGTH_EPS)) - { - goto dontuse; - } - } - - if((op.Minus(ip)).Magnitude() < lmin) { - lmin = (op.Minus(ip)).Magnitude(); - *vo = i; - *vi = j; - } -dontuse:; - } - } - if(lmin < 1e12) { - return true; - } else { - return false; - } + TriMode = mode; + TriVertexCount = 0; } - -bool SContour::VertexIsEar(int v, Vector normal) { - int va = WRAP(v-1, l.n), vb = WRAP(v , l.n), vc = WRAP(v+1, l.n); - Vector a = l.elem[va].p, b = l.elem[vb].p, c = l.elem[vc].p; - - STriMeta meta; - ZERO(&meta); - STriangle tr = STriangle::From(meta, a, b, c); - if(normal.Dot(tr.Normal()) > 0) return false; - - int i; - for(i = 0; i < l.n; i++) { - if(i == va) continue; - if(i == vb) continue; - if(i == vc) continue; - - Vector p = l.elem[i].p; - if(p.Equals(tr.a)) continue; - if(p.Equals(tr.b)) continue; - if(p.Equals(tr.c)) continue; - - if(tr.ContainsPoint(p)) return false; - } - return true; +static void GLX_CALLBACK TriEnd(void) +{ } - -void SContour::TriangulateInto(SMesh *m, STriMeta meta, Vector normal) { - int i; - - bool odd = false; - while(l.n >= 3) { - int start, end, incr; - if(odd) { - start = 0; end = l.n; incr = 1; - } else { - start = l.n - 1; end = -1; incr = -1; - } - for(i = start; i != end; i += incr) { - if(VertexIsEar(i, normal)) { - break; - } - } - if(i == end) { - dbp("couldn't find ear!"); - return; - } - - Vector a = l.elem[WRAP(i-1, l.n)].p, - b = l.elem[WRAP(i , l.n)].p, - c = l.elem[WRAP(i+1, l.n)].p; - m->AddTriangle(meta, c, b, a); - l.ClearTags(); - l.elem[i].tag = 1; - l.RemoveTagged(); - - odd = !odd; +static void GLX_CALLBACK TriVertex(Vector *triN) +{ + if(TriVertexCount == 0) { + Tri1 = *triN; } - - l.Clear(); + if(TriMode == GL_TRIANGLES) { + if((TriVertexCount % 3) == 2) { + TriMesh->AddTriangle( + TriMeta, TriNormal, TriNMinus2, TriNMinus1, *triN); + } + } else if(TriMode == GL_TRIANGLE_FAN) { + if(TriVertexCount >= 2) { + TriMesh->AddTriangle( + TriMeta, TriNormal, Tri1, TriNMinus1, *triN); + } + } else if(TriMode == GL_TRIANGLE_STRIP) { + if(TriVertexCount >= 2) { + TriMesh->AddTriangle( + TriMeta, TriNormal, TriNMinus2, TriNMinus1, *triN); + } + } else oops(); + + TriNMinus2 = TriNMinus1; + TriNMinus1 = *triN; + TriVertexCount++; } - void SPolygon::TriangulateInto(SMesh *m) { STriMeta meta; ZERO(&meta); TriangulateInto(m, meta); } void SPolygon::TriangulateInto(SMesh *m, STriMeta meta) { - FixContourDirections(); + TriMesh = m; + TriNormal = normal; + TriMeta = meta; - int i, j, k; - bool *used = (bool *)AllocTemporary(l.n*sizeof(bool)); - int *winding = (int *)AllocTemporary(l.n*sizeof(int)); - bool **contained = (bool **)AllocTemporary(l.n*sizeof(bool *)); - for(i = 0; i < l.n; i++) { - contained[i] = (bool *)AllocTemporary(l.n*sizeof(bool)); + GLUtesselator *gt = gluNewTess(); + gluTessCallback(gt, GLU_TESS_BEGIN, (glxCallbackFptr *)TriBegin); + gluTessCallback(gt, GLU_TESS_END, (glxCallbackFptr *)TriEnd); + gluTessCallback(gt, GLU_TESS_VERTEX, (glxCallbackFptr *)TriVertex); - SContour *sci = &(l.elem[i]); - if(sci->l.n < 1) continue; - for(j = 0; j < l.n; j++) { - SContour *scj = &(l.elem[j]); - if(scj->l.n < 1) continue; - if(i == j) { - contained[i][j] = true; - continue; - } - - if(scj->ContainsPointProjdToNormal(normal, sci->l.elem[0].p)) { - (winding[i])++; - contained[i][j] = true; - } - } - } + glxTesselatePolygon(gt, this); - for(;;) { - for(i = 0; i < l.n; i++) { - if(winding[i] == 0) break; - } - if(i >= l.n) { - // No outer contours left, so we're done - break; - } - - SContour *outer = &(l.elem[i]); - SContour merged; - ZERO(&merged); - - SEdgeList extras; - ZERO(&extras); - - for(j = 0; j < outer->l.n - 1; j++) { - merged.AddPoint(outer->l.elem[j].p); - } - // If this polygon has holes, then we must merge them in. - for(;;) { - for(j = 0; j < l.n; j++) { - if(used[j]) continue; - if(winding[j] != winding[i] + 1) continue; - if(!contained[j][i]) continue; - - SContour *inner = &(l.elem[j]); - - int vinner, vouter; - if(VisibleVertices(&merged, inner, &extras, &vouter, &vinner)) { - used[j] = true; - - SEdge se = - { 0, merged.l.elem[vouter].p, inner->l.elem[vinner].p }; - extras.l.Add(&se); - - SContour alt; - ZERO(&alt); - for(k = 0; k <= vouter; k++) { - alt.AddPoint(merged.l.elem[k].p); - } - for(k = 0; k <= inner->l.n - 1; k++) { - int v = WRAP(k + vinner, inner->l.n - 1); - alt.AddPoint(inner->l.elem[v].p); - } - for(k = vouter; k < merged.l.n; k++) { - alt.AddPoint(merged.l.elem[k].p); - } - merged.l.Clear(); - merged = alt; - break; - } - } - if(j >= l.n) { - break; - } - } - - merged.TriangulateInto(m, meta, normal); - merged.l.Clear(); - extras.Clear(); - - for(j = 0; j < l.n; j++) { - if(contained[j][i]) winding[j] -= 2; - } - used[i] = true; - } + gluDeleteTess(gt); } diff --git a/polygon.h b/polygon.h index e7da00f..9b896ac 100644 --- a/polygon.h +++ b/polygon.h @@ -78,20 +78,12 @@ public: Vector p; }; -typedef struct { - DWORD face; - int color; -} STriMeta; - class SContour { public: - int tag; SList l; void AddPoint(Vector p); void MakeEdgesInto(SEdgeList *el); - bool VertexIsEar(int v, Vector normal); - void TriangulateInto(SMesh *m, STriMeta meta, Vector normal); void Reverse(void); Vector ComputeNormal(void); bool IsClockwiseProjdToNormal(Vector n); @@ -99,6 +91,11 @@ public: bool AllPointsInPlane(Vector n, double d, Vector *notCoplanarAt); }; +typedef struct { + DWORD face; + int color; +} STriMeta; + class SPolygon { public: SList l; @@ -115,9 +112,6 @@ public: void Clear(void); bool AllPointsInPlane(Vector *notCoplanarAt); bool IsEmpty(void); - bool IntersectsPolygon(Vector a, Vector b); - bool VisibleVertices(SContour *outer, SContour *inner, - SEdgeList *extras, int *vo, int *vi); Vector AnyPoint(void); }; diff --git a/util.cpp b/util.cpp index e4e0c04..eccfbd9 100644 --- a/util.cpp +++ b/util.cpp @@ -500,21 +500,6 @@ Vector Vector::AtIntersectionOfPlanes(Vector n1, double d1, return (n1.ScaledBy(c1)).Plus(n2.ScaledBy(c2)); } -bool Vector::LinesIntersect(Vector a0, Vector da, Vector b0, Vector db, - double *ta, double *tb) -{ - Vector dn = da.Cross(db); // normal to both - if(dn.Magnitude() < 1e-10) return false; - - Vector dna = dn.Cross(da); // normal to dp - Vector dnb = dn.Cross(db); // normal to dg - - *tb = ((a0.Minus(b0)).Dot(dna))/(db.Dot(dna)); - *ta = -((a0.Minus(b0)).Dot(dnb))/(da.Dot(dnb)); - - return true; -} - Point2d Point2d::Plus(Point2d b) { Point2d r; r.x = x + b.x;