diff --git a/constraint.cpp b/constraint.cpp
index 48ae3c4..f073d02 100644
--- a/constraint.cpp
+++ b/constraint.cpp
@@ -276,7 +276,7 @@ void Constraint::MenuConstrain(int id) {
break;
case GraphicsWindow::MNU_SOLVE_NOW:
- SS.GenerateAll(true);
+ SS.GenerateAll(true, 0, 10000);
return;
case GraphicsWindow::MNU_SOLVE_AUTO:
diff --git a/drawconstraint.cpp b/drawconstraint.cpp
index 25646f9..9881e47 100644
--- a/drawconstraint.cpp
+++ b/drawconstraint.cpp
@@ -83,7 +83,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
Vector gu = SS.GW.projUp.ScaledBy(1/SS.GW.scale);
Vector gn = (gr.Cross(gu)).WithMagnitude(1/SS.GW.scale);
- glxColor3d(1, 0.2, 1);
+ glxColor3d(1, 0.4, 1);
switch(type) {
case PT_PT_DISTANCE: {
Vector ap = SS.GetEntity(ptA)->PointGetNum();
diff --git a/file.cpp b/file.cpp
index e4b5c4d..866ae7f 100644
--- a/file.cpp
+++ b/file.cpp
@@ -51,6 +51,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
{ 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) },
{ 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) },
+ { 'g', "Group.meshCombine", 'd', &(SS.sv.g.meshCombine) },
{ 'g', "Group.wrkpl.q.w", 'f', &(SS.sv.g.wrkpl.q.w) },
{ 'g', "Group.wrkpl.q.vx", 'f', &(SS.sv.g.wrkpl.q.vx) },
{ 'g', "Group.wrkpl.q.vy", 'f', &(SS.sv.g.wrkpl.q.vy) },
diff --git a/graphicswin.cpp b/graphicswin.cpp
index 9f70f1b..cb3ec77 100644
--- a/graphicswin.cpp
+++ b/graphicswin.cpp
@@ -102,12 +102,19 @@ void GraphicsWindow::Init(void) {
projRight.x = 1; projRight.y = projRight.z = 0;
projUp.y = 1; projUp.z = projUp.x = 0;
- EnsureValidActives();
-
// Start locked on to the XY plane.
hRequest r = Request::HREQUEST_REFERENCE_XY;
activeWorkplane = r.entity(0);
+ // And with the latest visible group active
+ int i;
+ for(i = 0; i < SS.group.n; i++) {
+ Group *g = &(SS.group.elem[i]);
+ if(g->visible) activeGroup = g->h;
+ }
+
+ EnsureValidActives();
+
showWorkplanes = true;
showNormals = true;
showPoints = true;
@@ -1144,11 +1151,10 @@ void GraphicsWindow::Paint(int w, int h) {
glxUnlockColor();
int i, a;
- // Draw the groups; this fills the polygons, if requested.
+ // Draw the groups; this fills the polygons in a drawing group, and
+ // draws the solid mesh.
if(showSolids) {
- for(i = 0; i < SS.group.n; i++) {
- SS.group.elem[i].Draw();
- }
+ (SS.GetGroup(activeGroup))->Draw();
}
// First, draw the entire scene. We don't necessarily want to draw
@@ -1180,35 +1186,5 @@ void GraphicsWindow::Paint(int w, int h) {
for(i = 0; i < MAX_SELECTED; i++) {
selection[i].Draw();
}
-
- if(SS.group.n >= 5) {
- SMesh *ma = &(SS.group.elem[2].mesh);
- SMesh *mb = &(SS.group.elem[4].mesh);
-
- SBsp3 *pa = SBsp3::FromMesh(ma);
- SBsp3 *pb = SBsp3::FromMesh(mb);
-
- SMesh br; ZERO(&br);
- br.flipNormal = true;
- br.keepCoplanar = false;
- br.AddAgainstBsp(mb, pa);
-
- br.flipNormal = false;
- br.keepCoplanar = false;
- br.AddAgainstBsp(ma, pb);
-
- dbp("triangles in = %d %d out = %d", ma->l.n, mb->l.n, br.l.n);
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_LIGHTING);
- glxFillMesh(&br);
- glDisable(GL_LIGHTING);
- glxLockColorTo(0, 1, 0);
- glEnable(GL_DEPTH_TEST);
- glxDebugMesh(&br);
-
- br.Clear();
- FreeAllTemporary();
- }
}
diff --git a/mesh.cpp b/mesh.cpp
index d92e671..ea25549 100644
--- a/mesh.cpp
+++ b/mesh.cpp
@@ -51,6 +51,7 @@ void SMesh::GetBounding(Vector *vmax, Vector *vmin) {
void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) {
int i;
+
for(i = 0; i < srcm->l.n; i++) {
STriangle *st = &(srcm->l.elem[i]);
int pn = l.n;
@@ -68,6 +69,32 @@ void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) {
}
}
+void SMesh::MakeFromUnion(SMesh *a, SMesh *b) {
+ SBsp3 *bspa = SBsp3::FromMesh(a);
+ SBsp3 *bspb = SBsp3::FromMesh(b);
+
+ flipNormal = false;
+ keepCoplanar = false;
+ AddAgainstBsp(b, bspa);
+
+ flipNormal = false;
+ keepCoplanar = true;
+ AddAgainstBsp(a, bspb);
+}
+
+void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
+ SBsp3 *bspa = SBsp3::FromMesh(a);
+ SBsp3 *bspb = SBsp3::FromMesh(b);
+
+ flipNormal = true;
+ keepCoplanar = false;
+ AddAgainstBsp(b, bspa);
+
+ flipNormal = false;
+ keepCoplanar = false;
+ AddAgainstBsp(a, bspb);
+}
+
SBsp2 *SBsp2::Alloc(void) { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); }
SBsp3 *SBsp3::Alloc(void) { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); }
@@ -153,7 +180,6 @@ alt:
} else {
// I suppose this actually is allowed to happen, if the coplanar
// face is the leaf, and all of its neighbors are earlier in tree?
- dbp("insert in plane");
InsertInPlane(false, tr, instead);
}
} else {
diff --git a/polygon.h b/polygon.h
index 280bee3..f6f0c27 100644
--- a/polygon.h
+++ b/polygon.h
@@ -178,6 +178,8 @@ public:
void GetBounding(Vector *vmax, Vector *vmin);
void AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3);
+ void MakeFromUnion(SMesh *a, SMesh *b);
+ void MakeFromDifference(SMesh *a, SMesh *b);
};
#endif
diff --git a/sketch.cpp b/sketch.cpp
index edb8832..30770d6 100644
--- a/sketch.cpp
+++ b/sketch.cpp
@@ -381,15 +381,27 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
SS.entity.Add(&en);
}
-void Group::MakePolygons(void) {
+SMesh *Group::PreviousGroupMesh(void) {
int i;
+ for(i = 0; i < SS.group.n; i++) {
+ Group *g = &(SS.group.elem[i]);
+ if(g->h.v == h.v) break;
+ }
+ if(i == 0 || i >= SS.group.n) oops();
+ return &(SS.group.elem[i-1].mesh);
+}
+
+void Group::MakePolygons(void) {
poly.Clear();
- mesh.Clear();
SEdgeList edges;
ZERO(&edges);
+ SMesh outm;
+ ZERO(&outm);
- if(type == DRAWING_3D || type == DRAWING_WORKPLANE) {
+ if(type == DRAWING_3D || type == DRAWING_WORKPLANE ||
+ type == ROTATE || type == TRANSLATE)
+ {
int i;
for(i = 0; i < SS.entity.n; i++) {
Entity *e = &(SS.entity.elem[i]);
@@ -427,7 +439,6 @@ void Group::MakePolygons(void) {
SMesh srcm; ZERO(&srcm);
(src->poly).TriangulateInto(&srcm);
- SMesh outm; ZERO(&outm);
// Do the bottom; that has normal pointing opposite from translate
for(i = 0; i < srcm.l.n; i++) {
STriangle *st = &(srcm.l.elem[i]);
@@ -435,9 +446,9 @@ void Group::MakePolygons(void) {
bt = (st->b).Plus(tbot),
ct = (st->c).Plus(tbot);
if(flipBottom) {
- mesh.AddTriangle(ct, bt, at);
+ outm.AddTriangle(ct, bt, at);
} else {
- mesh.AddTriangle(at, bt, ct);
+ outm.AddTriangle(at, bt, ct);
}
}
// And the top; that has the normal pointing the same dir as translate
@@ -447,9 +458,9 @@ void Group::MakePolygons(void) {
bt = (st->b).Plus(ttop),
ct = (st->c).Plus(ttop);
if(flipBottom) {
- mesh.AddTriangle(at, bt, ct);
+ outm.AddTriangle(at, bt, ct);
} else {
- mesh.AddTriangle(ct, bt, at);
+ outm.AddTriangle(ct, bt, at);
}
}
srcm.Clear();
@@ -463,26 +474,50 @@ void Group::MakePolygons(void) {
Vector abot = (edge->a).Plus(tbot), bbot = (edge->b).Plus(tbot);
Vector atop = (edge->a).Plus(ttop), btop = (edge->b).Plus(ttop);
if(flipBottom) {
- mesh.AddTriangle(bbot, abot, atop);
- mesh.AddTriangle(bbot, atop, btop);
+ outm.AddTriangle(bbot, abot, atop);
+ outm.AddTriangle(bbot, atop, btop);
} else {
- mesh.AddTriangle(abot, bbot, atop);
- mesh.AddTriangle(bbot, btop, atop);
+ outm.AddTriangle(abot, bbot, atop);
+ outm.AddTriangle(bbot, btop, atop);
}
}
}
edges.Clear();
+
+ // So our group's mesh appears in outm. Combine this with the previous
+ // group's mesh, using the requested operation.
+ mesh.Clear();
+ SMesh *a = PreviousGroupMesh();
+ if(meshCombine == COMBINE_AS_UNION) {
+ mesh.MakeFromUnion(a, &outm);
+ } else {
+ mesh.MakeFromDifference(a, &outm);
+ }
+ outm.Clear();
}
void Group::Draw(void) {
- if(!visible) return;
+ // Show this even if the group is not visible. It's already possible
+ // to show or hide just this with the "show solids" flag.
-
- GLfloat mpf[] = { 0.4f, 0.4f, 0.4f, 1.0 };
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
+ if(type == DRAWING_3D || type == DRAWING_WORKPLANE) {
+ GLfloat mpf[] = { 0.1f, 0.1f, 0.1f, 1.0 };
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
+ } else {
+ GLfloat mpf[] = { 0.3f, 0.3f, 0.3f, 1.0 };
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
+ }
+ // The back faces are drawn in red; should never seem them, since we
+ // draw closed shells, so that's a debugging aid.
GLfloat mpb[] = { 1.0f, 0.1f, 0.1f, 1.0 };
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb);
+ glEnable(GL_LIGHTING);
+ glxFillMesh(&mesh);
+ glDisable(GL_LIGHTING);
+
+// glxDebugMesh(&mesh);
+
if(polyError.yes) {
glxColor4d(1, 0, 0, 0.2);
glLineWidth(10);
@@ -498,13 +533,11 @@ void Group::Draw(void) {
glxWriteText("not closed contour!");
glPopMatrix();
} else {
-// glxFillPolygon(&poly);
+ glxColor4d(0, 1.0, 1.0, 0.1);
+ glPolygonOffset(-1, -1);
+ glxFillPolygon(&poly);
+ glPolygonOffset(0, 0);
}
- glEnable(GL_LIGHTING);
-// glxFillMesh(&mesh);
- glDisable(GL_LIGHTING);
-
-// glxDebugMesh(&mesh);
}
hParam Request::AddParam(IdList *param, hParam hp) {
diff --git a/sketch.h b/sketch.h
index a032b9a..f1d894c 100644
--- a/sketch.h
+++ b/sketch.h
@@ -84,8 +84,6 @@ public:
static const int TRANSLATE = 5030;
int type;
- bool solved;
-
hGroup opA;
hGroup opB;
bool visible;
@@ -113,6 +111,10 @@ public:
} polyError;
SMesh mesh;
+ static const int COMBINE_AS_UNION = 0;
+ static const int COMBINE_AS_DIFFERENCE = 1;
+ int meshCombine;
+
NameStr name;
char *DescriptionString(void);
@@ -131,6 +133,7 @@ public:
void GenerateEquations(IdList *l);
+ SMesh *PreviousGroupMesh(void);
void MakePolygons(void);
void Draw(void);
diff --git a/solvespace.cpp b/solvespace.cpp
index fd5fcec..e362a3e 100644
--- a/solvespace.cpp
+++ b/solvespace.cpp
@@ -9,11 +9,11 @@ void SolveSpace::Init(char *cmdLine) {
LoadFromFile(cmdLine);
}
+ GenerateAll(false, 0, INT_MAX);
+
TW.Init();
GW.Init();
- GenerateAll(false);
-
TW.Show();
}
@@ -122,6 +122,21 @@ bool SolveSpace::PruneConstraints(hGroup hg) {
}
void SolveSpace::GenerateAll(bool andSolve) {
+ int i;
+ int firstShown = INT_MAX, lastShown = 0;
+ // The references don't count, so start from group 1
+ for(i = 1; i < group.n; i++) {
+ if(group.elem[i].visible) {
+ firstShown = min(firstShown, i);
+ lastShown = max(lastShown, i);
+ }
+ }
+ // Even if nothing is shown, we have to keep going; the entities get
+ // generated for hidden groups, even though they're not solved.
+ GenerateAll(andSolve, firstShown, lastShown);
+}
+
+void SolveSpace::GenerateAll(bool andSolve, int first, int last) {
int i, j;
while(PruneOrphans())
@@ -132,12 +147,6 @@ void SolveSpace::GenerateAll(bool andSolve) {
param.MoveSelfInto(&prev);
entity.Clear();
- for(i = 0; i < group.n; i++) {
- group.elem[i].solved = false;
- }
-
- // For now, solve the groups in given order; should discover the
- // correct order later.
for(i = 0; i < group.n; i++) {
Group *g = &(group.elem[i]);
@@ -172,13 +181,24 @@ void SolveSpace::GenerateAll(bool andSolve) {
if(g->h.v == Group::HGROUP_REFERENCES.v) {
ForceReferences();
- group.elem[0].solved = true;
} else {
- // Solve this group.
- if(andSolve) SolveGroup(g->h);
- }
+ if(i >= first && i <= last) {
+ // The group falls inside the range, so really solve it,
+ // and then regenerate the mesh based on the solved stuff.
+ if(andSolve) SolveGroup(g->h);
+ g->MakePolygons();
+ } else {
+ // The group falls outside the range, so just assume that
+ // it's good wherever we left it. The mesh is unchanged,
+ // and the parameters must be marked as known.
+ for(j = 0; j < param.n; j++) {
+ Param *newp = &(param.elem[j]);
- g->MakePolygons();
+ Param *prevp = prev.FindByIdNoOops(newp->h);
+ if(prevp) newp->known = true;
+ }
+ }
+ }
}
prev.Clear();
@@ -217,7 +237,7 @@ pruned:
param.Clear();
prev.MoveSelfInto(¶m);
// Try again
- GenerateAll(andSolve);
+ GenerateAll(andSolve, first, last);
}
void SolveSpace::ForceReferences(void) {
@@ -299,8 +319,8 @@ void SolveSpace::MenuFile(int id) {
case GraphicsWindow::MNU_NEW:
SS.NewFile();
SS.GenerateAll(false);
- SS.GW.Init();
SS.TW.Init();
+ SS.GW.Init();
SS.TW.Show();
break;
diff --git a/solvespace.h b/solvespace.h
index faefb90..b85e13c 100644
--- a/solvespace.h
+++ b/solvespace.h
@@ -229,6 +229,7 @@ public:
bool PruneConstraints(hGroup hg);
void GenerateAll(bool andSolve);
+ void GenerateAll(bool andSolve, int first, int last);
bool SolveGroup(hGroup hg);
void ForceReferences(void);
diff --git a/textwin.cpp b/textwin.cpp
index 66f254e..11e6181 100644
--- a/textwin.cpp
+++ b/textwin.cpp
@@ -266,6 +266,9 @@ void TextWindow::ScreenToggleGroupShown(int link, DWORD v) {
hGroup hg = { v };
Group *g = SS.GetGroup(hg);
g->visible = !(g->visible);
+ // If a group was just shown, then it might not have been generated
+ // previously, so regenerate.
+ SS.GW.GeneratePerSolving();
}
void TextWindow::ScreenShowGroupsSpecial(int link, DWORD v) {
int i;
@@ -341,9 +344,19 @@ void TextWindow::ScreenChangeExtrudeSides(int link, DWORD v) {
Group *g = SS.GetGroup(SS.TW.shown->group);
if(g->subtype == Group::EXTRUDE_ONE_SIDED) {
g->subtype = Group::EXTRUDE_TWO_SIDED;
- } else {
+ } else if(g->subtype == Group::EXTRUDE_TWO_SIDED) {
g->subtype = Group::EXTRUDE_ONE_SIDED;
- }
+ } else oops();
+ SS.GW.GeneratePerSolving();
+ SS.GW.ClearSuper();
+}
+void TextWindow::ScreenChangeMeshCombine(int link, DWORD v) {
+ Group *g = SS.GetGroup(SS.TW.shown->group);
+ if(g->meshCombine == Group::COMBINE_AS_DIFFERENCE) {
+ g->meshCombine = Group::COMBINE_AS_UNION;
+ } else if(g->meshCombine == Group::COMBINE_AS_UNION) {
+ g->meshCombine = Group::COMBINE_AS_DIFFERENCE;
+ } else oops();
SS.GW.GeneratePerSolving();
SS.GW.ClearSuper();
}
@@ -361,12 +374,18 @@ void TextWindow::ShowGroupInfo(void) {
if(g->type == Group::EXTRUDE) {
bool one = (g->subtype == Group::EXTRUDE_ONE_SIDED);
- Printf(true, "%FtEXTRUDE%E one-sided: %Fh%f%Ll%s%E%Fs%s%E",
+ Printf(true, "%FtEXTRUDE%E %Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
&TextWindow::ScreenChangeExtrudeSides,
- (one ? "" : "no"), (one ? "yes" : ""));
- Printf(false, " two-sided: %Fh%f%Ll%s%E%Fs%s%E",
+ (one ? "" : "one side"), (one ? "one-side" : ""),
&TextWindow::ScreenChangeExtrudeSides,
- (!one ? "" : "no"), (!one ? "yes" : ""));
+ (!one ? "" : "two sides"), (!one ? "two sides" : ""));
+
+ bool diff = (g->meshCombine == Group::COMBINE_AS_DIFFERENCE);
+ Printf(false, "%FtCOMBINE%E %Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
+ &TextWindow::ScreenChangeMeshCombine,
+ (!diff ? "" : "as union"), (!diff ? "as union" : ""),
+ &TextWindow::ScreenChangeMeshCombine,
+ (diff ? "" : "as difference"), (diff ? "as difference" : ""));
}
Printf(true, "%Ftrequests in group");
diff --git a/ui.h b/ui.h
index 79fd719..d1aeae6 100644
--- a/ui.h
+++ b/ui.h
@@ -74,6 +74,7 @@ public:
static void ScreenSelectRequest(int link, DWORD v);
static void ScreenSelectConstraint(int link, DWORD v);
static void ScreenChangeExtrudeSides(int link, DWORD v);
+ static void ScreenChangeMeshCombine(int link, DWORD v);
static void ScreenNavigation(int link, DWORD v);
};