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;