Add selectable faces, by associating an hEntity with the triangle's
metadata. And add point-on-face constraints to go with that. Still needs some cleanup for the user interface. [git-p4: depot-paths = "//depot/solvespace/": change = 1766]
This commit is contained in:
parent
57db9bea34
commit
6748160026
|
@ -126,6 +126,10 @@ void Constraint::MenuConstrain(int id) {
|
|||
c.type = PT_ON_CIRCLE;
|
||||
c.ptA = gs.point[0];
|
||||
c.entityA = gs.entity[0];
|
||||
} else if(gs.points == 1 && gs.faces == 1 && gs.n == 2) {
|
||||
c.type = PT_ON_FACE;
|
||||
c.ptA = gs.point[0];
|
||||
c.entityA = gs.face[0];
|
||||
} else {
|
||||
Error("Bad selection for on point / curve / plane constraint.");
|
||||
return;
|
||||
|
@ -547,6 +551,16 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
SS.GetEntity(ptA)->PointGetExprs(), entityA), 0);
|
||||
break;
|
||||
|
||||
case PT_ON_FACE: {
|
||||
// a plane, n dot (p - p0) = 0
|
||||
ExprVector p = SS.GetEntity(ptA)->PointGetExprs();
|
||||
Entity *f = SS.GetEntity(entityA);
|
||||
ExprVector p0 = f->FaceGetPointExprs();
|
||||
ExprVector n = f->FaceGetNormalExprs();
|
||||
AddEq(l, (p.Minus(p0)).Dot(n), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case PT_ON_LINE:
|
||||
if(workplane.v == Entity::FREE_IN_3D.v) {
|
||||
Entity *ln = SS.GetEntity(entityA);
|
||||
|
|
|
@ -224,11 +224,25 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
|
||||
case PT_ON_CIRCLE:
|
||||
case PT_ON_LINE:
|
||||
case PT_ON_FACE:
|
||||
case PT_IN_PLANE: {
|
||||
double s = 7/SS.GW.scale;
|
||||
double s = 8/SS.GW.scale;
|
||||
Vector p = SS.GetEntity(ptA)->PointGetNum();
|
||||
Vector r = gr.WithMagnitude(s);
|
||||
Vector d = gu.WithMagnitude(s);
|
||||
Vector r, d;
|
||||
if(type == PT_ON_FACE) {
|
||||
Vector n = SS.GetEntity(entityA)->FaceGetNormalNum();
|
||||
r = n.Normal(0);
|
||||
d = n.Normal(1);
|
||||
} else if(type == PT_IN_PLANE) {
|
||||
Entity *n = SS.GetEntity(entityA)->Normal();
|
||||
r = n->NormalU();
|
||||
d = n->NormalV();
|
||||
} else {
|
||||
r = gr;
|
||||
d = gu;
|
||||
s *= (6.0/8); // draw these a little smaller
|
||||
}
|
||||
r = r.WithMagnitude(s); d = d.WithMagnitude(s);
|
||||
LineDrawOrGetDistance(p.Plus (r).Plus (d), p.Plus (r).Minus(d));
|
||||
LineDrawOrGetDistance(p.Plus (r).Minus(d), p.Minus(r).Minus(d));
|
||||
LineDrawOrGetDistance(p.Minus(r).Minus(d), p.Minus(r).Plus (d));
|
||||
|
|
1
dsc.h
1
dsc.h
|
@ -16,6 +16,7 @@ public:
|
|||
double w, vx, vy, vz;
|
||||
|
||||
static Quaternion From(double w, double vx, double vy, double vz);
|
||||
static Quaternion From(hParam w, hParam vx, hParam vy, hParam vz);
|
||||
static Quaternion From(Vector u, Vector v);
|
||||
|
||||
Quaternion Plus(Quaternion b);
|
||||
|
|
75
entity.cpp
75
entity.cpp
|
@ -574,6 +574,69 @@ Quaternion Entity::PointGetQuaternion(void) {
|
|||
return q;
|
||||
}
|
||||
|
||||
bool Entity::IsFace(void) {
|
||||
switch(type) {
|
||||
case FACE_NORMAL_PT:
|
||||
case FACE_XPROD:
|
||||
case FACE_N_ROT_TRANS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ExprVector Entity::FaceGetNormalExprs(void) {
|
||||
ExprVector r;
|
||||
if(type == FACE_NORMAL_PT) {
|
||||
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
||||
} else if(type == FACE_XPROD) {
|
||||
ExprVector vc = ExprVector::From(param[0], param[1], param[2]);
|
||||
ExprVector vn = ExprVector::From(numVector);
|
||||
r = vc.Cross(vn);
|
||||
} else if(type == FACE_N_ROT_TRANS) {
|
||||
// The numerical normal vector gets the rotation
|
||||
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
||||
ExprQuaternion q =
|
||||
ExprQuaternion::From(param[3], param[4], param[5], param[6]);
|
||||
r = q.Rotate(r);
|
||||
} else oops();
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector Entity::FaceGetNormalNum(void) {
|
||||
Vector r;
|
||||
if(type == FACE_NORMAL_PT) {
|
||||
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
||||
} else if(type == FACE_XPROD) {
|
||||
Vector vc = Vector::From(param[0], param[1], param[2]);
|
||||
r = vc.Cross(numVector);
|
||||
} else if(type == FACE_N_ROT_TRANS) {
|
||||
// The numerical normal vector gets the rotation
|
||||
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
||||
Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]);
|
||||
r = q.Rotate(r);
|
||||
} else oops();
|
||||
return r;
|
||||
}
|
||||
|
||||
ExprVector Entity::FaceGetPointExprs(void) {
|
||||
ExprVector r;
|
||||
if(type == FACE_NORMAL_PT) {
|
||||
r = SS.GetEntity(point[0])->PointGetExprs();
|
||||
} else if(type == FACE_XPROD) {
|
||||
r = ExprVector::From(numPoint);
|
||||
} else if(type == FACE_N_ROT_TRANS) {
|
||||
// The numerical point gets the rotation and translation.
|
||||
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
||||
ExprQuaternion q =
|
||||
ExprQuaternion::From(param[3], param[4], param[5], param[6]);
|
||||
r = ExprVector::From(numPoint);
|
||||
r = q.Rotate(r);
|
||||
r = r.Plus(trans);
|
||||
} else oops();
|
||||
return r;
|
||||
}
|
||||
|
||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||
if(dogd.drawing) {
|
||||
// glPolygonOffset works only on polys, not lines, so do it myself
|
||||
|
@ -890,6 +953,12 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
break;
|
||||
}
|
||||
|
||||
case FACE_NORMAL_PT:
|
||||
case FACE_XPROD:
|
||||
case FACE_N_ROT_TRANS:
|
||||
// Do nothing; these are drawn with the triangle mesh
|
||||
break;
|
||||
|
||||
default:
|
||||
oops();
|
||||
}
|
||||
|
@ -933,5 +1002,11 @@ void Entity::CalculateNumerical(void) {
|
|||
if(type == DISTANCE || type == DISTANCE_N_COPY) {
|
||||
actDistance = DistanceGetNum();
|
||||
}
|
||||
if(IsFace()) {
|
||||
ExprVector p = FaceGetPointExprs();
|
||||
ExprVector n = FaceGetNormalExprs();
|
||||
numPoint = Vector::From( p.x->Eval(), p.y->Eval(), p.z->Eval());
|
||||
numNormal = Quaternion::From(0, n.x->Eval(), n.y->Eval(), n.z->Eval());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
expr.cpp
17
expr.cpp
|
@ -21,6 +21,14 @@ ExprVector ExprVector::From(hParam x, hParam y, hParam z) {
|
|||
return ve;
|
||||
}
|
||||
|
||||
ExprVector ExprVector::From(double x, double y, double z) {
|
||||
ExprVector ve;
|
||||
ve.x = Expr::From(x);
|
||||
ve.y = Expr::From(y);
|
||||
ve.z = Expr::From(z);
|
||||
return ve;
|
||||
}
|
||||
|
||||
ExprVector ExprVector::Minus(ExprVector b) {
|
||||
ExprVector r;
|
||||
r.x = x->Minus(b.x);
|
||||
|
@ -236,6 +244,15 @@ int Expr::Children(void) {
|
|||
}
|
||||
}
|
||||
|
||||
int Expr::Nodes(void) {
|
||||
switch(Children()) {
|
||||
case 0: return 1;
|
||||
case 1: return 1 + a->Nodes();
|
||||
case 2: return 1 + a->Nodes() + b->Nodes();
|
||||
default: oops();
|
||||
}
|
||||
}
|
||||
|
||||
Expr *Expr::DeepCopy(void) {
|
||||
Expr *n = AllocExpr();
|
||||
*n = *this;
|
||||
|
|
3
expr.h
3
expr.h
|
@ -92,6 +92,8 @@ public:
|
|||
Expr *DeepCopy(void);
|
||||
// number of child nodes: 0 (e.g. constant), 1 (sqrt), or 2 (+)
|
||||
int Children(void);
|
||||
// total number of nodes in the tree
|
||||
int Nodes(void);
|
||||
|
||||
// Make a copy, with the parameters (usually referenced by hParam)
|
||||
// resolved to pointers to the actual value. This speeds things up
|
||||
|
@ -125,6 +127,7 @@ public:
|
|||
static ExprVector From(Expr *x, Expr *y, Expr *z);
|
||||
static ExprVector From(Vector vn);
|
||||
static ExprVector From(hParam x, hParam y, hParam z);
|
||||
static ExprVector From(double x, double y, double z);
|
||||
|
||||
ExprVector Plus(ExprVector b);
|
||||
ExprVector Minus(ExprVector b);
|
||||
|
|
17
glhelper.cpp
17
glhelper.cpp
|
@ -111,7 +111,7 @@ void glxColor4d(double r, double g, double b, double a)
|
|||
if(!ColorLocked) glColor4d(r, g, b, a);
|
||||
}
|
||||
|
||||
void glxFillMesh(bool useModelColor, SMesh *m)
|
||||
void glxFillMesh(int specColor, SMesh *m, DWORD h, DWORD s1, DWORD s2)
|
||||
{
|
||||
glEnable(GL_NORMALIZE);
|
||||
int prevColor = -1;
|
||||
|
@ -121,8 +121,19 @@ void glxFillMesh(bool useModelColor, SMesh *m)
|
|||
Vector n = tr->Normal();
|
||||
glNormal3d(n.x, n.y, n.z);
|
||||
|
||||
int color = tr->meta.color;
|
||||
if(useModelColor && color != prevColor) {
|
||||
int color;
|
||||
if((s1 != 0 && tr->meta.face == s1) ||
|
||||
(s2 != 0 && tr->meta.face == s2))
|
||||
{
|
||||
color = RGB(200, 0, 0);
|
||||
} else if(h != 0 && tr->meta.face == h) {
|
||||
color = RGB(200, 200, 0);
|
||||
} else if(specColor < 0) {
|
||||
color = tr->meta.color;
|
||||
} else {
|
||||
color = specColor;
|
||||
}
|
||||
if(color != prevColor) {
|
||||
GLfloat mpf[] = { ((color >> 0) & 0xff) / 255.0f,
|
||||
((color >> 8) & 0xff) / 255.0f,
|
||||
((color >> 16) & 0xff) / 255.0f, 1.0 };
|
||||
|
|
|
@ -745,6 +745,15 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
|||
}
|
||||
}
|
||||
|
||||
// Faces, from the triangle mesh; these are lowest priority
|
||||
if(s.constraint.v == 0 && s.entity.v == 0 && (showMesh || showShaded)) {
|
||||
SMesh *m = &((SS.GetGroup(activeGroup))->mesh);
|
||||
DWORD v = m->FirstIntersectionWith(mp);
|
||||
if(v) {
|
||||
s.entity.v = v;
|
||||
}
|
||||
}
|
||||
|
||||
if(!s.Equals(&hover)) {
|
||||
hover = s;
|
||||
InvalidateGraphics();
|
||||
|
@ -804,6 +813,11 @@ void GraphicsWindow::GroupSelection(void) {
|
|||
gs.vector[(gs.vectors)++] = s->entity;
|
||||
}
|
||||
|
||||
// Faces (which are special, associated/drawn with triangles)
|
||||
if(e->IsFace()) {
|
||||
gs.face[(gs.faces)++] = s->entity;
|
||||
}
|
||||
|
||||
// And some aux counts too
|
||||
switch(e->type) {
|
||||
case Entity::WORKPLANE: (gs.workplanes)++; break;
|
||||
|
|
29
mesh.cpp
29
mesh.cpp
|
@ -235,6 +235,35 @@ void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
|||
dbp("tris = %d", l.n);
|
||||
}
|
||||
|
||||
DWORD SMesh::FirstIntersectionWith(Point2d mp) {
|
||||
Vector gu = SS.GW.projRight, gv = SS.GW.projUp;
|
||||
Vector gn = (gu.Cross(gv)).WithMagnitude(1);
|
||||
|
||||
Vector p0 = gu.ScaledBy(mp.x/SS.GW.scale).Plus(
|
||||
gv.ScaledBy(mp.y/SS.GW.scale));
|
||||
p0 = p0.Minus(SS.GW.offset);
|
||||
|
||||
double maxT = -1e12;
|
||||
DWORD face = 0;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
STriangle *tr = &(l.elem[i]);
|
||||
Vector n = tr->Normal();
|
||||
if(n.Dot(gn) < LENGTH_EPS) continue; // back-facing or on edge
|
||||
|
||||
if(tr->ContainsPointProjd(gn, p0)) {
|
||||
// Let our line have the form r(t) = p0 + gn*t
|
||||
double t = (n.Dot((tr->a).Minus(p0)))/(n.Dot(gn));
|
||||
if(t > maxT) {
|
||||
maxT = t;
|
||||
face = tr->meta.face;
|
||||
}
|
||||
}
|
||||
}
|
||||
return face;
|
||||
}
|
||||
|
||||
SBsp2 *SBsp2::Alloc(void) { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); }
|
||||
SBsp3 *SBsp3::Alloc(void) { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); }
|
||||
|
||||
|
|
|
@ -6,9 +6,12 @@ Vector STriangle::Normal(void) {
|
|||
}
|
||||
|
||||
bool STriangle::ContainsPoint(Vector p) {
|
||||
Vector n = Normal();
|
||||
return ContainsPointProjd(n.WithMagnitude(1), p);
|
||||
}
|
||||
|
||||
bool STriangle::ContainsPointProjd(Vector n, Vector p) {
|
||||
Vector ab = b.Minus(a), bc = c.Minus(b), ca = a.Minus(c);
|
||||
Vector n = ab.Cross(bc);
|
||||
n = n.WithMagnitude(1);
|
||||
|
||||
Vector no_ab = n.Cross(ab);
|
||||
if(no_ab.Dot(p) < no_ab.Dot(a) - LENGTH_EPS) return false;
|
||||
|
|
|
@ -114,6 +114,7 @@ public:
|
|||
static STriangle From(STriMeta meta, Vector a, Vector b, Vector c);
|
||||
Vector Normal(void);
|
||||
bool ContainsPoint(Vector p);
|
||||
bool ContainsPointProjd(Vector n, Vector p);
|
||||
};
|
||||
|
||||
class SBsp2 {
|
||||
|
@ -190,6 +191,8 @@ public:
|
|||
void AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3);
|
||||
void MakeFromUnion(SMesh *a, SMesh *b);
|
||||
void MakeFromDifference(SMesh *a, SMesh *b);
|
||||
|
||||
DWORD FirstIntersectionWith(Point2d mp);
|
||||
};
|
||||
|
||||
// A linked list of triangles
|
||||
|
|
125
sketch.cpp
125
sketch.cpp
|
@ -10,6 +10,8 @@ const hRequest Request::HREQUEST_REFERENCE_XY = { 1 };
|
|||
const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 };
|
||||
const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 };
|
||||
|
||||
#define gs (SS.GW.gs)
|
||||
|
||||
void Group::AddParam(IdList<Param,hParam> *param, hParam hp, double v) {
|
||||
Param pa;
|
||||
memset(&pa, 0, sizeof(pa));
|
||||
|
@ -30,7 +32,6 @@ void Group::MenuGroup(int id) {
|
|||
}
|
||||
|
||||
SS.GW.GroupSelection();
|
||||
#define gs (SS.GW.gs)
|
||||
|
||||
switch(id) {
|
||||
case GraphicsWindow::MNU_GROUP_3D:
|
||||
|
@ -214,7 +215,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
break;
|
||||
}
|
||||
|
||||
case EXTRUDE:
|
||||
case EXTRUDE: {
|
||||
AddParam(param, h.param(0), gn.x);
|
||||
AddParam(param, h.param(1), gn.y);
|
||||
AddParam(param, h.param(2), gn.z);
|
||||
|
@ -224,10 +225,16 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
} else if(subtype == TWO_SIDED) {
|
||||
ai = -1; af = 1;
|
||||
} else oops();
|
||||
|
||||
// Get some arbitrary point in the sketch, that will be used
|
||||
// as a reference when defining top and bottom faces.
|
||||
hEntity pt = { 0 };
|
||||
for(i = 0; i < entity->n; i++) {
|
||||
Entity *e = &(entity->elem[i]);
|
||||
if(e->group.v != opA.v) continue;
|
||||
|
||||
if(e->IsPoint()) pt = e->h;
|
||||
|
||||
e->CalculateNumerical();
|
||||
hEntity he = e->h; e = NULL;
|
||||
// As soon as I call CopyEntity, e may become invalid! That
|
||||
|
@ -242,7 +249,11 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
true, false);
|
||||
MakeExtrusionLines(he);
|
||||
}
|
||||
// Remapped versions of that arbitrary point will be used to
|
||||
// provide points on the plane faces.
|
||||
MakeExtrusionTopBottomFaces(pt);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSLATE: {
|
||||
// The translation vector
|
||||
|
@ -386,16 +397,54 @@ hEntity Group::Remap(hEntity in, int copyNumber) {
|
|||
|
||||
void Group::MakeExtrusionLines(hEntity in) {
|
||||
Entity *ep = SS.GetEntity(in);
|
||||
if(!(ep->IsPoint())) return;
|
||||
|
||||
Entity en;
|
||||
memset(&en, 0, sizeof(en));
|
||||
en.point[0] = Remap(ep->h, REMAP_TOP);
|
||||
en.point[1] = Remap(ep->h, REMAP_BOTTOM);
|
||||
ZERO(&en);
|
||||
if(ep->IsPoint()) {
|
||||
// A point gets extruded to form a line segment
|
||||
en.point[0] = Remap(ep->h, REMAP_TOP);
|
||||
en.point[1] = Remap(ep->h, REMAP_BOTTOM);
|
||||
en.group = h;
|
||||
en.h = Remap(ep->h, REMAP_PT_TO_LINE);
|
||||
en.type = Entity::LINE_SEGMENT;
|
||||
SS.entity.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.
|
||||
Vector a = SS.GetEntity(ep->point[0])->PointGetNum();
|
||||
Vector b = SS.GetEntity(ep->point[1])->PointGetNum();
|
||||
Vector ab = b.Minus(a);
|
||||
|
||||
en.param[0] = h.param(0);
|
||||
en.param[1] = h.param(1);
|
||||
en.param[2] = h.param(2);
|
||||
en.numPoint = a;
|
||||
en.numVector = ab;
|
||||
|
||||
en.group = h;
|
||||
en.h = Remap(ep->h, REMAP_LINE_TO_FACE);
|
||||
en.type = Entity::FACE_XPROD;
|
||||
SS.entity.Add(&en);
|
||||
}
|
||||
}
|
||||
|
||||
void Group::MakeExtrusionTopBottomFaces(hEntity pt) {
|
||||
if(pt.v == 0) return;
|
||||
Group *src = SS.GetGroup(opA);
|
||||
Vector n = src->poly.normal;
|
||||
|
||||
Entity en;
|
||||
ZERO(&en);
|
||||
en.type = Entity::FACE_NORMAL_PT;
|
||||
en.group = h;
|
||||
en.h = Remap(ep->h, 10);
|
||||
en.type = Entity::LINE_SEGMENT;
|
||||
// And then this line segment gets added
|
||||
|
||||
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);
|
||||
|
||||
en.point[0] = Remap(pt, REMAP_BOTTOM);
|
||||
en.h = Remap(Entity::NO_ENTITY, REMAP_BOTTOM);
|
||||
SS.entity.Add(&en);
|
||||
}
|
||||
|
||||
|
@ -498,6 +547,23 @@ void Group::CopyEntity(Entity *ep, int timesApplied, int remap,
|
|||
en.numDistance = ep->actDistance;
|
||||
break;
|
||||
|
||||
case Entity::FACE_NORMAL_PT:
|
||||
case Entity::FACE_XPROD:
|
||||
case Entity::FACE_N_ROT_TRANS:
|
||||
if(asTrans || asAxisAngle) return;
|
||||
|
||||
en.type = Entity::FACE_N_ROT_TRANS;
|
||||
en.param[0] = dx;
|
||||
en.param[1] = dy;
|
||||
en.param[2] = dz;
|
||||
en.param[3] = qw;
|
||||
en.param[4] = qvx;
|
||||
en.param[5] = qvy;
|
||||
en.param[6] = qvz;
|
||||
en.numPoint = ep->numPoint;
|
||||
en.numNormal = ep->numNormal;
|
||||
break;
|
||||
|
||||
default:
|
||||
oops();
|
||||
}
|
||||
|
@ -526,8 +592,8 @@ void Group::TagEdgesFromLineSegments(SEdgeList *el) {
|
|||
|
||||
for(j = 0; j < el->l.n; j++) {
|
||||
SEdge *se = &(el->l.elem[j]);
|
||||
if((p0.Equals(se->a) && p1.Equals(se->b))) se->tag = 1;
|
||||
if((p0.Equals(se->b) && p1.Equals(se->a))) se->tag = 1;
|
||||
if((p0.Equals(se->a) && p1.Equals(se->b))) se->tag = e->h.v;
|
||||
if((p0.Equals(se->b) && p1.Equals(se->a))) se->tag = e->h.v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -583,6 +649,7 @@ void Group::MakePolygons(void) {
|
|||
STriMeta meta = { 0, color };
|
||||
|
||||
// Do the bottom; that has normal pointing opposite from translate
|
||||
meta.face = Remap(Entity::NO_ENTITY, REMAP_BOTTOM).v;
|
||||
for(i = 0; i < srcm.l.n; i++) {
|
||||
STriangle *st = &(srcm.l.elem[i]);
|
||||
Vector at = (st->a).Plus(tbot),
|
||||
|
@ -595,6 +662,7 @@ void Group::MakePolygons(void) {
|
|||
}
|
||||
}
|
||||
// And the top; that has the normal pointing the same dir as translate
|
||||
meta.face = Remap(Entity::NO_ENTITY, REMAP_TOP).v;
|
||||
for(i = 0; i < srcm.l.n; i++) {
|
||||
STriangle *st = &(srcm.l.elem[i]);
|
||||
Vector at = (st->a).Plus(ttop),
|
||||
|
@ -618,6 +686,15 @@ void Group::MakePolygons(void) {
|
|||
SEdge *edge = &(edges.l.elem[i]);
|
||||
Vector abot = (edge->a).Plus(tbot), bbot = (edge->b).Plus(tbot);
|
||||
Vector atop = (edge->a).Plus(ttop), btop = (edge->b).Plus(ttop);
|
||||
// We tagged the edges that came from line segments; their
|
||||
// triangles should be associated with that plane face.
|
||||
if(edge->tag) {
|
||||
hEntity hl = { edge->tag };
|
||||
hEntity hf = Remap(hl, REMAP_LINE_TO_FACE);
|
||||
meta.face = hf.v;
|
||||
} else {
|
||||
meta.face = 0;
|
||||
}
|
||||
if(flipBottom) {
|
||||
outm.AddTriangle(meta, bbot, abot, atop);
|
||||
outm.AddTriangle(meta, bbot, atop, btop);
|
||||
|
@ -641,6 +718,11 @@ void Group::MakePolygons(void) {
|
|||
|
||||
for(int i = 0; i < impMesh.l.n; i++) {
|
||||
STriangle st = impMesh.l.elem[i];
|
||||
|
||||
if(st.meta.face != 0) {
|
||||
hEntity he = { st.meta.face };
|
||||
st.meta.face = Remap(he, 0).v;
|
||||
}
|
||||
st.a = q.Rotate(st.a).Plus(offset);
|
||||
st.b = q.Rotate(st.b).Plus(offset);
|
||||
st.c = q.Rotate(st.c).Plus(offset);
|
||||
|
@ -665,21 +747,30 @@ void Group::Draw(void) {
|
|||
// Show this even if the group is not visible. It's already possible
|
||||
// to show or hide just this with the "show solids" flag.
|
||||
|
||||
bool useModelColor;
|
||||
int specColor;
|
||||
if(type != EXTRUDE && type != IMPORTED) {
|
||||
GLfloat mpf[] = { 0.1f, 0.1f, 0.1f, 1.0 };
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
|
||||
useModelColor = false;
|
||||
specColor = RGB(25, 25, 25); // force the color to something dim
|
||||
} else {
|
||||
useModelColor = true;
|
||||
specColor = -1; // use the model color
|
||||
}
|
||||
// The back faces are drawn in red; should never seem them, since we
|
||||
// draw closed shells, so that's a debugging aid.
|
||||
GLfloat mpb[] = { 1.0f, 0.1f, 0.1f, 1.0 };
|
||||
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb);
|
||||
|
||||
// When we fill the mesh, we need to know which triangles are selected
|
||||
// or hovered, in order to draw them differently.
|
||||
DWORD mh = 0, ms1 = 0, ms2 = 0;
|
||||
hEntity he = SS.GW.hover.entity;
|
||||
if(he.v != 0 && SS.GetEntity(he)->IsFace()) {
|
||||
mh = he.v;
|
||||
}
|
||||
SS.GW.GroupSelection();
|
||||
if(gs.faces > 0) ms1 = gs.face[0].v;
|
||||
if(gs.faces > 1) ms2 = gs.face[1].v;
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
if(SS.GW.showShaded) glxFillMesh(useModelColor, &mesh);
|
||||
if(SS.GW.showShaded) glxFillMesh(specColor, &mesh, mh, ms1, ms2);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if(SS.GW.showMesh) glxDebugMesh(&mesh);
|
||||
|
|
16
sketch.h
16
sketch.h
|
@ -148,8 +148,11 @@ public:
|
|||
static const int REMAP_LAST = 1000;
|
||||
static const int REMAP_TOP = 1001;
|
||||
static const int REMAP_BOTTOM = 1002;
|
||||
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 TagEdgesFromLineSegments(SEdgeList *sle);
|
||||
void CopyEntity(Entity *ep, int timesApplied, int remap,
|
||||
hParam dx, hParam dy, hParam dz,
|
||||
|
@ -232,9 +235,9 @@ public:
|
|||
static const int DISTANCE = 4000;
|
||||
static const int DISTANCE_N_COPY = 4001;
|
||||
|
||||
static const int FACE_N_COPY = 5000;
|
||||
static const int FACE_N_TRANS = 5001;
|
||||
static const int FACE_N_XPROD = 5002;
|
||||
static const int FACE_NORMAL_PT = 5000;
|
||||
static const int FACE_XPROD = 5001;
|
||||
static const int FACE_N_ROT_TRANS = 5002;
|
||||
|
||||
|
||||
static const int WORKPLANE = 10000;
|
||||
|
@ -258,6 +261,8 @@ public:
|
|||
Vector numPoint;
|
||||
Quaternion numNormal;
|
||||
double numDistance;
|
||||
// and a bit more state that the faces need
|
||||
Vector numVector;
|
||||
|
||||
// All points/normals/distances have their numerical value; this is
|
||||
// a convenience, to simplify the import/assembly code, so that the
|
||||
|
@ -297,6 +302,11 @@ public:
|
|||
Vector WorkplaneGetOffset(void);
|
||||
Entity *Normal(void);
|
||||
|
||||
bool IsFace(void);
|
||||
ExprVector FaceGetNormalExprs(void);
|
||||
Vector FaceGetNormalNum(void);
|
||||
ExprVector FaceGetPointExprs(void);
|
||||
|
||||
bool IsPoint(void);
|
||||
// Applies for any of the point types
|
||||
Vector PointGetNum(void);
|
||||
|
|
|
@ -104,7 +104,7 @@ void glxVertex3v(Vector u);
|
|||
typedef void GLX_CALLBACK glxCallbackFptr(void);
|
||||
void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
|
||||
void glxFillPolygon(SPolygon *p);
|
||||
void glxFillMesh(bool useModelColor, SMesh *m);
|
||||
void glxFillMesh(int color, SMesh *m, DWORD h, DWORD s1, DWORD s2);
|
||||
void glxDebugPolygon(SPolygon *p);
|
||||
void glxDebugEdgeList(SEdgeList *l);
|
||||
void glxDebugMesh(SMesh *m);
|
||||
|
|
9
util.cpp
9
util.cpp
|
@ -32,6 +32,15 @@ Quaternion Quaternion::From(double w, double vx, double vy, double vz) {
|
|||
return q;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::From(hParam w, hParam vx, hParam vy, hParam vz) {
|
||||
Quaternion q;
|
||||
q.w = SS.GetParam(w )->val;
|
||||
q.vx = SS.GetParam(vx)->val;
|
||||
q.vy = SS.GetParam(vy)->val;
|
||||
q.vz = SS.GetParam(vz)->val;
|
||||
return q;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::From(Vector u, Vector v)
|
||||
{
|
||||
Vector n = u.Cross(v);
|
||||
|
|
Loading…
Reference in New Issue
Block a user