Add ability to represent our surfaces as either a shell or a mesh,
according to the user's preference. I templated the housekeeping stuff for Boolean operations and step and repeat, so it's relatively clean. Still need to add the stuff to make a mesh vertex-to-vertex, and to export sections of a mesh. [git-p4: depot-paths = "//depot/solvespace/": change = 1959]
This commit is contained in:
parent
03ecbad981
commit
ddbd0ff77b
2
draw.cpp
2
draw.cpp
|
@ -1026,7 +1026,7 @@ void GraphicsWindow::Paint(int w, int h) {
|
||||||
// And the naked edges, if the user did Analyze -> Show Naked Edges.
|
// And the naked edges, if the user did Analyze -> Show Naked Edges.
|
||||||
glLineWidth(7);
|
glLineWidth(7);
|
||||||
glColor3d(1, 0, 0);
|
glColor3d(1, 0, 0);
|
||||||
glxDrawEdges(&(SS.nakedEdges));
|
glxDrawEdges(&(SS.nakedEdges), true);
|
||||||
|
|
||||||
// Then redraw whatever the mouse is hovering over, highlighted.
|
// Then redraw whatever the mouse is hovering over, highlighted.
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
|
@ -7,7 +7,7 @@ void SolveSpace::ExportSectionTo(char *filename) {
|
||||||
|
|
||||||
Group *g = SK.GetGroup(SS.GW.activeGroup);
|
Group *g = SK.GetGroup(SS.GW.activeGroup);
|
||||||
g->GenerateDisplayItems();
|
g->GenerateDisplayItems();
|
||||||
if(g->displayMesh.l.n == 0) {
|
if(g->displayMesh.IsEmpty()) {
|
||||||
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;
|
||||||
|
@ -100,7 +100,7 @@ void SolveSpace::ExportViewTo(char *filename) {
|
||||||
g->GenerateDisplayItems();
|
g->GenerateDisplayItems();
|
||||||
sm = &(g->displayMesh);
|
sm = &(g->displayMesh);
|
||||||
}
|
}
|
||||||
if(sm->l.n == 0) {
|
if(sm->IsEmpty()) {
|
||||||
sm = NULL;
|
sm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,7 +979,7 @@ void HpglFileWriter::FinishAndCloseFile(void) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void SolveSpace::ExportMeshTo(char *filename) {
|
void SolveSpace::ExportMeshTo(char *filename) {
|
||||||
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
|
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
|
||||||
if(m->l.n == 0) {
|
if(m->IsEmpty()) {
|
||||||
Error("Active group mesh is empty; nothing to export.");
|
Error("Active group mesh is empty; nothing to export.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
17
glhelper.cpp
17
glhelper.cpp
|
@ -293,7 +293,7 @@ void glxDebugPolygon(SPolygon *p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void glxDrawEdges(SEdgeList *el)
|
void glxDrawEdges(SEdgeList *el, bool endpointsToo)
|
||||||
{
|
{
|
||||||
SEdge *se;
|
SEdge *se;
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
|
@ -302,13 +302,16 @@ void glxDrawEdges(SEdgeList *el)
|
||||||
glxVertex3v(se->b);
|
glxVertex3v(se->b);
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
glPointSize(12);
|
|
||||||
glBegin(GL_POINTS);
|
if(endpointsToo) {
|
||||||
for(se = el->l.First(); se; se = el->l.NextAfter(se)) {
|
glPointSize(12);
|
||||||
glxVertex3v(se->a);
|
glBegin(GL_POINTS);
|
||||||
glxVertex3v(se->b);
|
for(se = el->l.First(); se; se = el->l.NextAfter(se)) {
|
||||||
|
glxVertex3v(se->a);
|
||||||
|
glxVertex3v(se->b);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
}
|
}
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void glxDebugMesh(SMesh *m)
|
void glxDebugMesh(SMesh *m)
|
||||||
|
|
188
groupmesh.cpp
188
groupmesh.cpp
|
@ -51,15 +51,35 @@ void Group::GenerateLoops(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::GenerateShellForStepAndRepeat(void) {
|
void SShell::RemapFaces(Group *g, int remap) {
|
||||||
Group *src = SK.GetGroup(opA);
|
SSurface *ss;
|
||||||
SShell *srcs = &(src->thisShell); // the shell to step and repeat
|
for(ss = surface.First(); ss; ss = surface.NextAfter(ss)){
|
||||||
|
hEntity face = { ss->face };
|
||||||
|
if(face.v == Entity::NO_ENTITY.v) continue;
|
||||||
|
|
||||||
SShell workA, workB;
|
face = g->Remap(face, remap);
|
||||||
|
ss->face = face.v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMesh::RemapFaces(Group *g, int remap) {
|
||||||
|
STriangle *tr;
|
||||||
|
for(tr = l.First(); tr; tr = l.NextAfter(tr)) {
|
||||||
|
hEntity face = { tr->meta.face };
|
||||||
|
if(face.v == Entity::NO_ENTITY.v) continue;
|
||||||
|
|
||||||
|
face = g->Remap(face, remap);
|
||||||
|
tr->meta.face = face.v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Group::GenerateForStepAndRepeat(T *prevs, T *steps, T *outs, int how) {
|
||||||
|
T workA, workB;
|
||||||
ZERO(&workA);
|
ZERO(&workA);
|
||||||
ZERO(&workB);
|
ZERO(&workB);
|
||||||
SShell *soFar = &workA, *scratch = &workB;
|
T *soFar = &workA, *scratch = &workB;
|
||||||
soFar->MakeFromCopyOf(&(src->PreviousGroup()->runningShell));
|
soFar->MakeFromCopyOf(prevs);
|
||||||
|
|
||||||
int n = (int)valA, a0 = 0;
|
int n = (int)valA, a0 = 0;
|
||||||
if(subtype == ONE_SIDED && skipFirst) {
|
if(subtype == ONE_SIDED && skipFirst) {
|
||||||
|
@ -70,13 +90,12 @@ void Group::GenerateShellForStepAndRepeat(void) {
|
||||||
int ap = a*2 - (subtype == ONE_SIDED ? 0 : (n-1));
|
int ap = a*2 - (subtype == ONE_SIDED ? 0 : (n-1));
|
||||||
int remap = (a == (n - 1)) ? REMAP_LAST : a;
|
int remap = (a == (n - 1)) ? REMAP_LAST : a;
|
||||||
|
|
||||||
SShell transd;
|
T transd;
|
||||||
ZERO(&transd);
|
ZERO(&transd);
|
||||||
if(type == TRANSLATE) {
|
if(type == TRANSLATE) {
|
||||||
Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
|
Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
|
||||||
trans = trans.ScaledBy(ap);
|
trans = trans.ScaledBy(ap);
|
||||||
Quaternion q = Quaternion::From(1, 0, 0, 0);
|
transd.MakeFromTransformationOf(steps, trans, Quaternion::IDENTITY);
|
||||||
transd.MakeFromTransformationOf(srcs, trans, q);
|
|
||||||
} else {
|
} else {
|
||||||
Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
|
Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
|
||||||
double theta = ap * SK.GetParam(h.param(3))->val;
|
double theta = ap * SK.GetParam(h.param(3))->val;
|
||||||
|
@ -84,43 +103,88 @@ void Group::GenerateShellForStepAndRepeat(void) {
|
||||||
Vector axis = Vector::From(h.param(4), h.param(5), h.param(6));
|
Vector axis = Vector::From(h.param(4), h.param(5), h.param(6));
|
||||||
Quaternion q = Quaternion::From(c, s*axis.x, s*axis.y, s*axis.z);
|
Quaternion q = Quaternion::From(c, s*axis.x, s*axis.y, s*axis.z);
|
||||||
// Rotation is centered at t; so A(x - t) + t = Ax + (t - At)
|
// Rotation is centered at t; so A(x - t) + t = Ax + (t - At)
|
||||||
transd.MakeFromTransformationOf(srcs,
|
transd.MakeFromTransformationOf(steps,
|
||||||
trans.Minus(q.Rotate(trans)), q);
|
trans.Minus(q.Rotate(trans)), q);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to rewrite any plane face entities to the transformed ones.
|
// We need to rewrite any plane face entities to the transformed ones.
|
||||||
SSurface *ss;
|
transd.RemapFaces(this, remap);
|
||||||
for(ss = transd.surface.First(); ss; ss = transd.surface.NextAfter(ss)){
|
|
||||||
hEntity face = { ss->face };
|
|
||||||
if(face.v == Entity::NO_ENTITY.v) continue;
|
|
||||||
|
|
||||||
face = Remap(face, remap);
|
if(how == COMBINE_AS_DIFFERENCE) {
|
||||||
ss->face = face.v;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(src->meshCombine == COMBINE_AS_DIFFERENCE) {
|
|
||||||
scratch->MakeFromDifferenceOf(soFar, &transd);
|
scratch->MakeFromDifferenceOf(soFar, &transd);
|
||||||
} else if(src->meshCombine == COMBINE_AS_UNION) {
|
} else if(how == COMBINE_AS_UNION) {
|
||||||
scratch->MakeFromUnionOf(soFar, &transd);
|
scratch->MakeFromUnionOf(soFar, &transd);
|
||||||
} else {
|
} else {
|
||||||
scratch->MakeFromAssemblyOf(soFar, &transd);
|
scratch->MakeFromAssemblyOf(soFar, &transd);
|
||||||
}
|
}
|
||||||
SWAP(SShell *, scratch, soFar);
|
SWAP(T *, scratch, soFar);
|
||||||
|
|
||||||
scratch->Clear();
|
scratch->Clear();
|
||||||
transd.Clear();
|
transd.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
runningShell.Clear();
|
outs->Clear();
|
||||||
runningShell = *soFar;
|
*outs = *soFar;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Group::GenerateForBoolean(T *prevs, T *thiss, T *outs) {
|
||||||
|
// If this group contributes no new mesh, then our running mesh is the
|
||||||
|
// same as last time, no combining required. Likewise if we have a mesh
|
||||||
|
// but it's suppressed.
|
||||||
|
if(thiss->IsEmpty() || suppress) {
|
||||||
|
outs->MakeFromCopyOf(prevs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// So our group's shell appears in thisShell. Combine this with the
|
||||||
|
// previous group's shell, using the requested operation.
|
||||||
|
if(meshCombine == COMBINE_AS_UNION) {
|
||||||
|
outs->MakeFromUnionOf(prevs, thiss);
|
||||||
|
} else if(meshCombine == COMBINE_AS_DIFFERENCE) {
|
||||||
|
outs->MakeFromDifferenceOf(prevs, thiss);
|
||||||
|
} else {
|
||||||
|
outs->MakeFromAssemblyOf(prevs, thiss);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::GenerateShellAndMesh(void) {
|
void Group::GenerateShellAndMesh(void) {
|
||||||
thisShell.Clear();
|
thisShell.Clear();
|
||||||
|
thisMesh.Clear();
|
||||||
|
runningShell.Clear();
|
||||||
|
runningMesh.Clear();
|
||||||
|
|
||||||
if(type == TRANSLATE || type == ROTATE) {
|
if(type == TRANSLATE || type == ROTATE) {
|
||||||
GenerateShellForStepAndRepeat();
|
Group *src = SK.GetGroup(opA);
|
||||||
goto done;
|
Group *pg = src->PreviousGroup();
|
||||||
|
|
||||||
|
if(src->thisMesh.IsEmpty() && pg->runningMesh.IsEmpty() && !forceToMesh)
|
||||||
|
{
|
||||||
|
SShell *toStep = &(src->thisShell),
|
||||||
|
*prev = &(pg->runningShell);
|
||||||
|
|
||||||
|
GenerateForStepAndRepeat<SShell>
|
||||||
|
(prev, toStep, &runningShell, src->meshCombine);
|
||||||
|
} else {
|
||||||
|
SMesh prevm, stepm;
|
||||||
|
ZERO(&prevm);
|
||||||
|
ZERO(&stepm);
|
||||||
|
|
||||||
|
prevm.MakeFromCopyOf(&(pg->runningMesh));
|
||||||
|
pg->runningShell.TriangulateInto(&prevm);
|
||||||
|
|
||||||
|
stepm.MakeFromCopyOf(&(src->thisMesh));
|
||||||
|
src->thisShell.TriangulateInto(&stepm);
|
||||||
|
|
||||||
|
GenerateForStepAndRepeat<SMesh>
|
||||||
|
(&prevm, &stepm, &runningMesh, src->meshCombine);
|
||||||
|
|
||||||
|
stepm.Clear();
|
||||||
|
prevm.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
displayDirty = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == EXTRUDE) {
|
if(type == EXTRUDE) {
|
||||||
|
@ -205,51 +269,38 @@ void Group::GenerateShellAndMesh(void) {
|
||||||
SK.GetParam(h.param(5))->val,
|
SK.GetParam(h.param(5))->val,
|
||||||
SK.GetParam(h.param(6))->val };
|
SK.GetParam(h.param(6))->val };
|
||||||
|
|
||||||
for(int i = 0; i < impMesh.l.n; i++) {
|
thisMesh.MakeFromTransformationOf(&impMesh, offset, q);
|
||||||
STriangle st = impMesh.l.elem[i];
|
thisMesh.RemapFaces(this, 0);
|
||||||
|
|
||||||
if(st.meta.face != 0) {
|
|
||||||
hEntity he = { st.meta.face };
|
|
||||||
st.meta.face = Remap(he, 0).v;
|
|
||||||
}
|
|
||||||
st.a = q.Rotate(st.a).Plus(offset);
|
|
||||||
st.b = q.Rotate(st.b).Plus(offset);
|
|
||||||
st.c = q.Rotate(st.c).Plus(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
thisShell.MakeFromTransformationOf(&impShell, offset, q);
|
thisShell.MakeFromTransformationOf(&impShell, offset, q);
|
||||||
SSurface *srf;
|
thisShell.RemapFaces(this, 0);
|
||||||
IdList<SSurface,hSSurface> *sl = &(thisShell.surface);
|
|
||||||
for(srf = sl->First(); srf; srf = sl->NextAfter(srf)) {
|
|
||||||
if(srf->face != 0) {
|
|
||||||
hEntity he = { srf->face };
|
|
||||||
srf->face = Remap(he, 0).v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runningShell.Clear();
|
// So now we've got the mesh or shell for this group. Combine it with
|
||||||
|
// the previous group's mesh or shell with the requested Boolean, and
|
||||||
|
// we're done.
|
||||||
|
|
||||||
// If this group contributes no new mesh, then our running mesh is the
|
Group *pg = PreviousGroup();
|
||||||
// same as last time, no combining required. Likewise if we have a mesh
|
if(pg->runningMesh.IsEmpty() && thisMesh.IsEmpty() && !forceToMesh) {
|
||||||
// but it's suppressed.
|
SShell *prevs = &(pg->runningShell);
|
||||||
if(suppress) {
|
GenerateForBoolean<SShell>(prevs, &thisShell, &runningShell);
|
||||||
runningShell.MakeFromCopyOf(&(PreviousGroup()->runningShell));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
// So our group's shell appears in thisShell. Combine this with the
|
|
||||||
// previous group's shell, using the requested operation.
|
|
||||||
SShell *a = &(PreviousGroup()->runningShell);
|
|
||||||
if(meshCombine == COMBINE_AS_UNION) {
|
|
||||||
runningShell.MakeFromUnionOf(a, &thisShell);
|
|
||||||
} else if(meshCombine == COMBINE_AS_DIFFERENCE) {
|
|
||||||
runningShell.MakeFromDifferenceOf(a, &thisShell);
|
|
||||||
} else {
|
} else {
|
||||||
runningShell.MakeFromAssemblyOf(a, &thisShell);
|
SMesh prevm, thism;
|
||||||
|
ZERO(&prevm);
|
||||||
|
ZERO(&thism);
|
||||||
|
|
||||||
|
prevm.MakeFromCopyOf(&(pg->runningMesh));
|
||||||
|
pg->runningShell.TriangulateInto(&prevm);
|
||||||
|
|
||||||
|
thism.MakeFromCopyOf(&thisMesh);
|
||||||
|
thisShell.TriangulateInto(&thism);
|
||||||
|
|
||||||
|
GenerateForBoolean<SMesh>(&prevm, &thism, &runningMesh);
|
||||||
|
|
||||||
|
thism.Clear();
|
||||||
|
prevm.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
displayDirty = true;
|
displayDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,8 +308,19 @@ void Group::GenerateDisplayItems(void) {
|
||||||
if(displayDirty) {
|
if(displayDirty) {
|
||||||
displayMesh.Clear();
|
displayMesh.Clear();
|
||||||
runningShell.TriangulateInto(&displayMesh);
|
runningShell.TriangulateInto(&displayMesh);
|
||||||
|
STriangle *tr;
|
||||||
|
for(tr = runningMesh.l.First(); tr; tr = runningMesh.l.NextAfter(tr)) {
|
||||||
|
STriangle trn = *tr;
|
||||||
|
Vector n = trn.Normal();
|
||||||
|
trn.an = n;
|
||||||
|
trn.bn = n;
|
||||||
|
trn.cn = n;
|
||||||
|
displayMesh.AddTriangle(&trn);
|
||||||
|
}
|
||||||
|
|
||||||
displayEdges.Clear();
|
displayEdges.Clear();
|
||||||
runningShell.MakeEdgesInto(&displayEdges);
|
runningShell.MakeEdgesInto(&displayEdges);
|
||||||
|
|
||||||
displayDirty = false;
|
displayDirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,7 +376,7 @@ 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(&displayEdges);
|
glxDrawEdges(&displayEdges, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SS.GW.showMesh) glxDebugMesh(&displayMesh);
|
if(SS.GW.showMesh) glxDebugMesh(&displayMesh);
|
||||||
|
|
53
mesh.cpp
53
mesh.cpp
|
@ -206,7 +206,7 @@ void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMesh::MakeFromUnion(SMesh *a, SMesh *b) {
|
void SMesh::MakeFromUnionOf(SMesh *a, SMesh *b) {
|
||||||
SBsp3 *bspa = SBsp3::FromMesh(a);
|
SBsp3 *bspa = SBsp3::FromMesh(a);
|
||||||
SBsp3 *bspb = SBsp3::FromMesh(b);
|
SBsp3 *bspb = SBsp3::FromMesh(b);
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ void SMesh::MakeFromUnion(SMesh *a, SMesh *b) {
|
||||||
AddAgainstBsp(a, bspb);
|
AddAgainstBsp(a, bspb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
void SMesh::MakeFromDifferenceOf(SMesh *a, SMesh *b) {
|
||||||
SBsp3 *bspa = SBsp3::FromMesh(a);
|
SBsp3 *bspa = SBsp3::FromMesh(a);
|
||||||
SBsp3 *bspb = SBsp3::FromMesh(b);
|
SBsp3 *bspb = SBsp3::FromMesh(b);
|
||||||
|
|
||||||
|
@ -232,40 +232,33 @@ void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
||||||
AddAgainstBsp(a, bspb);
|
AddAgainstBsp(a, bspb);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SMesh::MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *error) {
|
void SMesh::MakeFromCopyOf(SMesh *a) {
|
||||||
SBsp3 *bspa = SBsp3::FromMesh(srca);
|
|
||||||
SBsp3 *bspb = SBsp3::FromMesh(srcb);
|
|
||||||
|
|
||||||
error->Clear();
|
|
||||||
error->flipNormal = true;
|
|
||||||
error->keepCoplanar = false;
|
|
||||||
|
|
||||||
error->AddAgainstBsp(srcb, bspa);
|
|
||||||
error->AddAgainstBsp(srca, bspb);
|
|
||||||
// Now we have a list of all the triangles (or fragments thereof) from
|
|
||||||
// A that lie inside B, or vice versa. That's the interference, and
|
|
||||||
// we report it so that it can be flagged.
|
|
||||||
|
|
||||||
// For the actual output, take the union.
|
|
||||||
flipNormal = false;
|
|
||||||
keepCoplanar = false;
|
|
||||||
AddAgainstBsp(srcb, bspa);
|
|
||||||
|
|
||||||
flipNormal = false;
|
|
||||||
keepCoplanar = true;
|
|
||||||
AddAgainstBsp(srca, bspb);
|
|
||||||
|
|
||||||
// And we're successful if the intersection was empty.
|
|
||||||
return (error->l.n == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SMesh::MakeFromCopy(SMesh *a) {
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < a->l.n; i++) {
|
for(i = 0; i < a->l.n; i++) {
|
||||||
AddTriangle(&(a->l.elem[i]));
|
AddTriangle(&(a->l.elem[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMesh::MakeFromAssemblyOf(SMesh *a, SMesh *b) {
|
||||||
|
MakeFromCopyOf(a);
|
||||||
|
MakeFromCopyOf(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMesh::MakeFromTransformationOf(SMesh *a, Vector trans, Quaternion q) {
|
||||||
|
STriangle *tr;
|
||||||
|
for(tr = a->l.First(); tr; tr = a->l.NextAfter(tr)) {
|
||||||
|
STriangle tt = *tr;
|
||||||
|
tt.a = (q.Rotate(tt.a)).Plus(trans);
|
||||||
|
tt.b = (q.Rotate(tt.b)).Plus(trans);
|
||||||
|
tt.c = (q.Rotate(tt.c)).Plus(trans);
|
||||||
|
AddTriangle(&tt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SMesh::IsEmpty(void) {
|
||||||
|
return (l.n == 0);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD SMesh::FirstIntersectionWith(Point2d mp) {
|
DWORD SMesh::FirstIntersectionWith(Point2d mp) {
|
||||||
Vector p0 = Vector::From(mp.x, mp.y, 0);
|
Vector p0 = Vector::From(mp.x, mp.y, 0);
|
||||||
Vector gn = Vector::From(0, 0, 1);
|
Vector gn = Vector::From(0, 0, 1);
|
||||||
|
|
13
polygon.h
13
polygon.h
|
@ -184,10 +184,15 @@ public:
|
||||||
void Simplify(int start);
|
void Simplify(int start);
|
||||||
|
|
||||||
void AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3);
|
void AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3);
|
||||||
void MakeFromUnion(SMesh *a, SMesh *b);
|
void MakeFromUnionOf(SMesh *a, SMesh *b);
|
||||||
void MakeFromDifference(SMesh *a, SMesh *b);
|
void MakeFromDifferenceOf(SMesh *a, SMesh *b);
|
||||||
bool MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *errorAt);
|
|
||||||
void MakeFromCopy(SMesh *a);
|
void MakeFromCopyOf(SMesh *a);
|
||||||
|
void MakeFromTransformationOf(SMesh *a, Vector trans, Quaternion q);
|
||||||
|
void MakeFromAssemblyOf(SMesh *a, SMesh *b);
|
||||||
|
|
||||||
|
bool IsEmpty(void);
|
||||||
|
void RemapFaces(Group *g, int remap);
|
||||||
|
|
||||||
DWORD FirstIntersectionWith(Point2d mp);
|
DWORD FirstIntersectionWith(Point2d mp);
|
||||||
};
|
};
|
||||||
|
|
3
sketch.h
3
sketch.h
|
@ -208,9 +208,10 @@ public:
|
||||||
void GenerateLoops(void);
|
void GenerateLoops(void);
|
||||||
// And the mesh stuff
|
// And the mesh stuff
|
||||||
Group *PreviousGroup(void);
|
Group *PreviousGroup(void);
|
||||||
void GenerateShellForStepAndRepeat(void);
|
|
||||||
void GenerateDisplayItems(void);
|
void GenerateDisplayItems(void);
|
||||||
void GenerateShellAndMesh(void);
|
void GenerateShellAndMesh(void);
|
||||||
|
template<class T> void GenerateForStepAndRepeat(T *a, T *b, T *o, int how);
|
||||||
|
template<class T> void GenerateForBoolean(T *a, T *b, T *o);
|
||||||
void Draw(void);
|
void Draw(void);
|
||||||
|
|
||||||
SPolygon GetPolygon(void);
|
SPolygon GetPolygon(void);
|
||||||
|
|
|
@ -149,7 +149,7 @@ void vl(void); // debug function to validate heaps
|
||||||
// End of platform-specific functions
|
// End of platform-specific functions
|
||||||
//================
|
//================
|
||||||
|
|
||||||
|
class Group;
|
||||||
class SSurface;
|
class SSurface;
|
||||||
#include "dsc.h"
|
#include "dsc.h"
|
||||||
#include "polygon.h"
|
#include "polygon.h"
|
||||||
|
@ -175,7 +175,7 @@ void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
|
||||||
void glxFillPolygon(SPolygon *p);
|
void glxFillPolygon(SPolygon *p);
|
||||||
void glxFillMesh(int color, SMesh *m, DWORD h, DWORD s1, DWORD s2);
|
void glxFillMesh(int color, SMesh *m, DWORD h, DWORD s1, DWORD s2);
|
||||||
void glxDebugPolygon(SPolygon *p);
|
void glxDebugPolygon(SPolygon *p);
|
||||||
void glxDrawEdges(SEdgeList *l);
|
void glxDrawEdges(SEdgeList *l, bool endpointsToo);
|
||||||
void glxDebugMesh(SMesh *m);
|
void glxDebugMesh(SMesh *m);
|
||||||
void glxMarkPolygonNormal(SPolygon *p);
|
void glxMarkPolygonNormal(SPolygon *p);
|
||||||
void glxWriteText(char *str);
|
void glxWriteText(char *str);
|
||||||
|
|
|
@ -666,6 +666,10 @@ void SShell::TriangulateInto(SMesh *sm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SShell::IsEmpty(void) {
|
||||||
|
return (surface.n == 0);
|
||||||
|
}
|
||||||
|
|
||||||
void SShell::Clear(void) {
|
void SShell::Clear(void) {
|
||||||
SSurface *s;
|
SSurface *s;
|
||||||
for(s = surface.First(); s; s = surface.NextAfter(s)) {
|
for(s = surface.First(); s; s = surface.NextAfter(s)) {
|
||||||
|
|
|
@ -319,6 +319,8 @@ public:
|
||||||
void MakeEdgesInto(SEdgeList *sel);
|
void MakeEdgesInto(SEdgeList *sel);
|
||||||
void MakeSectionEdgesInto(Vector n, double d,
|
void MakeSectionEdgesInto(Vector n, double d,
|
||||||
SEdgeList *sel, SBezierList *sbl);
|
SEdgeList *sel, SBezierList *sbl);
|
||||||
|
bool IsEmpty(void);
|
||||||
|
void RemapFaces(Group *g, int remap);
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ void TextWindow::ShowGroupInfo(void) {
|
||||||
g->runningShell.surface.n > 0))
|
g->runningShell.surface.n > 0))
|
||||||
{
|
{
|
||||||
Group *pg = g->PreviousGroup();
|
Group *pg = g->PreviousGroup();
|
||||||
if(pg->runningMesh.l.n == 0 && g->thisMesh.l.n == 0) {
|
if(pg->runningMesh.IsEmpty() && g->thisMesh.IsEmpty()) {
|
||||||
bool fm = g->forceToMesh;
|
bool fm = g->forceToMesh;
|
||||||
Printf(true,
|
Printf(true,
|
||||||
"%FtSURFACES%E %Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
|
"%FtSURFACES%E %Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
|
||||||
|
@ -473,7 +473,7 @@ void TextWindow::ShowGroupInfo(void) {
|
||||||
(fm ? "" : "as mesh"), (fm ? "as mesh" : ""));
|
(fm ? "" : "as mesh"), (fm ? "as mesh" : ""));
|
||||||
} else {
|
} else {
|
||||||
Printf(false,
|
Printf(false,
|
||||||
"%FtSURFACES%E %Fas mesh%FE");
|
"%FtSURFACES%E %Fsas mesh%E");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user