Resovle a huge performance regression introduced by commit ab10e38 while still fixing the NURBS issues resolved by that commit with only modest speed penalty. The performance is significantly improved by using bounding box tests on curves prior to doing complex intersection testing.

pull/766/head
phkahler 2020-10-21 16:30:55 -04:00
parent 0761339ec9
commit 0f1ece2b8e
2 changed files with 35 additions and 14 deletions

View File

@ -20,18 +20,36 @@ void SShell::MakeFromIntersectionOf(SShell *a, SShell *b) {
MakeFromBoolean(a, b, SSurface::CombineAs::INTERSECTION); MakeFromBoolean(a, b, SSurface::CombineAs::INTERSECTION);
} }
// We will be inserting existing verticies into curves to split them void SCurve::GetAxisAlignedBounding(Vector *ptMax, Vector *ptMin) const {
// todo: this is only using the ends of exact curves, and it is only *ptMax = {VERY_NEGATIVE, VERY_NEGATIVE, VERY_NEGATIVE};
// using them to split existing curves, not new intersections. *ptMin = {VERY_POSITIVE, VERY_POSITIVE, VERY_POSITIVE};
// It resolves some issues but we could do better. We will need to
// reorder things so the surface intersection curves exist prior to for(int i = 0; i <= exact.deg; i++) {
// splitting any curves at all in order to have their verticies too. exact.ctrl[i].MakeMaxMin(ptMax, ptMin);
// Better still would be to get curve/surface intersection to work }
// more reliably at the edges - maybe do curve/curve tests as part }
// of the curve-surface intersection test.
// We will be inserting other curve verticies into our curves to split them.
// This is helpful when curved surfaces become tangent along a trim and the
// usual tests for curve-surface intersection don't split the curve at a vertex.
// This is faster than the previous version that split at surface corners and
// handles more buggy cases. It's not clear this is the best way but it works ok.
static void FindVertsOnCurve(List<SInter> *l, const SCurve *curve, SShell *sh) { static void FindVertsOnCurve(List<SInter> *l, const SCurve *curve, SShell *sh) {
Vector amax, amin;
curve->GetAxisAlignedBounding(&amax, &amin);
for(auto sc : sh->curve) { for(auto sc : sh->curve) {
if(!sc.isExact) continue; if(!sc.isExact) continue;
Vector cmax, cmin;
sc.GetAxisAlignedBounding(&cmax, &cmin);
if(Vector::BoundingBoxesDisjoint(amax, amin, cmax, cmin)) {
// They cannot possibly intersect, no curves to generate
continue;
}
for(int i=0; i<2; i++) { for(int i=0; i<2; i++) {
Vector pt = sc.exact.ctrl[ i==0 ? 0 : sc.exact.deg ]; Vector pt = sc.exact.ctrl[ i==0 ? 0 : sc.exact.deg ];
double t; double t;
@ -63,10 +81,12 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
// First find any vertex that lies on our curve. // First find any vertex that lies on our curve.
List<SInter> vertpts = {}; List<SInter> vertpts = {};
if(agnstA) if(isExact) {
FindVertsOnCurve(&vertpts, this, agnstA); if(agnstA)
if(agnstB) FindVertsOnCurve(&vertpts, this, agnstA);
FindVertsOnCurve(&vertpts, this, agnstB); if(agnstB)
FindVertsOnCurve(&vertpts, this, agnstB);
}
const SCurvePt *p = pts.First(); const SCurvePt *p = pts.First();
ssassert(p != NULL, "Cannot split an empty curve"); ssassert(p != NULL, "Cannot split an empty curve");

View File

@ -219,6 +219,7 @@ public:
SSurface *GetSurfaceB(SShell *a, SShell *b) const; SSurface *GetSurfaceB(SShell *a, SShell *b) const;
void Clear(); void Clear();
void GetAxisAlignedBounding(Vector *ptMax, Vector *ptMin) const;
}; };
// A segment of a curve by which a surface is trimmed: indicates which curve, // A segment of a curve by which a surface is trimmed: indicates which curve,