From ddf93642576d048b60c27676ecfc74579a595204 Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Thu, 21 May 2009 01:06:26 -0800 Subject: [PATCH] Add a separate display mesh and edge list; so if we're working with a mesh than that's a copy, and if we're working with a shell then it's the shell's triangulation. [git-p4: depot-paths = "//depot/solvespace/": change = 1957] --- draw.cpp | 2 +- export.cpp | 13 +++++++++---- file.cpp | 4 ++++ graphicswin.cpp | 6 ++++-- groupmesh.cpp | 33 ++++++++++++++++++++++----------- sketch.h | 9 ++++++++- solvespace.cpp | 4 ++-- textscreens.cpp | 2 +- undoredo.cpp | 8 ++++++-- 9 files changed, 57 insertions(+), 24 deletions(-) diff --git a/draw.cpp b/draw.cpp index ebd3115..1ae0eb6 100644 --- a/draw.cpp +++ b/draw.cpp @@ -868,7 +868,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) { // Faces, from the triangle mesh; these are lowest priority if(s.constraint.v == 0 && s.entity.v == 0 && showShaded && showFaces) { - SMesh *m = &((SK.GetGroup(activeGroup))->runningMesh); + SMesh *m = &((SK.GetGroup(activeGroup))->displayMesh); DWORD v = m->FirstIntersectionWith(mp); if(v) { s.entity.v = v; diff --git a/export.cpp b/export.cpp index a960379..f68f111 100644 --- a/export.cpp +++ b/export.cpp @@ -6,7 +6,8 @@ void SolveSpace::ExportSectionTo(char *filename) { gn = gn.WithMagnitude(1); Group *g = SK.GetGroup(SS.GW.activeGroup); - if(g->runningMesh.l.n == 0) { + g->GenerateDisplayItems(); + if(g->displayMesh.l.n == 0) { Error("No solid model present; draw one with extrudes and revolves, " "or use Export 2d View to export bare lines and curves."); return; @@ -95,7 +96,9 @@ void SolveSpace::ExportViewTo(char *filename) { SMesh *sm = NULL; if(SS.GW.showShaded) { - sm = &((SK.GetGroup(SS.GW.activeGroup))->runningMesh); + Group *g = SK.GetGroup(SS.GW.activeGroup); + g->GenerateDisplayItems(); + sm = &(g->displayMesh); } if(sm->l.n == 0) { sm = NULL; @@ -119,7 +122,9 @@ void SolveSpace::ExportViewTo(char *filename) { } if(SS.GW.showEdges) { - SEdgeList *selr = &((SK.GetGroup(SS.GW.activeGroup))->runningEdges); + Group *g = SK.GetGroup(SS.GW.activeGroup); + g->GenerateDisplayItems(); + SEdgeList *selr = &(g->displayEdges); SEdge *se; for(se = selr->l.First(); se; se = selr->l.NextAfter(se)) { edges.AddEdge(se->a, se->b); @@ -973,7 +978,7 @@ void HpglFileWriter::FinishAndCloseFile(void) { // not self-intersecting, so not much to do. //----------------------------------------------------------------------------- void SolveSpace::ExportMeshTo(char *filename) { - SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->runningMesh); + SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh); if(m->l.n == 0) { Error("Active group mesh is empty; nothing to export."); return; diff --git a/file.cpp b/file.cpp index 2b437ee..11afb7c 100644 --- a/file.cpp +++ b/file.cpp @@ -78,6 +78,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = { { 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) }, { 'g', "Group.skipFirst", 'b', &(SS.sv.g.skipFirst) }, { 'g', "Group.meshCombine", 'd', &(SS.sv.g.meshCombine) }, + { 'g', "Group.forceToMesh", 'd', &(SS.sv.g.forceToMesh) }, { 'g', "Group.predef.q.w", 'f', &(SS.sv.g.predef.q.w) }, { 'g', "Group.predef.q.vx", 'f', &(SS.sv.g.predef.q.vx) }, { 'g', "Group.predef.q.vy", 'f', &(SS.sv.g.predef.q.vy) }, @@ -235,6 +236,9 @@ bool SolveSpace::SaveToFile(char *filename) { fprintf(fh, "AddConstraint\n\n"); } + // A group will have either a mesh or a shell, but not both; but the code + // to print either of those just does nothing if the mesh/shell is empty. + SMesh *m = &(SK.group.elem[SK.group.n-1].runningMesh); for(i = 0; i < m->l.n; i++) { STriangle *tr = &(m->l.elem[i]); diff --git a/graphicswin.cpp b/graphicswin.cpp index 7d4cf98..a536f3a 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -290,9 +290,11 @@ void GraphicsWindow::LoopOverPoints( } } } + Group *g = SK.GetGroup(activeGroup); - for(i = 0; i < g->runningMesh.l.n; i++) { - STriangle *tr = &(g->runningMesh.l.elem[i]); + g->GenerateDisplayItems(); + for(i = 0; i < g->displayMesh.l.n; i++) { + STriangle *tr = &(g->displayMesh.l.elem[i]); HandlePointForZoomToFit(tr->a, pmax, pmin, wmin, div); HandlePointForZoomToFit(tr->b, pmax, pmin, wmin, div); HandlePointForZoomToFit(tr->c, pmax, pmin, wmin, div); diff --git a/groupmesh.cpp b/groupmesh.cpp index 8e0a31c..19ce083 100644 --- a/groupmesh.cpp +++ b/groupmesh.cpp @@ -238,8 +238,8 @@ void Group::GenerateShellAndMesh(void) { goto done; } - // So our group's mesh appears in thisMesh. Combine this with the previous - // group's mesh, using the requested operation. + // So our group's shell appears in thisShell. Combine this with the + // previous group's shell, using the requested operation. SShell *a = PreviousGroupShell(); if(meshCombine == COMBINE_AS_UNION) { runningShell.MakeFromUnionOf(a, &thisShell); @@ -250,10 +250,17 @@ void Group::GenerateShellAndMesh(void) { } done: - runningMesh.Clear(); - runningShell.TriangulateInto(&runningMesh); - runningEdges.Clear(); - runningShell.MakeEdgesInto(&runningEdges); + displayDirty = true; +} + +void Group::GenerateDisplayItems(void) { + if(displayDirty) { + displayMesh.Clear(); + runningShell.TriangulateInto(&displayMesh); + displayEdges.Clear(); + runningShell.MakeEdgesInto(&displayEdges); + displayDirty = false; + } } SShell *Group::PreviousGroupShell(void) { @@ -267,8 +274,12 @@ SShell *Group::PreviousGroupShell(void) { } void Group::Draw(void) { - // Show this even if the group is not visible. It's already possible - // to show or hide just this with the "show solids" flag. + // Everything here gets drawn whether or not the group is hidden; we + // can control this stuff independently, with show/hide solids, edges, + // mesh, etc. + + // Triangulate the shells if necessary. + GenerateDisplayItems(); int specColor; if(type == DRAWING_3D || type == DRAWING_WORKPLANE) { @@ -294,7 +305,7 @@ void Group::Draw(void) { if(SS.GW.showShaded) { glEnable(GL_LIGHTING); - glxFillMesh(specColor, &runningMesh, mh, ms1, ms2); + glxFillMesh(specColor, &displayMesh, mh, ms1, ms2); glDisable(GL_LIGHTING); } if(SS.GW.showEdges) { @@ -303,10 +314,10 @@ void Group::Draw(void) { glxColor3d(REDf (SS.edgeColor), GREENf(SS.edgeColor), BLUEf (SS.edgeColor)); - glxDrawEdges(&runningEdges); + glxDrawEdges(&displayEdges); } - if(SS.GW.showMesh) glxDebugMesh(&runningMesh); + if(SS.GW.showMesh) glxDebugMesh(&displayMesh); // And finally show the polygons too if(!SS.GW.showShaded) return; diff --git a/sketch.h b/sketch.h index 55bc91e..8670c2f 100644 --- a/sketch.h +++ b/sketch.h @@ -148,14 +148,20 @@ public: SShell thisShell; SShell runningShell; + SMesh thisMesh; SMesh runningMesh; - SEdgeList runningEdges; + + bool displayDirty; + SMesh displayMesh; + SEdgeList displayEdges; static const int COMBINE_AS_UNION = 0; static const int COMBINE_AS_DIFFERENCE = 1; static const int COMBINE_AS_ASSEMBLE = 2; int meshCombine; + bool forceToMesh; + IdList remap; static const int REMAP_PRIME = 19477; int remapCache[REMAP_PRIME]; @@ -203,6 +209,7 @@ public: // And the mesh stuff SShell *PreviousGroupShell(void); void GenerateShellForStepAndRepeat(void); + void GenerateDisplayItems(void); void GenerateShellAndMesh(void); void Draw(void); diff --git a/solvespace.cpp b/solvespace.cpp index eb6677c..89a778a 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -417,7 +417,7 @@ void SolveSpace::MenuAnalyze(int id) { case GraphicsWindow::MNU_NAKED_EDGES: { SS.nakedEdges.Clear(); - SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->runningMesh); + SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh); SKdNode *root = SKdNode::From(m); bool inters, leaks; root->MakeNakedEdgesInto(&(SS.nakedEdges), &inters, &leaks); @@ -441,7 +441,7 @@ void SolveSpace::MenuAnalyze(int id) { } case GraphicsWindow::MNU_VOLUME: { - SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->runningMesh); + SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh); double vol = 0; int i; diff --git a/textscreens.cpp b/textscreens.cpp index 67148d8..0276a72 100644 --- a/textscreens.cpp +++ b/textscreens.cpp @@ -654,7 +654,7 @@ void TextWindow::ShowConfiguration(void) { Printf(false, "%Ba %2 %Fl%Ll%f%D[change]%E; now %d triangles", SS.chordTol, &ScreenChangeChordTolerance, 0, - SK.GetGroup(SS.GW.activeGroup)->runningMesh.l.n); + SK.GetGroup(SS.GW.activeGroup)->displayMesh.l.n); Printf(false, "%Ft max piecewise linear segments%E"); Printf(false, "%Ba %d %Fl%Ll%f[change]%E", SS.maxSegments, diff --git a/undoredo.cpp b/undoredo.cpp index d7d85c9..87c68d6 100644 --- a/undoredo.cpp +++ b/undoredo.cpp @@ -50,10 +50,12 @@ void SolveSpace::PushFromCurrentOnto(UndoStack *uk) { ZERO(&(dest.poly)); ZERO(&(dest.bezierLoopSet)); ZERO(&(dest.polyError)); + ZERO(&(dest.thisMesh)); ZERO(&(dest.runningMesh)); ZERO(&(dest.thisShell)); ZERO(&(dest.runningShell)); - ZERO(&(dest.runningEdges)); + ZERO(&(dest.displayMesh)); + ZERO(&(dest.displayEdges)); ZERO(&(dest.remap)); src->remap.DeepCopyInto(&(dest.remap)); @@ -93,10 +95,12 @@ void SolveSpace::PopOntoCurrentFrom(UndoStack *uk) { Group *g = &(SK.group.elem[i]); g->poly.Clear(); g->bezierLoopSet.Clear(); + g->thisMesh.Clear(); g->runningMesh.Clear(); g->thisShell.Clear(); g->runningShell.Clear(); - g->runningEdges.Clear(); + g->displayMesh.Clear(); + g->displayEdges.Clear(); g->remap.Clear(); g->impMesh.Clear(); g->impShell.Clear();