Major speedups, mostly by playing nicer with OpenGL; batch things

up more. Also change from stupid linear search lists to sorted
binary search lists, remove a stupid bug where I double-generated
entities, and don't do the triple drawing of entities (since
offsets on the Z buffer were doing the same job already).

[git-p4: depot-paths = "//depot/solvespace/": change = 1776]
This commit is contained in:
Jonathan Westhues 2008-06-05 23:50:08 -08:00
parent 48612bde3d
commit ab44c24cfc
9 changed files with 110 additions and 75 deletions

View File

@ -513,6 +513,7 @@ s:
void Constraint::Draw(void) { void Constraint::Draw(void) {
dogd.drawing = true; dogd.drawing = true;
glLineWidth(1);
DrawOrGetDistance(NULL); DrawOrGetDistance(NULL);
} }

27
dsc.h
View File

@ -102,10 +102,19 @@ public:
if(n >= elemsAllocated) { if(n >= elemsAllocated) {
elemsAllocated = (elemsAllocated + 32)*2; elemsAllocated = (elemsAllocated + 32)*2;
elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0])); elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0]));
if(!elem) oops();
} }
elem[n] = *t; int i = 0;
if(n == 0 || elem[n-1].h.v < t->h.v) {
i = n;
} else {
while(i < n && elem[i].h.v < t->h.v) {
i++;
}
}
if(i < n && elem[i].h.v == t->h.v) oops();
memmove(elem+i+1, elem+i, (n-i)*sizeof(elem[0]));
elem[i] = *t;
n++; n++;
} }
@ -119,10 +128,16 @@ public:
} }
T *FindByIdNoOops(H h) { T *FindByIdNoOops(H h) {
int i; int first = 0, last = n-1;
for(i = 0; i < n; i++) { while(first <= last) {
if(elem[i].h.v == h.v) { int mid = (first + last)/2;
return &(elem[i]); H hm = elem[mid].h;
if(hm.v > h.v) {
last = mid-1; // and first stays the same
} else if(hm.v < h.v) {
first = mid+1; // and last stays the same
} else {
return &(elem[mid]);
} }
} }
return NULL; return NULL;

View File

@ -642,16 +642,55 @@ void Entity::LineDrawOrGetDistanceOrEdge(Vector a, Vector b) {
} }
} }
void Entity::Draw(int order) { void Entity::DrawAll(void) {
// This handles points and line segments as a special case, because I
// seem to be able to get a huge speedup that way, by consolidating
// stuff to gl.
int i;
if(SS.GW.showPoints) {
double s = 3.5/SS.GW.scale;
Vector r = SS.GW.projRight.ScaledBy(s);
Vector d = SS.GW.projUp.ScaledBy(s);
glxColor3d(0, 0.8, 0);
glPolygonOffset(-10, -10);
glBegin(GL_QUADS);
for(i = 0; i < SS.entity.n; i++) {
Entity *e = &(SS.entity.elem[i]);
if(!e->IsPoint()) continue;
if(!(SS.GetGroup(e->group)->visible)) continue;
Vector v = e->PointGetNum();
glxVertex3v(v.Plus (r).Plus (d));
glxVertex3v(v.Plus (r).Minus(d));
glxVertex3v(v.Minus(r).Minus(d));
glxVertex3v(v.Minus(r).Plus (d));
}
glEnd();
glPolygonOffset(0, 0);
}
glLineWidth(1.5);
for(i = 0; i < SS.entity.n; i++) {
Entity *e = &(SS.entity.elem[i]);
if(e->IsPoint())
{
continue; // already handled
}
e->Draw();
}
glLineWidth(1);
}
void Entity::Draw(void) {
dogd.drawing = true; dogd.drawing = true;
dogd.edges = NULL; dogd.edges = NULL;
DrawOrGetDistance(order); DrawOrGetDistance();
} }
void Entity::GenerateEdges(SEdgeList *el) { void Entity::GenerateEdges(SEdgeList *el) {
dogd.drawing = false; dogd.drawing = false;
dogd.edges = el; dogd.edges = el;
DrawOrGetDistance(-1); DrawOrGetDistance();
dogd.edges = NULL; dogd.edges = NULL;
} }
@ -661,7 +700,7 @@ double Entity::GetDistance(Point2d mp) {
dogd.mp = mp; dogd.mp = mp;
dogd.dmin = 1e12; dogd.dmin = 1e12;
DrawOrGetDistance(-1); DrawOrGetDistance();
return dogd.dmin; return dogd.dmin;
} }
@ -671,7 +710,7 @@ Vector Entity::GetReferencePos(void) {
dogd.edges = NULL; dogd.edges = NULL;
dogd.refp = SS.GW.offset.ScaledBy(-1); dogd.refp = SS.GW.offset.ScaledBy(-1);
DrawOrGetDistance(-1); DrawOrGetDistance();
return dogd.refp; return dogd.refp;
} }
@ -697,15 +736,14 @@ bool Entity::IsVisible(void) {
return true; return true;
} }
void Entity::DrawOrGetDistance(int order) { void Entity::DrawOrGetDistance(void) {
Group *g = SS.GetGroup(group);
// If an entity is invisible, then it doesn't get shown, and it doesn't // If an entity is invisible, then it doesn't get shown, and it doesn't
// contribute a distance for the selection, but it still generates edges. // contribute a distance for the selection, but it still generates edges.
if(!dogd.edges) { if(!dogd.edges) {
if(!IsVisible()) return; if(!IsVisible()) return;
} }
glLineWidth(1.5); Group *g = SS.GetGroup(group);
if(group.v != SS.GW.activeGroup.v) { if(group.v != SS.GW.activeGroup.v) {
glxColor3d(0.5, 0.3, 0.0); glxColor3d(0.5, 0.3, 0.0);
@ -722,8 +760,6 @@ void Entity::DrawOrGetDistance(int order) {
case POINT_N_ROT_AA: case POINT_N_ROT_AA:
case POINT_IN_3D: case POINT_IN_3D:
case POINT_IN_2D: { case POINT_IN_2D: {
if(order >= 0 && order != 2) break;
Vector v = PointGetNum(); Vector v = PointGetNum();
if(dogd.drawing) { if(dogd.drawing) {
@ -754,8 +790,6 @@ void Entity::DrawOrGetDistance(int order) {
case NORMAL_N_ROT_AA: case NORMAL_N_ROT_AA:
case NORMAL_IN_3D: case NORMAL_IN_3D:
case NORMAL_IN_2D: { case NORMAL_IN_2D: {
if(order >= 0 && order != 2) break;
int i; int i;
for(i = 0; i < 2; i++) { for(i = 0; i < 2; i++) {
hRequest hr = h.request(); hRequest hr = h.request();
@ -799,7 +833,7 @@ void Entity::DrawOrGetDistance(int order) {
LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis, 0.6))); LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis, 0.6)));
LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis,-0.6))); LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis,-0.6)));
} }
glLineWidth(1); glLineWidth(1.5);
break; break;
} }
@ -809,8 +843,6 @@ void Entity::DrawOrGetDistance(int order) {
break; break;
case WORKPLANE: { case WORKPLANE: {
if(order >= 0 && order != 0) break;
Vector p; Vector p;
p = SS.GetEntity(point[0])->PointGetNum(); p = SS.GetEntity(point[0])->PointGetNum();
@ -841,6 +873,7 @@ void Entity::DrawOrGetDistance(int order) {
LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mm, mp);
LineDrawOrGetDistance(mp, pp); LineDrawOrGetDistance(mp, pp);
glDisable(GL_LINE_STIPPLE); glDisable(GL_LINE_STIPPLE);
glLineWidth(1.5);
char *str = DescriptionString()+5; char *str = DescriptionString()+5;
if(dogd.drawing) { if(dogd.drawing) {
@ -862,7 +895,6 @@ void Entity::DrawOrGetDistance(int order) {
} }
case LINE_SEGMENT: { case LINE_SEGMENT: {
if(order >= 0 && order != 1) break;
Vector a = SS.GetEntity(point[0])->PointGetNum(); Vector a = SS.GetEntity(point[0])->PointGetNum();
Vector b = SS.GetEntity(point[1])->PointGetNum(); Vector b = SS.GetEntity(point[1])->PointGetNum();
LineDrawOrGetDistanceOrEdge(a, b); LineDrawOrGetDistanceOrEdge(a, b);
@ -870,7 +902,6 @@ void Entity::DrawOrGetDistance(int order) {
} }
case CUBIC: { case CUBIC: {
if(order >= 0 && order != 1) break;
Vector p0 = SS.GetEntity(point[0])->PointGetNum(); Vector p0 = SS.GetEntity(point[0])->PointGetNum();
Vector p1 = SS.GetEntity(point[1])->PointGetNum(); Vector p1 = SS.GetEntity(point[1])->PointGetNum();
Vector p2 = SS.GetEntity(point[2])->PointGetNum(); Vector p2 = SS.GetEntity(point[2])->PointGetNum();
@ -892,7 +923,6 @@ void Entity::DrawOrGetDistance(int order) {
#define CIRCLE_SIDES(r) (7 + (int)(sqrt(r*SS.GW.scale))) #define CIRCLE_SIDES(r) (7 + (int)(sqrt(r*SS.GW.scale)))
case ARC_OF_CIRCLE: { case ARC_OF_CIRCLE: {
if(order >= 0 && order != 1) break;
Vector c = SS.GetEntity(point[0])->PointGetNum(); Vector c = SS.GetEntity(point[0])->PointGetNum();
Vector pa = SS.GetEntity(point[1])->PointGetNum(); Vector pa = SS.GetEntity(point[1])->PointGetNum();
Vector pb = SS.GetEntity(point[2])->PointGetNum(); Vector pb = SS.GetEntity(point[2])->PointGetNum();
@ -919,8 +949,6 @@ void Entity::DrawOrGetDistance(int order) {
} }
case CIRCLE: { case CIRCLE: {
if(order >= 0 && order != 1) break;
Quaternion q = SS.GetEntity(normal)->NormalGetNum(); Quaternion q = SS.GetEntity(normal)->NormalGetNum();
double r = SS.GetEntity(distance)->DistanceGetNum(); double r = SS.GetEntity(distance)->DistanceGetNum();
Vector center = SS.GetEntity(point[0])->PointGetNum(); Vector center = SS.GetEntity(point[0])->PointGetNum();
@ -948,8 +976,6 @@ void Entity::DrawOrGetDistance(int order) {
default: default:
oops(); oops();
} }
glLineWidth(1);
} }
void Entity::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) { void Entity::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) {

View File

@ -708,9 +708,11 @@ void GraphicsWindow::Selection::Clear(void) {
void GraphicsWindow::Selection::Draw(void) { void GraphicsWindow::Selection::Draw(void) {
Vector refp; Vector refp;
if(entity.v) { if(entity.v) {
glLineWidth(1.5);
Entity *e = SS.GetEntity(entity); Entity *e = SS.GetEntity(entity);
e->Draw(-1); e->Draw();
if(emphasized) refp = e->GetReferencePos(); if(emphasized) refp = e->GetReferencePos();
glLineWidth(1);
} }
if(constraint.v) { if(constraint.v) {
Constraint *c = SS.GetConstraint(constraint); Constraint *c = SS.GetConstraint(constraint);
@ -749,7 +751,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
int i; int i;
double d, dmin = 1e12; double d, dmin = 1e12;
Selection s; Selection s;
memset(&s, 0, sizeof(s)); ZERO(&s);
// Do the entities // Do the entities
for(i = 0; i < SS.entity.n; i++) { for(i = 0; i < SS.entity.n; i++) {
@ -1217,8 +1219,6 @@ Vector GraphicsWindow::VectorFromProjs(double right, double up, double fwd) {
} }
void GraphicsWindow::Paint(int w, int h) { void GraphicsWindow::Paint(int w, int h) {
SDWORD in = GetMilliseconds();
havePainted = true; havePainted = true;
width = w; height = h; width = w; height = h;
@ -1272,25 +1272,14 @@ void GraphicsWindow::Paint(int w, int h) {
glxUnlockColor(); glxUnlockColor();
int i, a; int i;
// Draw the groups; this fills the polygons in a drawing group, and // Draw the groups; this fills the polygons in a drawing group, and
// draws the solid mesh. // draws the solid mesh.
(SS.GetGroup(activeGroup))->Draw(); (SS.GetGroup(activeGroup))->Draw();
dbp("done group: %d ms", GetMilliseconds() - in);
// First, draw the entire scene. We don't necessarily want to draw // Now draw the entities
// things with normal z-buffering behaviour; e.g. we always want to if(showHdnLines) glDisable(GL_DEPTH_TEST);
// draw a line segment in front of a reference. So we have three draw Entity::DrawAll();
// levels, and only the first gets normal depth testing.
for(a = 0; a <= 2; a++) {
// Three levels: 0 least prominent (e.g. a reference workplane), 1 is
// middle (e.g. line segment), 2 is always in front (e.g. point).
if(a >= 1 && showHdnLines) glDisable(GL_DEPTH_TEST);
for(i = 0; i < SS.entity.n; i++) {
SS.entity.elem[i].Draw(a);
}
}
dbp("done entity: %d ms", GetMilliseconds() - in);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
// Draw the constraints // Draw the constraints
@ -1308,9 +1297,5 @@ void GraphicsWindow::Paint(int w, int h) {
for(i = 0; i < MAX_SELECTED; i++) { for(i = 0; i < MAX_SELECTED; i++) {
selection[i].Draw(); selection[i].Draw();
} }
dbp("till end: %d ms", GetMilliseconds() - in);
dbp("entity.n: %d", SS.entity.n);
dbp("param.n: %d", SS.param.n);
} }

View File

@ -251,19 +251,19 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
hEntity he = e->h; e = NULL; hEntity he = e->h; e = NULL;
// As soon as I call CopyEntity, e may become invalid! That // As soon as I call CopyEntity, e may become invalid! That
// adds entities, which may cause a realloc. // adds entities, which may cause a realloc.
CopyEntity(SS.GetEntity(he), ai, REMAP_BOTTOM, CopyEntity(entity, SS.GetEntity(he), ai, REMAP_BOTTOM,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true, false); true, false);
CopyEntity(SS.GetEntity(he), af, REMAP_TOP, CopyEntity(entity, SS.GetEntity(he), af, REMAP_TOP,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true, false); true, false);
MakeExtrusionLines(he); MakeExtrusionLines(entity, he);
} }
// Remapped versions of that arbitrary point will be used to // Remapped versions of that arbitrary point will be used to
// provide points on the plane faces. // provide points on the plane faces.
MakeExtrusionTopBottomFaces(pt); MakeExtrusionTopBottomFaces(entity, pt);
break; break;
} }
@ -280,7 +280,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
if(e->group.v != opA.v) continue; if(e->group.v != opA.v) continue;
e->CalculateNumerical(); e->CalculateNumerical();
CopyEntity(e, CopyEntity(entity, e,
a*2 - (subtype == ONE_SIDED ? 0 : (n-1)), a*2 - (subtype == ONE_SIDED ? 0 : (n-1)),
(a == (n - 1)) ? REMAP_LAST : a, (a == (n - 1)) ? REMAP_LAST : a,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
@ -308,7 +308,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
if(e->group.v != opA.v) continue; if(e->group.v != opA.v) continue;
e->CalculateNumerical(); e->CalculateNumerical();
CopyEntity(e, CopyEntity(entity, e,
a*2 - (subtype == ONE_SIDED ? 0 : (n-1)), a*2 - (subtype == ONE_SIDED ? 0 : (n-1)),
(a == (n - 1)) ? REMAP_LAST : a, (a == (n - 1)) ? REMAP_LAST : a,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
@ -332,7 +332,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
for(i = 0; i < impEntity.n; i++) { for(i = 0; i < impEntity.n; i++) {
Entity *ie = &(impEntity.elem[i]); Entity *ie = &(impEntity.elem[i]);
CopyEntity(ie, 0, 0, CopyEntity(entity, ie, 0, 0,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
h.param(3), h.param(4), h.param(5), h.param(6), h.param(3), h.param(4), h.param(5), h.param(6),
false, false); false, false);
@ -407,7 +407,7 @@ hEntity Group::Remap(hEntity in, int copyNumber) {
return h.entity(em.h.v); return h.entity(em.h.v);
} }
void Group::MakeExtrusionLines(hEntity in) { void Group::MakeExtrusionLines(IdList<Entity,hEntity> *el, hEntity in) {
Entity *ep = SS.GetEntity(in); Entity *ep = SS.GetEntity(in);
Entity en; Entity en;
@ -419,7 +419,7 @@ void Group::MakeExtrusionLines(hEntity in) {
en.group = h; en.group = h;
en.h = Remap(ep->h, REMAP_PT_TO_LINE); en.h = Remap(ep->h, REMAP_PT_TO_LINE);
en.type = Entity::LINE_SEGMENT; en.type = Entity::LINE_SEGMENT;
SS.entity.Add(&en); el->Add(&en);
} else if(ep->type == Entity::LINE_SEGMENT) { } else if(ep->type == Entity::LINE_SEGMENT) {
// A line gets extruded to form a plane face; an endpoint of the // A line gets extruded to form a plane face; an endpoint of the
// original line is a point in the plane, and the line is in the plane. // original line is a point in the plane, and the line is in the plane.
@ -436,11 +436,12 @@ void Group::MakeExtrusionLines(hEntity in) {
en.group = h; en.group = h;
en.h = Remap(ep->h, REMAP_LINE_TO_FACE); en.h = Remap(ep->h, REMAP_LINE_TO_FACE);
en.type = Entity::FACE_XPROD; en.type = Entity::FACE_XPROD;
SS.entity.Add(&en); el->Add(&en);
} }
} }
void Group::MakeExtrusionTopBottomFaces(hEntity pt) { void Group::MakeExtrusionTopBottomFaces(IdList<Entity,hEntity> *el, hEntity pt)
{
if(pt.v == 0) return; if(pt.v == 0) return;
Group *src = SS.GetGroup(opA); Group *src = SS.GetGroup(opA);
Vector n = src->poly.normal; Vector n = src->poly.normal;
@ -453,14 +454,15 @@ void Group::MakeExtrusionTopBottomFaces(hEntity pt) {
en.numNormal = Quaternion::From(0, n.x, n.y, n.z); en.numNormal = Quaternion::From(0, n.x, n.y, n.z);
en.point[0] = Remap(pt, REMAP_TOP); en.point[0] = Remap(pt, REMAP_TOP);
en.h = Remap(Entity::NO_ENTITY, REMAP_TOP); en.h = Remap(Entity::NO_ENTITY, REMAP_TOP);
SS.entity.Add(&en); el->Add(&en);
en.point[0] = Remap(pt, REMAP_BOTTOM); en.point[0] = Remap(pt, REMAP_BOTTOM);
en.h = Remap(Entity::NO_ENTITY, REMAP_BOTTOM); en.h = Remap(Entity::NO_ENTITY, REMAP_BOTTOM);
SS.entity.Add(&en); el->Add(&en);
} }
void Group::CopyEntity(Entity *ep, int timesApplied, int remap, void Group::CopyEntity(IdList<Entity,hEntity> *el,
Entity *ep, int timesApplied, int remap,
hParam dx, hParam dy, hParam dz, hParam dx, hParam dy, hParam dz,
hParam qw, hParam qvx, hParam qvy, hParam qvz, hParam qw, hParam qvx, hParam qvy, hParam qvz,
bool asTrans, bool asAxisAngle) bool asTrans, bool asAxisAngle)
@ -579,7 +581,7 @@ void Group::CopyEntity(Entity *ep, int timesApplied, int remap,
default: default:
oops(); oops();
} }
SS.entity.Add(&en); el->Add(&en);
} }
void Group::TagEdgesFromLineSegments(SEdgeList *el) { void Group::TagEdgesFromLineSegments(SEdgeList *el) {

View File

@ -158,10 +158,11 @@ public:
static const int REMAP_PT_TO_LINE = 1003; static const int REMAP_PT_TO_LINE = 1003;
static const int REMAP_LINE_TO_FACE = 1004; static const int REMAP_LINE_TO_FACE = 1004;
hEntity Remap(hEntity in, int copyNumber); hEntity Remap(hEntity in, int copyNumber);
void MakeExtrusionLines(hEntity in); void MakeExtrusionLines(IdList<Entity,hEntity> *el, hEntity in);
void MakeExtrusionTopBottomFaces(hEntity pt); void MakeExtrusionTopBottomFaces(IdList<Entity,hEntity> *el, hEntity pt);
void TagEdgesFromLineSegments(SEdgeList *sle); void TagEdgesFromLineSegments(SEdgeList *sle);
void CopyEntity(Entity *ep, int timesApplied, int remap, void CopyEntity(IdList<Entity,hEntity> *el,
Entity *ep, int timesApplied, int remap,
hParam dx, hParam dy, hParam dz, hParam dx, hParam dy, hParam dz,
hParam qw, hParam qvx, hParam qvy, hParam qvz, hParam qw, hParam qvx, hParam qvy, hParam qvz,
bool asTrans, bool asAxisAngle); bool asTrans, bool asAxisAngle);
@ -353,9 +354,10 @@ public:
} dogd; // state for drawing or getting distance (for hit testing) } dogd; // state for drawing or getting distance (for hit testing)
void LineDrawOrGetDistance(Vector a, Vector b); void LineDrawOrGetDistance(Vector a, Vector b);
void LineDrawOrGetDistanceOrEdge(Vector a, Vector b); void LineDrawOrGetDistanceOrEdge(Vector a, Vector b);
void DrawOrGetDistance(int order); void DrawOrGetDistance(void);
void Draw(int order); static void DrawAll(void);
void Draw(void);
double GetDistance(Point2d mp); double GetDistance(Point2d mp);
void GenerateEdges(SEdgeList *el); void GenerateEdges(SEdgeList *el);
Vector GetReferencePos(void); Vector GetReferencePos(void);

View File

@ -278,7 +278,9 @@ bool System::SolveLeastSquares(void) {
// changes in some parameters, and smaller in others. // changes in some parameters, and smaller in others.
for(c = 0; c < mat.n; c++) { for(c = 0; c < mat.n; c++) {
if(IsDragged(mat.param[c])) { if(IsDragged(mat.param[c])) {
mat.scale[c] = 1/5.0; // It's least squares, so this parameter doesn't need to be all
// that big to get a large effect.
mat.scale[c] = 1/20.0;
} else { } else {
mat.scale[c] = 1; mat.scale[c] = 1;
} }

View File

@ -131,7 +131,11 @@ Vector Quaternion::RotationV(void) {
} }
Vector Quaternion::RotationN(void) { Vector Quaternion::RotationN(void) {
return RotationU().Cross(RotationV()); Vector v;
v.x = 2*w*vy + 2*vx*vz;
v.y = 2*vy*vz - 2*w*vx;
v.z = w*w - vx*vx - vy*vy + vz*vz;
return v;
} }
Vector Quaternion::Rotate(Vector p) { Vector Quaternion::Rotate(Vector p) {

View File

@ -1,6 +1,4 @@
stupidity where stuff gets double-added to entity list
replace linear search through IdLists with faster (binary search?)
point face distance constraint point face distance constraint
STL check for meshes, and T intersection removal STL check for meshes, and T intersection removal