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]solver
parent
48612bde3d
commit
ab44c24cfc
|
@ -513,6 +513,7 @@ s:
|
|||
|
||||
void Constraint::Draw(void) {
|
||||
dogd.drawing = true;
|
||||
glLineWidth(1);
|
||||
DrawOrGetDistance(NULL);
|
||||
}
|
||||
|
||||
|
|
27
dsc.h
27
dsc.h
|
@ -102,10 +102,19 @@ public:
|
|||
if(n >= elemsAllocated) {
|
||||
elemsAllocated = (elemsAllocated + 32)*2;
|
||||
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++;
|
||||
}
|
||||
|
||||
|
@ -119,10 +128,16 @@ public:
|
|||
}
|
||||
|
||||
T *FindByIdNoOops(H h) {
|
||||
int i;
|
||||
for(i = 0; i < n; i++) {
|
||||
if(elem[i].h.v == h.v) {
|
||||
return &(elem[i]);
|
||||
int first = 0, last = n-1;
|
||||
while(first <= last) {
|
||||
int mid = (first + last)/2;
|
||||
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;
|
||||
|
|
70
entity.cpp
70
entity.cpp
|
@ -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.edges = NULL;
|
||||
DrawOrGetDistance(order);
|
||||
DrawOrGetDistance();
|
||||
}
|
||||
|
||||
void Entity::GenerateEdges(SEdgeList *el) {
|
||||
dogd.drawing = false;
|
||||
dogd.edges = el;
|
||||
DrawOrGetDistance(-1);
|
||||
DrawOrGetDistance();
|
||||
dogd.edges = NULL;
|
||||
}
|
||||
|
||||
|
@ -661,7 +700,7 @@ double Entity::GetDistance(Point2d mp) {
|
|||
dogd.mp = mp;
|
||||
dogd.dmin = 1e12;
|
||||
|
||||
DrawOrGetDistance(-1);
|
||||
DrawOrGetDistance();
|
||||
|
||||
return dogd.dmin;
|
||||
}
|
||||
|
@ -671,7 +710,7 @@ Vector Entity::GetReferencePos(void) {
|
|||
dogd.edges = NULL;
|
||||
|
||||
dogd.refp = SS.GW.offset.ScaledBy(-1);
|
||||
DrawOrGetDistance(-1);
|
||||
DrawOrGetDistance();
|
||||
|
||||
return dogd.refp;
|
||||
}
|
||||
|
@ -697,15 +736,14 @@ bool Entity::IsVisible(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Entity::DrawOrGetDistance(int order) {
|
||||
Group *g = SS.GetGroup(group);
|
||||
void Entity::DrawOrGetDistance(void) {
|
||||
// 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.
|
||||
if(!dogd.edges) {
|
||||
if(!IsVisible()) return;
|
||||
}
|
||||
|
||||
glLineWidth(1.5);
|
||||
Group *g = SS.GetGroup(group);
|
||||
|
||||
if(group.v != SS.GW.activeGroup.v) {
|
||||
glxColor3d(0.5, 0.3, 0.0);
|
||||
|
@ -722,8 +760,6 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
case POINT_N_ROT_AA:
|
||||
case POINT_IN_3D:
|
||||
case POINT_IN_2D: {
|
||||
if(order >= 0 && order != 2) break;
|
||||
|
||||
Vector v = PointGetNum();
|
||||
|
||||
if(dogd.drawing) {
|
||||
|
@ -754,8 +790,6 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
case NORMAL_N_ROT_AA:
|
||||
case NORMAL_IN_3D:
|
||||
case NORMAL_IN_2D: {
|
||||
if(order >= 0 && order != 2) break;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 2; i++) {
|
||||
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)));
|
||||
}
|
||||
glLineWidth(1);
|
||||
glLineWidth(1.5);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -809,8 +843,6 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
break;
|
||||
|
||||
case WORKPLANE: {
|
||||
if(order >= 0 && order != 0) break;
|
||||
|
||||
Vector p;
|
||||
p = SS.GetEntity(point[0])->PointGetNum();
|
||||
|
||||
|
@ -841,6 +873,7 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
LineDrawOrGetDistance(mm, mp);
|
||||
LineDrawOrGetDistance(mp, pp);
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
glLineWidth(1.5);
|
||||
|
||||
char *str = DescriptionString()+5;
|
||||
if(dogd.drawing) {
|
||||
|
@ -862,7 +895,6 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
}
|
||||
|
||||
case LINE_SEGMENT: {
|
||||
if(order >= 0 && order != 1) break;
|
||||
Vector a = SS.GetEntity(point[0])->PointGetNum();
|
||||
Vector b = SS.GetEntity(point[1])->PointGetNum();
|
||||
LineDrawOrGetDistanceOrEdge(a, b);
|
||||
|
@ -870,7 +902,6 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
}
|
||||
|
||||
case CUBIC: {
|
||||
if(order >= 0 && order != 1) break;
|
||||
Vector p0 = SS.GetEntity(point[0])->PointGetNum();
|
||||
Vector p1 = SS.GetEntity(point[1])->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)))
|
||||
case ARC_OF_CIRCLE: {
|
||||
if(order >= 0 && order != 1) break;
|
||||
Vector c = SS.GetEntity(point[0])->PointGetNum();
|
||||
Vector pa = SS.GetEntity(point[1])->PointGetNum();
|
||||
Vector pb = SS.GetEntity(point[2])->PointGetNum();
|
||||
|
@ -919,8 +949,6 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
}
|
||||
|
||||
case CIRCLE: {
|
||||
if(order >= 0 && order != 1) break;
|
||||
|
||||
Quaternion q = SS.GetEntity(normal)->NormalGetNum();
|
||||
double r = SS.GetEntity(distance)->DistanceGetNum();
|
||||
Vector center = SS.GetEntity(point[0])->PointGetNum();
|
||||
|
@ -948,8 +976,6 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
default:
|
||||
oops();
|
||||
}
|
||||
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
void Entity::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) {
|
||||
|
|
|
@ -708,9 +708,11 @@ void GraphicsWindow::Selection::Clear(void) {
|
|||
void GraphicsWindow::Selection::Draw(void) {
|
||||
Vector refp;
|
||||
if(entity.v) {
|
||||
glLineWidth(1.5);
|
||||
Entity *e = SS.GetEntity(entity);
|
||||
e->Draw(-1);
|
||||
e->Draw();
|
||||
if(emphasized) refp = e->GetReferencePos();
|
||||
glLineWidth(1);
|
||||
}
|
||||
if(constraint.v) {
|
||||
Constraint *c = SS.GetConstraint(constraint);
|
||||
|
@ -749,7 +751,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
|||
int i;
|
||||
double d, dmin = 1e12;
|
||||
Selection s;
|
||||
memset(&s, 0, sizeof(s));
|
||||
ZERO(&s);
|
||||
|
||||
// Do the entities
|
||||
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) {
|
||||
SDWORD in = GetMilliseconds();
|
||||
|
||||
havePainted = true;
|
||||
width = w; height = h;
|
||||
|
||||
|
@ -1272,25 +1272,14 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
|
||||
glxUnlockColor();
|
||||
|
||||
int i, a;
|
||||
int i;
|
||||
// Draw the groups; this fills the polygons in a drawing group, and
|
||||
// draws the solid mesh.
|
||||
(SS.GetGroup(activeGroup))->Draw();
|
||||
dbp("done group: %d ms", GetMilliseconds() - in);
|
||||
|
||||
// First, draw the entire scene. We don't necessarily want to draw
|
||||
// things with normal z-buffering behaviour; e.g. we always want to
|
||||
// draw a line segment in front of a reference. So we have three draw
|
||||
// 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);
|
||||
// Now draw the entities
|
||||
if(showHdnLines) glDisable(GL_DEPTH_TEST);
|
||||
Entity::DrawAll();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
// Draw the constraints
|
||||
|
@ -1308,9 +1297,5 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
for(i = 0; i < MAX_SELECTED; i++) {
|
||||
selection[i].Draw();
|
||||
}
|
||||
|
||||
dbp("till end: %d ms", GetMilliseconds() - in);
|
||||
dbp("entity.n: %d", SS.entity.n);
|
||||
dbp("param.n: %d", SS.param.n);
|
||||
}
|
||||
|
||||
|
|
32
sketch.cpp
32
sketch.cpp
|
@ -251,19 +251,19 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
hEntity he = e->h; e = NULL;
|
||||
// As soon as I call CopyEntity, e may become invalid! That
|
||||
// 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),
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
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),
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
true, false);
|
||||
MakeExtrusionLines(he);
|
||||
MakeExtrusionLines(entity, he);
|
||||
}
|
||||
// Remapped versions of that arbitrary point will be used to
|
||||
// provide points on the plane faces.
|
||||
MakeExtrusionTopBottomFaces(pt);
|
||||
MakeExtrusionTopBottomFaces(entity, pt);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
if(e->group.v != opA.v) continue;
|
||||
|
||||
e->CalculateNumerical();
|
||||
CopyEntity(e,
|
||||
CopyEntity(entity, e,
|
||||
a*2 - (subtype == ONE_SIDED ? 0 : (n-1)),
|
||||
(a == (n - 1)) ? REMAP_LAST : a,
|
||||
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;
|
||||
|
||||
e->CalculateNumerical();
|
||||
CopyEntity(e,
|
||||
CopyEntity(entity, e,
|
||||
a*2 - (subtype == ONE_SIDED ? 0 : (n-1)),
|
||||
(a == (n - 1)) ? REMAP_LAST : a,
|
||||
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++) {
|
||||
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(3), h.param(4), h.param(5), h.param(6),
|
||||
false, false);
|
||||
|
@ -407,7 +407,7 @@ hEntity Group::Remap(hEntity in, int copyNumber) {
|
|||
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 en;
|
||||
|
@ -419,7 +419,7 @@ void Group::MakeExtrusionLines(hEntity in) {
|
|||
en.group = h;
|
||||
en.h = Remap(ep->h, REMAP_PT_TO_LINE);
|
||||
en.type = Entity::LINE_SEGMENT;
|
||||
SS.entity.Add(&en);
|
||||
el->Add(&en);
|
||||
} else if(ep->type == Entity::LINE_SEGMENT) {
|
||||
// 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.
|
||||
|
@ -436,11 +436,12 @@ void Group::MakeExtrusionLines(hEntity in) {
|
|||
en.group = h;
|
||||
en.h = Remap(ep->h, REMAP_LINE_TO_FACE);
|
||||
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;
|
||||
Group *src = SS.GetGroup(opA);
|
||||
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.point[0] = Remap(pt, 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.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 qw, hParam qvx, hParam qvy, hParam qvz,
|
||||
bool asTrans, bool asAxisAngle)
|
||||
|
@ -579,7 +581,7 @@ void Group::CopyEntity(Entity *ep, int timesApplied, int remap,
|
|||
default:
|
||||
oops();
|
||||
}
|
||||
SS.entity.Add(&en);
|
||||
el->Add(&en);
|
||||
}
|
||||
|
||||
void Group::TagEdgesFromLineSegments(SEdgeList *el) {
|
||||
|
|
12
sketch.h
12
sketch.h
|
@ -158,10 +158,11 @@ public:
|
|||
static const int REMAP_PT_TO_LINE = 1003;
|
||||
static const int REMAP_LINE_TO_FACE = 1004;
|
||||
hEntity Remap(hEntity in, int copyNumber);
|
||||
void MakeExtrusionLines(hEntity in);
|
||||
void MakeExtrusionTopBottomFaces(hEntity pt);
|
||||
void MakeExtrusionLines(IdList<Entity,hEntity> *el, hEntity in);
|
||||
void MakeExtrusionTopBottomFaces(IdList<Entity,hEntity> *el, hEntity pt);
|
||||
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 qw, hParam qvx, hParam qvy, hParam qvz,
|
||||
bool asTrans, bool asAxisAngle);
|
||||
|
@ -353,9 +354,10 @@ public:
|
|||
} dogd; // state for drawing or getting distance (for hit testing)
|
||||
void LineDrawOrGetDistance(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);
|
||||
void GenerateEdges(SEdgeList *el);
|
||||
Vector GetReferencePos(void);
|
||||
|
|
|
@ -278,7 +278,9 @@ bool System::SolveLeastSquares(void) {
|
|||
// changes in some parameters, and smaller in others.
|
||||
for(c = 0; c < mat.n; 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 {
|
||||
mat.scale[c] = 1;
|
||||
}
|
||||
|
|
6
util.cpp
6
util.cpp
|
@ -131,7 +131,11 @@ Vector Quaternion::RotationV(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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
STL check for meshes, and T intersection removal
|
||||
|
|
Loading…
Reference in New Issue