From 6245c63f2e1f555f153f1b4dc7c564d139ee5584 Mon Sep 17 00:00:00 2001 From: ruevs Date: Sun, 10 May 2020 03:35:53 +0300 Subject: [PATCH] Intersection boolen in triangle mesh mode is properly implemented In addition the union operation in tiangle mesh mode is changed to keep coplanar faces the same way as the NURBS union does. Finalizes: https://github.com/solvespace/solvespace/issues/35 --- src/bsp.cpp | 35 +++++++++++++++++++++++------------ src/mesh.cpp | 26 +++++++++++++------------- src/polygon.h | 1 + 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/bsp.cpp b/src/bsp.cpp index 9dcaace..bac5ff3 100644 --- a/src/bsp.cpp +++ b/src/bsp.cpp @@ -62,14 +62,17 @@ void SBsp3::InsertInPlane(bool pos2, STriangle *tr, SMesh *m) { ll = ll->more; } - if(m->flipNormal && ((!pos2 && !onFace) || - (onFace && !sameNormal && m->keepCoplanar))) - { - m->AddTriangle(tr->meta, tr->c, tr->b, tr->a); - } else if(!(m->flipNormal) && ((pos2 && !onFace) || - (onFace && sameNormal && m->keepCoplanar))) - { - m->AddTriangle(tr->meta, tr->a, tr->b, tr->c); + if((!onFace && ((m->keepInsideOtherShell && !pos2) || + (!m->keepInsideOtherShell && pos2))) || + (onFace && ((m->keepCoplanar && m->flipNormal && !sameNormal) || + (m->keepCoplanar && !m->flipNormal && sameNormal)))) { + // We have decided that we need to keep a triangle either inside, + // outside or on the other shell. So add it and flip it if requested. + if(!(m->flipNormal)) { + m->AddTriangle(tr->meta, tr->a, tr->b, tr->c); + } else { + m->AddTriangle(tr->meta, tr->c, tr->b, tr->a); + } } else { m->atLeastOneDiscarded = true; } @@ -101,10 +104,15 @@ void SBsp3::InsertHow(BspClass how, STriangle *tr, SMesh *instead) { return; alt: - if(how == BspClass::POS && !(instead->flipNormal)) { - instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c); - } else if(how == BspClass::NEG && instead->flipNormal) { - instead->AddTriangle(tr->meta, tr->c, tr->b, tr->a); + if(((BspClass::POS == how) && !instead->keepInsideOtherShell) || + ((BspClass::NEG == how) && instead->keepInsideOtherShell)) { + // We have decided that we need to keep a triangle (either inside or + // outside the other shell. So add it and flip it if requested. + if(!(instead->flipNormal)) { + instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c); + } else { + instead->AddTriangle(tr->meta, tr->c, tr->b, tr->a); + } } else if(how == BspClass::COPLANAR) { if(edges) { edges->InsertTriangle(tr, instead, this); @@ -431,6 +439,9 @@ SBsp3 *SBsp3::InsertConvex(STriMeta meta, Vector *vertex, size_t cnt, SMesh *ins SBsp3 *SBsp3::InsertOrCreate(SBsp3 *where, STriangle *tr, SMesh *instead) { if(where == NULL) { if(instead) { + // ruevs: I do not think this code is reachable, but in + // principle should we use instead->keepInsideOtherShell + // in place of instead->flipNormal ? if(instead->flipNormal) { instead->atLeastOneDiscarded = true; } else { diff --git a/src/mesh.cpp b/src/mesh.cpp index 0a8478a..1ef6c17 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -265,11 +265,12 @@ void SMesh::MakeFromUnionOf(SMesh *a, SMesh *b) { SBsp3 *bspb = SBsp3::FromMesh(b); flipNormal = false; - keepCoplanar = false; + keepInsideOtherShell = false; + + keepCoplanar = true; AddAgainstBsp(b, bspa); - flipNormal = false; - keepCoplanar = true; + keepCoplanar = false; AddAgainstBsp(a, bspb); } @@ -279,28 +280,27 @@ void SMesh::MakeFromDifferenceOf(SMesh *a, SMesh *b) { flipNormal = true; keepCoplanar = true; + keepInsideOtherShell = true; AddAgainstBsp(b, bspa); flipNormal = false; keepCoplanar = false; + keepInsideOtherShell = false; AddAgainstBsp(a, bspb); } void SMesh::MakeFromIntersectionOf(SMesh *a, SMesh *b) { - // Emulate triangle mesh intersection with difference - // by doing C=A-(A-B). Figure out how to do it properly later. - SMesh c = {}; - c.MakeFromDifferenceOf(a, b); - MakeFromDifferenceOf(a, &c); - - c.Clear(); - -/* SBsp3 *bspa = SBsp3::FromMesh(a); + SBsp3 *bspa = SBsp3::FromMesh(a); SBsp3 *bspb = SBsp3::FromMesh(b); + keepInsideOtherShell = true; + flipNormal = false; + + keepCoplanar = false; AddAgainstBsp(a, bspb); + + keepCoplanar = true; AddAgainstBsp(b, bspa); -*/ } void SMesh::MakeFromCopyOf(SMesh *a) { diff --git a/src/polygon.h b/src/polygon.h index a2afafe..66023eb 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -252,6 +252,7 @@ public: List l; bool flipNormal; + bool keepInsideOtherShell; bool keepCoplanar; bool atLeastOneDiscarded; bool isTransparent;