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]
This commit is contained in:
Jonathan Westhues 2009-05-21 01:06:26 -08:00
parent e70bb37061
commit ddf9364257
9 changed files with 57 additions and 24 deletions

View File

@ -868,7 +868,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
// Faces, from the triangle mesh; these are lowest priority // Faces, from the triangle mesh; these are lowest priority
if(s.constraint.v == 0 && s.entity.v == 0 && showShaded && showFaces) { 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); DWORD v = m->FirstIntersectionWith(mp);
if(v) { if(v) {
s.entity.v = v; s.entity.v = v;

View File

@ -6,7 +6,8 @@ void SolveSpace::ExportSectionTo(char *filename) {
gn = gn.WithMagnitude(1); gn = gn.WithMagnitude(1);
Group *g = SK.GetGroup(SS.GW.activeGroup); 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, " Error("No solid model present; draw one with extrudes and revolves, "
"or use Export 2d View to export bare lines and curves."); "or use Export 2d View to export bare lines and curves.");
return; return;
@ -95,7 +96,9 @@ void SolveSpace::ExportViewTo(char *filename) {
SMesh *sm = NULL; SMesh *sm = NULL;
if(SS.GW.showShaded) { 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) { if(sm->l.n == 0) {
sm = NULL; sm = NULL;
@ -119,7 +122,9 @@ void SolveSpace::ExportViewTo(char *filename) {
} }
if(SS.GW.showEdges) { 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; SEdge *se;
for(se = selr->l.First(); se; se = selr->l.NextAfter(se)) { for(se = selr->l.First(); se; se = selr->l.NextAfter(se)) {
edges.AddEdge(se->a, se->b); edges.AddEdge(se->a, se->b);
@ -973,7 +978,7 @@ void HpglFileWriter::FinishAndCloseFile(void) {
// not self-intersecting, so not much to do. // not self-intersecting, so not much to do.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SolveSpace::ExportMeshTo(char *filename) { 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) { if(m->l.n == 0) {
Error("Active group mesh is empty; nothing to export."); Error("Active group mesh is empty; nothing to export.");
return; return;

View File

@ -78,6 +78,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) }, { 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) },
{ 'g', "Group.skipFirst", 'b', &(SS.sv.g.skipFirst) }, { 'g', "Group.skipFirst", 'b', &(SS.sv.g.skipFirst) },
{ 'g', "Group.meshCombine", 'd', &(SS.sv.g.meshCombine) }, { '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.w", 'f', &(SS.sv.g.predef.q.w) },
{ 'g', "Group.predef.q.vx", 'f', &(SS.sv.g.predef.q.vx) }, { 'g', "Group.predef.q.vx", 'f', &(SS.sv.g.predef.q.vx) },
{ 'g', "Group.predef.q.vy", 'f', &(SS.sv.g.predef.q.vy) }, { '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"); 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); SMesh *m = &(SK.group.elem[SK.group.n-1].runningMesh);
for(i = 0; i < m->l.n; i++) { for(i = 0; i < m->l.n; i++) {
STriangle *tr = &(m->l.elem[i]); STriangle *tr = &(m->l.elem[i]);

View File

@ -290,9 +290,11 @@ void GraphicsWindow::LoopOverPoints(
} }
} }
} }
Group *g = SK.GetGroup(activeGroup); Group *g = SK.GetGroup(activeGroup);
for(i = 0; i < g->runningMesh.l.n; i++) { g->GenerateDisplayItems();
STriangle *tr = &(g->runningMesh.l.elem[i]); 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->a, pmax, pmin, wmin, div);
HandlePointForZoomToFit(tr->b, pmax, pmin, wmin, div); HandlePointForZoomToFit(tr->b, pmax, pmin, wmin, div);
HandlePointForZoomToFit(tr->c, pmax, pmin, wmin, div); HandlePointForZoomToFit(tr->c, pmax, pmin, wmin, div);

View File

@ -238,8 +238,8 @@ void Group::GenerateShellAndMesh(void) {
goto done; goto done;
} }
// So our group's mesh appears in thisMesh. Combine this with the previous // So our group's shell appears in thisShell. Combine this with the
// group's mesh, using the requested operation. // previous group's shell, using the requested operation.
SShell *a = PreviousGroupShell(); SShell *a = PreviousGroupShell();
if(meshCombine == COMBINE_AS_UNION) { if(meshCombine == COMBINE_AS_UNION) {
runningShell.MakeFromUnionOf(a, &thisShell); runningShell.MakeFromUnionOf(a, &thisShell);
@ -250,10 +250,17 @@ void Group::GenerateShellAndMesh(void) {
} }
done: done:
runningMesh.Clear(); displayDirty = true;
runningShell.TriangulateInto(&runningMesh); }
runningEdges.Clear();
runningShell.MakeEdgesInto(&runningEdges); void Group::GenerateDisplayItems(void) {
if(displayDirty) {
displayMesh.Clear();
runningShell.TriangulateInto(&displayMesh);
displayEdges.Clear();
runningShell.MakeEdgesInto(&displayEdges);
displayDirty = false;
}
} }
SShell *Group::PreviousGroupShell(void) { SShell *Group::PreviousGroupShell(void) {
@ -267,8 +274,12 @@ SShell *Group::PreviousGroupShell(void) {
} }
void Group::Draw(void) { void Group::Draw(void) {
// Show this even if the group is not visible. It's already possible // Everything here gets drawn whether or not the group is hidden; we
// to show or hide just this with the "show solids" flag. // can control this stuff independently, with show/hide solids, edges,
// mesh, etc.
// Triangulate the shells if necessary.
GenerateDisplayItems();
int specColor; int specColor;
if(type == DRAWING_3D || type == DRAWING_WORKPLANE) { if(type == DRAWING_3D || type == DRAWING_WORKPLANE) {
@ -294,7 +305,7 @@ void Group::Draw(void) {
if(SS.GW.showShaded) { if(SS.GW.showShaded) {
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glxFillMesh(specColor, &runningMesh, mh, ms1, ms2); glxFillMesh(specColor, &displayMesh, mh, ms1, ms2);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
} }
if(SS.GW.showEdges) { if(SS.GW.showEdges) {
@ -303,10 +314,10 @@ void Group::Draw(void) {
glxColor3d(REDf (SS.edgeColor), glxColor3d(REDf (SS.edgeColor),
GREENf(SS.edgeColor), GREENf(SS.edgeColor),
BLUEf (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 // And finally show the polygons too
if(!SS.GW.showShaded) return; if(!SS.GW.showShaded) return;

View File

@ -148,14 +148,20 @@ public:
SShell thisShell; SShell thisShell;
SShell runningShell; SShell runningShell;
SMesh thisMesh;
SMesh runningMesh; SMesh runningMesh;
SEdgeList runningEdges;
bool displayDirty;
SMesh displayMesh;
SEdgeList displayEdges;
static const int COMBINE_AS_UNION = 0; static const int COMBINE_AS_UNION = 0;
static const int COMBINE_AS_DIFFERENCE = 1; static const int COMBINE_AS_DIFFERENCE = 1;
static const int COMBINE_AS_ASSEMBLE = 2; static const int COMBINE_AS_ASSEMBLE = 2;
int meshCombine; int meshCombine;
bool forceToMesh;
IdList<EntityMap,EntityId> remap; IdList<EntityMap,EntityId> remap;
static const int REMAP_PRIME = 19477; static const int REMAP_PRIME = 19477;
int remapCache[REMAP_PRIME]; int remapCache[REMAP_PRIME];
@ -203,6 +209,7 @@ public:
// And the mesh stuff // And the mesh stuff
SShell *PreviousGroupShell(void); SShell *PreviousGroupShell(void);
void GenerateShellForStepAndRepeat(void); void GenerateShellForStepAndRepeat(void);
void GenerateDisplayItems(void);
void GenerateShellAndMesh(void); void GenerateShellAndMesh(void);
void Draw(void); void Draw(void);

View File

@ -417,7 +417,7 @@ void SolveSpace::MenuAnalyze(int id) {
case GraphicsWindow::MNU_NAKED_EDGES: { case GraphicsWindow::MNU_NAKED_EDGES: {
SS.nakedEdges.Clear(); SS.nakedEdges.Clear();
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->runningMesh); SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
SKdNode *root = SKdNode::From(m); SKdNode *root = SKdNode::From(m);
bool inters, leaks; bool inters, leaks;
root->MakeNakedEdgesInto(&(SS.nakedEdges), &inters, &leaks); root->MakeNakedEdgesInto(&(SS.nakedEdges), &inters, &leaks);
@ -441,7 +441,7 @@ void SolveSpace::MenuAnalyze(int id) {
} }
case GraphicsWindow::MNU_VOLUME: { case GraphicsWindow::MNU_VOLUME: {
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->runningMesh); SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
double vol = 0; double vol = 0;
int i; int i;

View File

@ -654,7 +654,7 @@ void TextWindow::ShowConfiguration(void) {
Printf(false, "%Ba %2 %Fl%Ll%f%D[change]%E; now %d triangles", Printf(false, "%Ba %2 %Fl%Ll%f%D[change]%E; now %d triangles",
SS.chordTol, SS.chordTol,
&ScreenChangeChordTolerance, 0, &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, "%Ft max piecewise linear segments%E");
Printf(false, "%Ba %d %Fl%Ll%f[change]%E", Printf(false, "%Ba %d %Fl%Ll%f[change]%E",
SS.maxSegments, SS.maxSegments,

View File

@ -50,10 +50,12 @@ void SolveSpace::PushFromCurrentOnto(UndoStack *uk) {
ZERO(&(dest.poly)); ZERO(&(dest.poly));
ZERO(&(dest.bezierLoopSet)); ZERO(&(dest.bezierLoopSet));
ZERO(&(dest.polyError)); ZERO(&(dest.polyError));
ZERO(&(dest.thisMesh));
ZERO(&(dest.runningMesh)); ZERO(&(dest.runningMesh));
ZERO(&(dest.thisShell)); ZERO(&(dest.thisShell));
ZERO(&(dest.runningShell)); ZERO(&(dest.runningShell));
ZERO(&(dest.runningEdges)); ZERO(&(dest.displayMesh));
ZERO(&(dest.displayEdges));
ZERO(&(dest.remap)); ZERO(&(dest.remap));
src->remap.DeepCopyInto(&(dest.remap)); src->remap.DeepCopyInto(&(dest.remap));
@ -93,10 +95,12 @@ void SolveSpace::PopOntoCurrentFrom(UndoStack *uk) {
Group *g = &(SK.group.elem[i]); Group *g = &(SK.group.elem[i]);
g->poly.Clear(); g->poly.Clear();
g->bezierLoopSet.Clear(); g->bezierLoopSet.Clear();
g->thisMesh.Clear();
g->runningMesh.Clear(); g->runningMesh.Clear();
g->thisShell.Clear(); g->thisShell.Clear();
g->runningShell.Clear(); g->runningShell.Clear();
g->runningEdges.Clear(); g->displayMesh.Clear();
g->displayEdges.Clear();
g->remap.Clear(); g->remap.Clear();
g->impMesh.Clear(); g->impMesh.Clear();
g->impShell.Clear(); g->impShell.Clear();