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]
solver
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
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;

View File

@ -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;

View File

@ -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]);

View File

@ -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);

View File

@ -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;

View File

@ -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<EntityMap,EntityId> 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);

View File

@ -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;

View File

@ -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,

View File

@ -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();