Make the extrude command do a bit more; now I generate all the
faces of the polyhedron. And shade the faces when I draw them, and fix up our projection matrix so that the depth testing works properly. [git-p4: depot-paths = "//depot/solvespace/": change = 1703]
This commit is contained in:
parent
658b7df50f
commit
30636a6f29
@ -234,9 +234,14 @@ void Entity::PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v) {
|
||||
|
||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||
if(dogd.drawing) {
|
||||
// This fudge guarantees that the line will get drawn in front of
|
||||
// anything else at the "same" depth in the z-buffer, so that it
|
||||
// goes in front of the shaded stuff.
|
||||
Vector n = SS.GW.projRight.Cross(SS.GW.projUp);
|
||||
n = n.WithMagnitude(1.2/SS.GW.scale);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glxVertex3v(a);
|
||||
glxVertex3v(b);
|
||||
glxVertex3v(a.Plus(n));
|
||||
glxVertex3v(b.Plus(n));
|
||||
glEnd();
|
||||
} else {
|
||||
Point2d ap = SS.GW.ProjectPoint(a);
|
||||
|
@ -133,6 +133,9 @@ void glxFillPolygon(SPolygon *p)
|
||||
gluTessCallback(gt, GLU_TESS_COMBINE, (cf *)Combine);
|
||||
gluTessProperty(gt, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
|
||||
|
||||
Vector normal = p->Normal();
|
||||
glNormal3d(normal.x, normal.y, normal.z);
|
||||
|
||||
gluTessBeginPolygon(gt, NULL);
|
||||
for(i = 0; i < p->l.n; i++) {
|
||||
SContour *sc = &(p->l.elem[i]);
|
||||
|
@ -108,8 +108,10 @@ void GraphicsWindow::Init(void) {
|
||||
showWorkplanes = true;
|
||||
showAxes = true;
|
||||
showPoints = true;
|
||||
showAllGroups = true;
|
||||
showConstraints = true;
|
||||
showSolids = true;
|
||||
showHdnLines = false;
|
||||
showSolids = true;
|
||||
|
||||
solving = SOLVE_ALWAYS;
|
||||
|
||||
@ -443,6 +445,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||
if(pendingOperation == DRAGGING_NEW_POINT ||
|
||||
pendingOperation == DRAGGING_NEW_LINE_POINT)
|
||||
{
|
||||
SS.GenerateAll(SS.GW.solving == SOLVE_ALWAYS);
|
||||
UpdateDraggedEntity(pendingPoint, x, y);
|
||||
HitTestMakeSelection(mp);
|
||||
} else if(pendingOperation == DRAGGING_NEW_CUBIC_POINT) {
|
||||
@ -690,6 +693,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SS.GenerateAll(SS.GW.solving == SOLVE_ALWAYS);
|
||||
|
||||
SS.TW.Show();
|
||||
InvalidateGraphics();
|
||||
@ -777,6 +781,15 @@ void GraphicsWindow::ToggleAnyDatumShown(int link, DWORD v) {
|
||||
SS.TW.Show();
|
||||
}
|
||||
|
||||
Vector GraphicsWindow::VectorFromProjs(double right, double up, double fwd) {
|
||||
Vector n = projRight.Cross(projUp);
|
||||
Vector r = offset.ScaledBy(-1);
|
||||
r = r.Plus(projRight.ScaledBy(right));
|
||||
r = r.Plus(projUp.ScaledBy(up));
|
||||
r = r.Plus(n.ScaledBy(fwd));
|
||||
return r;
|
||||
}
|
||||
|
||||
void GraphicsWindow::Paint(int w, int h) {
|
||||
havePainted = true;
|
||||
width = w; height = h;
|
||||
@ -786,57 +799,73 @@ void GraphicsWindow::Paint(int w, int h) {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glScaled(scale*2.0/w, scale*2.0/h, 0);
|
||||
glScaled(scale*2.0/w, scale*2.0/h, scale*2.0/w);
|
||||
|
||||
double tx = projRight.Dot(offset);
|
||||
double ty = projUp.Dot(offset);
|
||||
Vector n = projUp.Cross(projRight);
|
||||
double tz = n.Dot(offset);
|
||||
double mat[16];
|
||||
MakeMatrix(mat, projRight.x, projRight.y, projRight.z, tx,
|
||||
projUp.x, projUp.y, projUp.z, ty,
|
||||
0, 0, 0, 0,
|
||||
n.x, n.y, n.z, tz,
|
||||
0, 0, 0, 1);
|
||||
glMultMatrixd(mat);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glClearIndex((GLfloat)0);
|
||||
glClearDepth(1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
Vector light = VectorFromProjs(-0.49*w/scale, 0.49*h/scale, 0);
|
||||
GLfloat lightPos[4] =
|
||||
{ (GLfloat)light.x, (GLfloat)light.y, (GLfloat)light.z, 0 };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1);
|
||||
GLfloat ambient[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
|
||||
|
||||
glxUnlockColor();
|
||||
|
||||
int i, a;
|
||||
// Draw the groups; this fills the polygons, if requested.
|
||||
if(showSolids) {
|
||||
for(i = 0; i < SS.group.n; i++) {
|
||||
SS.group.elem[i].Draw();
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
glxUnlockColor();
|
||||
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) glDisable(GL_DEPTH_TEST);
|
||||
if(a >= 1 && showHdnLines) glDisable(GL_DEPTH_TEST);
|
||||
for(i = 0; i < SS.entity.n; i++) {
|
||||
SS.entity.elem[i].Draw(a);
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
// Draw the constraints
|
||||
for(i = 0; i < SS.constraint.n; i++) {
|
||||
SS.constraint.elem[i].Draw();
|
||||
}
|
||||
|
||||
// Draw the groups; this fills the polygons, if requested.
|
||||
for(i = 0; i < SS.group.n; i++) {
|
||||
SS.group.elem[i].Draw();
|
||||
}
|
||||
|
||||
// Then redraw whatever the mouse is hovering over, highlighted.
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glxLockColorTo(1, 1, 0);
|
||||
|
42
polygon.cpp
42
polygon.cpp
@ -76,3 +76,45 @@ void SPolygon::AddPoint(Vector p) {
|
||||
(l.elem[l.n-1]).l.Add(&sp);
|
||||
}
|
||||
|
||||
void SPolygon::MakeEdgesInto(SEdgeList *el) {
|
||||
int i;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
(l.elem[i]).MakeEdgesInto(el);
|
||||
}
|
||||
}
|
||||
|
||||
Vector SPolygon::Normal(void) {
|
||||
if(l.n < 1) return Vector::MakeFrom(0, 0, 0);
|
||||
return (l.elem[0]).Normal();
|
||||
}
|
||||
|
||||
void SContour::MakeEdgesInto(SEdgeList *el) {
|
||||
int i;
|
||||
for(i = 0; i < (l.n-1); i++) {
|
||||
SEdge e;
|
||||
e.a = l.elem[i].p;
|
||||
e.b = l.elem[i+1].p;
|
||||
el->l.Add(&e);
|
||||
}
|
||||
}
|
||||
|
||||
Vector SContour::Normal(void) {
|
||||
if(l.n < 3) return Vector::MakeFrom(0, 0, 0);
|
||||
|
||||
Vector u = (l.elem[0].p).Minus(l.elem[1].p);
|
||||
|
||||
Vector v;
|
||||
double dot = 2;
|
||||
// Find the edge in the contour that's closest to perpendicular to the
|
||||
// first edge, since that will give best numerical stability.
|
||||
for(int i = 1; i < (l.n-1); i++) {
|
||||
Vector vt = (l.elem[i].p).Minus(l.elem[i+1].p);
|
||||
double dott = fabs(vt.Dot(u)/(u.Magnitude()*vt.Magnitude()));
|
||||
if(dott < dot) {
|
||||
dot = dott;
|
||||
v = vt;
|
||||
}
|
||||
}
|
||||
return (u.Cross(v)).WithMagnitude(1);
|
||||
}
|
||||
|
||||
|
@ -55,14 +55,19 @@ public:
|
||||
class SContour {
|
||||
public:
|
||||
SList<SPoint> l;
|
||||
|
||||
void MakeEdgesInto(SEdgeList *el);
|
||||
Vector Normal(void);
|
||||
};
|
||||
|
||||
class SPolygon {
|
||||
public:
|
||||
SList<SContour> l;
|
||||
|
||||
Vector Normal(void);
|
||||
void AddEmptyContour(void);
|
||||
void AddPoint(Vector p);
|
||||
void MakeEdgesInto(SEdgeList *el);
|
||||
void Clear(void);
|
||||
};
|
||||
|
||||
|
97
sketch.cpp
97
sketch.cpp
@ -134,39 +134,98 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz) {
|
||||
SS.entity.Add(&en);
|
||||
}
|
||||
|
||||
void Group::MakePolygons(void) {
|
||||
faces.Clear();
|
||||
if(type == DRAWING) {
|
||||
edges.l.Clear();
|
||||
int i;
|
||||
for(i = 0; i < SS.entity.n; i++) {
|
||||
Entity *e = &(SS.entity.elem[i]);
|
||||
if(e->group.v != h.v) continue;
|
||||
|
||||
e->GenerateEdges(&edges);
|
||||
}
|
||||
SPolygon poly;
|
||||
memset(&poly, 0, sizeof(poly));
|
||||
SEdge error;
|
||||
if(edges.AssemblePolygon(&poly, &error)) {
|
||||
polyError.yes = false;
|
||||
faces.Add(&poly);
|
||||
} else {
|
||||
polyError.yes = true;
|
||||
polyError.notClosedAt = error;
|
||||
poly.Clear();
|
||||
}
|
||||
} else if(type == EXTRUDE) {
|
||||
Vector translate;
|
||||
translate.x = SS.GetParam(h.param(0))->val;
|
||||
translate.y = SS.GetParam(h.param(1))->val;
|
||||
translate.z = SS.GetParam(h.param(2))->val;
|
||||
|
||||
edges.l.Clear();
|
||||
Group *src = SS.GetGroup(opA);
|
||||
if(src->faces.n != 1) return;
|
||||
|
||||
(src->faces.elem[0]).MakeEdgesInto(&edges);
|
||||
|
||||
SPolygon poly;
|
||||
SEdge error;
|
||||
|
||||
// The bottom
|
||||
memset(&poly, 0, sizeof(poly));
|
||||
if(!edges.AssemblePolygon(&poly, &error)) oops();
|
||||
faces.Add(&poly);
|
||||
|
||||
// The sides
|
||||
int i;
|
||||
for(i = 0; i < edges.l.n; i++) {
|
||||
SEdge *edge = &(edges.l.elem[i]);
|
||||
memset(&poly, 0, sizeof(poly));
|
||||
poly.AddEmptyContour();
|
||||
poly.AddPoint(edge->a);
|
||||
poly.AddPoint(edge->b);
|
||||
poly.AddPoint((edge->b).Plus(translate));
|
||||
poly.AddPoint((edge->a).Plus(translate));
|
||||
poly.AddPoint(edge->a);
|
||||
faces.Add(&poly);
|
||||
edge->a = (edge->a).Plus(translate);
|
||||
edge->b = (edge->b).Plus(translate);
|
||||
}
|
||||
|
||||
// The top
|
||||
memset(&poly, 0, sizeof(poly));
|
||||
if(!edges.AssemblePolygon(&poly, &error)) oops();
|
||||
faces.Add(&poly);
|
||||
}
|
||||
}
|
||||
|
||||
void Group::Draw(void) {
|
||||
if(!visible) return;
|
||||
|
||||
edges.l.Clear();
|
||||
int i;
|
||||
for(i = 0; i < SS.entity.n; i++) {
|
||||
Entity *e = &(SS.entity.elem[i]);
|
||||
if(e->group.v != h.v) continue;
|
||||
|
||||
e->GenerateEdges(&edges);
|
||||
}
|
||||
SPolygon poly;
|
||||
memset(&poly, 0, sizeof(poly));
|
||||
SEdge error;
|
||||
if(edges.AssemblePolygon(&poly, &error)) {
|
||||
glxColor4d(0, 0, 1, 0.1);
|
||||
glxFillPolygon(&poly);
|
||||
} else {
|
||||
if(polyError.yes) {
|
||||
glxColor4d(1, 0, 0, 0.2);
|
||||
glLineWidth(10);
|
||||
glBegin(GL_LINES);
|
||||
glxVertex3v(error.a);
|
||||
glxVertex3v(error.b);
|
||||
glxVertex3v(polyError.notClosedAt.a);
|
||||
glxVertex3v(polyError.notClosedAt.b);
|
||||
glEnd();
|
||||
glLineWidth(1);
|
||||
glxColor3d(1, 0, 0);
|
||||
glPushMatrix();
|
||||
glxTranslatev(error.b);
|
||||
glxTranslatev(polyError.notClosedAt.b);
|
||||
glxOntoWorkplane(SS.GW.projRight, SS.GW.projUp);
|
||||
glxWriteText("not closed contour!");
|
||||
glPopMatrix();
|
||||
} else {
|
||||
int i;
|
||||
glEnable(GL_LIGHTING);
|
||||
GLfloat vec[] = { 0, 0, 0.5, 1.0 };
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec);
|
||||
for(i = 0; i < faces.n; i++) {
|
||||
glxFillPolygon(&(faces.elem[i]));
|
||||
}
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
poly.Clear();
|
||||
}
|
||||
|
||||
hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) {
|
||||
|
9
sketch.h
9
sketch.h
@ -85,8 +85,12 @@ public:
|
||||
hGroup opB;
|
||||
bool visible;
|
||||
|
||||
SEdgeList edges;
|
||||
SPolygon poly;
|
||||
SEdgeList edges;
|
||||
SList<SPolygon> faces;
|
||||
struct {
|
||||
SEdge notClosedAt;
|
||||
bool yes;
|
||||
} polyError;
|
||||
|
||||
NameStr name;
|
||||
char *DescriptionString(void);
|
||||
@ -101,6 +105,7 @@ public:
|
||||
hEntity Remap(hEntity in, int copyNumber);
|
||||
void CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz);
|
||||
|
||||
void MakePolygons(void);
|
||||
void Draw(void);
|
||||
|
||||
SPolygon GetPolygon(void);
|
||||
|
@ -60,6 +60,8 @@ void SolveSpace::GenerateAll(bool andSolve) {
|
||||
// Solve this group.
|
||||
if(andSolve) SolveGroup(g->h);
|
||||
}
|
||||
|
||||
g->MakePolygons();
|
||||
}
|
||||
|
||||
prev.Clear();
|
||||
|
25
textwin.cpp
25
textwin.cpp
@ -217,17 +217,14 @@ void TextWindow::ShowHeader(void) {
|
||||
|
||||
SS.GW.EnsureValidActives();
|
||||
|
||||
char *cd = (SS.GW.activeWorkplane.v == Entity::FREE_IN_3D.v) ?
|
||||
"free in 3d" :
|
||||
SS.GetEntity(SS.GW.activeWorkplane)->DescriptionString();
|
||||
|
||||
// Navigation buttons
|
||||
if(SS.GW.pendingDescription) {
|
||||
Printf(false, " %Bt%Ft group:%s",
|
||||
SS.group.FindById(SS.GW.activeGroup)->DescriptionString());
|
||||
Printf(false, " %Bt%Ft workplane:%Fd %s", cd);
|
||||
} else {
|
||||
// Navigation buttons
|
||||
char *cd;
|
||||
if(SS.GW.activeWorkplane.v == Entity::FREE_IN_3D.v) {
|
||||
cd = "free in 3d";
|
||||
} else {
|
||||
cd = SS.GetEntity(SS.GW.activeWorkplane)->DescriptionString();
|
||||
}
|
||||
Printf(false, " %Lb%f<<%E %Lh%fhome%E %Bt%Ft workplane:%Fd %s",
|
||||
(&TextWindow::ScreenNavigation),
|
||||
(&TextWindow::ScreenNavigation),
|
||||
@ -255,10 +252,12 @@ void TextWindow::ShowHeader(void) {
|
||||
datumColor, &(SS.GW.ToggleAnyDatumShown)
|
||||
);
|
||||
Printf(false, "%Bt%Ft "
|
||||
"%Fp%Ll%D%fall-groups%E "
|
||||
"%Fp%Ll%D%fconstraints%E",
|
||||
hs(SS.GW.showAllGroups), (DWORD)(&SS.GW.showAllGroups), &(SS.GW.ToggleBool),
|
||||
hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints), &(SS.GW.ToggleBool)
|
||||
"%Fp%Ll%D%fconstraints%E "
|
||||
"%Fp%Ll%D%fsolids%E "
|
||||
"%Fp%Ll%D%fhidden-lines%E",
|
||||
hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints), &(SS.GW.ToggleBool),
|
||||
hs(SS.GW.showSolids), (DWORD)(&SS.GW.showSolids), &(SS.GW.ToggleBool),
|
||||
hs(SS.GW.showHdnLines), (DWORD)(&SS.GW.showHdnLines), &(SS.GW.ToggleBool)
|
||||
);
|
||||
}
|
||||
|
||||
|
4
ui.h
4
ui.h
@ -155,6 +155,7 @@ public:
|
||||
void NormalizeProjectionVectors(void);
|
||||
Point2d ProjectPoint(Vector p);
|
||||
void AnimateOnto(Quaternion quatf, Vector offsetf);
|
||||
Vector VectorFromProjs(double right, double up, double forward);
|
||||
|
||||
typedef enum {
|
||||
UNIT_MM = 0,
|
||||
@ -215,9 +216,10 @@ public:
|
||||
bool showWorkplanes;
|
||||
bool showAxes;
|
||||
bool showPoints;
|
||||
bool showAllGroups;
|
||||
bool showConstraints;
|
||||
bool showTextWindow;
|
||||
bool showSolids;
|
||||
bool showHdnLines;
|
||||
static void ToggleBool(int link, DWORD v);
|
||||
static void ToggleAnyDatumShown(int link, DWORD v);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user