Add color. Now each triangle has metadata, which are preserved in

csg ops; so the union of a red part and a blue part has both red
and blue faces. And some user interface to pick the color in the
text window.

The metadata also include a face, which will be an entity; I can
use that to constrain against. But none of that is yet implemented.

[git-p4: depot-paths = "//depot/solvespace/": change = 1757]
solver
Jonathan Westhues 2008-05-29 22:09:41 -08:00
parent 4bd44bf18a
commit 69eb2273ac
11 changed files with 149 additions and 65 deletions

View File

@ -57,6 +57,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'g', "Group.activeWorkplane.v", 'x', &(SS.sv.g.activeWorkplane.v) },
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
{ 'g', "Group.exprA", 'E', &(SS.sv.g.exprA) },
{ 'g', "Group.color", 'x', &(SS.sv.g.color) },
{ 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) },
{ 'g', "Group.meshCombine", 'd', &(SS.sv.g.meshCombine) },
{ 'g', "Group.wrkpl.q.w", 'f', &(SS.sv.g.wrkpl.q.w) },
@ -223,8 +224,9 @@ bool SolveSpace::SaveToFile(char *filename) {
SMesh *m = &(group.elem[group.n-1].mesh);
for(i = 0; i < m->l.n; i++) {
STriangle *tr = &(m->l.elem[i]);
fprintf(fh, "Triangle "
fprintf(fh, "Triangle %08x %08x "
"%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
tr->meta.face, tr->meta.color,
CO(tr->a), CO(tr->b), CO(tr->c));
}
@ -376,10 +378,12 @@ bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le, SMesh *m) {
} else if(memcmp(line, "Triangle", 8)==0) {
STriangle tr; ZERO(&tr);
if(sscanf(line, "Triangle %lf %lf %lf %lf %lf %lf %lf %lf %lf",
if(sscanf(line, "Triangle %x %x "
"%lf %lf %lf %lf %lf %lf %lf %lf %lf",
&(tr.meta.face), &(tr.meta.color),
&(tr.a.x), &(tr.a.y), &(tr.a.z),
&(tr.b.x), &(tr.b.y), &(tr.b.z),
&(tr.c.x), &(tr.c.y), &(tr.c.z)) != 9)
&(tr.c.x), &(tr.c.y), &(tr.c.z)) != 11)
{
oops();
}

View File

@ -111,15 +111,27 @@ void glxColor4d(double r, double g, double b, double a)
if(!ColorLocked) glColor4d(r, g, b, a);
}
void glxFillMesh(SMesh *m)
void glxFillMesh(bool useModelColor, SMesh *m)
{
glEnable(GL_NORMALIZE);
int prevColor = -1;
glBegin(GL_TRIANGLES);
for(int i = 0; i < m->l.n; i++) {
STriangle *tr = &(m->l.elem[i]);
Vector n = tr->Normal();
glNormal3d(n.x, n.y, n.z);
int color = tr->meta.color;
if(useModelColor && color != prevColor) {
GLfloat mpf[] = { ((color >> 0) & 0xff) / 255.0f,
((color >> 8) & 0xff) / 255.0f,
((color >> 16) & 0xff) / 255.0f, 1.0 };
glEnd();
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
prevColor = color;
glBegin(GL_TRIANGLES);
}
glxVertex3v(tr->a);
glxVertex3v(tr->b);
glxVertex3v(tr->c);

View File

@ -11,14 +11,16 @@ void SMesh::AddTriangle(Vector n, Vector a, Vector b, Vector c) {
// ugh; gl sometimes tesselates to collinear triangles
return;
}
STriMeta meta; ZERO(&meta);
if(np.Dot(n) > 0) {
AddTriangle(a, b, c);
AddTriangle(meta, a, b, c);
} else {
AddTriangle(c, b, a);
AddTriangle(meta, c, b, a);
}
}
void SMesh::AddTriangle(Vector a, Vector b, Vector c) {
void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) {
STriangle t; ZERO(&t);
t.meta = meta;
t.a = a;
t.b = b;
t.c = c;
@ -53,6 +55,8 @@ void SMesh::Simplify(int start) {
#define MAX_TRIANGLES 2000
if(l.n - start > MAX_TRIANGLES) oops();
STriMeta meta = l.elem[start].meta;
STriangle tout[MAX_TRIANGLES];
int toutc = 0;
@ -161,7 +165,7 @@ void SMesh::Simplify(int start) {
}
for(i = 0; i < convc - 2; i++) {
STriangle tr = { 0, conv[0], conv[i+1], conv[i+2] };
STriangle tr = STriangle::From(meta, conv[0], conv[i+1], conv[i+2]);
if((tr.Normal()).Magnitude() > LENGTH_EPS*LENGTH_EPS) {
tout[toutc++] = tr;
}
@ -185,9 +189,9 @@ void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) {
if(!atLeastOneDiscarded && (l.n != (pn+1))) {
l.n = pn;
if(flipNormal) {
AddTriangle(st->c, st->b, st->a);
AddTriangle(st->meta, st->c, st->b, st->a);
} else {
AddTriangle(st->a, st->b, st->c);
AddTriangle(st->meta, st->a, st->b, st->c);
}
}
if(l.n - pn > 1) {
@ -287,11 +291,11 @@ void SBsp3::InsertInPlane(bool pos2, STriangle *tr, SMesh *m) {
}
if(m->flipNormal && ((!pos2 && !onFace) || (onFace && !sameNormal))) {
m->AddTriangle(tr->c, tr->b, tr->a);
m->AddTriangle(tr->meta, tr->c, tr->b, tr->a);
} else if(!(m->flipNormal) && ((pos2 && !onFace) ||
(onFace && sameNormal && m->keepCoplanar)))
{
m->AddTriangle(tr->a, tr->b, tr->c);
m->AddTriangle(tr->meta, tr->a, tr->b, tr->c);
} else {
m->atLeastOneDiscarded = true;
}
@ -325,9 +329,9 @@ void SBsp3::InsertHow(int how, STriangle *tr, SMesh *instead) {
alt:
if(how == POS && !(instead->flipNormal)) {
instead->AddTriangle(tr->a, tr->b, tr->c);
instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c);
} else if(how == NEG && instead->flipNormal) {
instead->AddTriangle(tr->c, tr->b, tr->a);
instead->AddTriangle(tr->meta, tr->c, tr->b, tr->a);
} else if(how == COPLANAR) {
if(edges) {
edges->InsertTriangle(tr, instead, this);
@ -341,18 +345,20 @@ alt:
}
}
void SBsp3::InsertConvexHow(int how, Vector *vertex, int n, SMesh *instead) {
void SBsp3::InsertConvexHow(int how, STriMeta meta, Vector *vertex, int n,
SMesh *instead)
{
switch(how) {
case POS:
if(pos) {
pos = pos->InsertConvex(vertex, n, instead);
pos = pos->InsertConvex(meta, vertex, n, instead);
return;
}
break;
case NEG:
if(neg) {
neg = neg->InsertConvex(vertex, n, instead);
neg = neg->InsertConvex(meta, vertex, n, instead);
return;
}
break;
@ -361,12 +367,15 @@ void SBsp3::InsertConvexHow(int how, Vector *vertex, int n, SMesh *instead) {
}
int i;
for(i = 0; i < n - 2; i++) {
STriangle tr = { 0, vertex[0], vertex[i+1], vertex[i+2] };
STriangle tr = STriangle::From(meta,
vertex[0], vertex[i+1], vertex[i+2]);
InsertHow(how, &tr, instead);
}
}
SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) {
SBsp3 *SBsp3::InsertConvex(STriMeta meta, Vector *vertex, int cnt,
SMesh *instead)
{
Vector e01 = (vertex[1]).Minus(vertex[0]);
Vector e12 = (vertex[2]).Minus(vertex[1]);
Vector out = e01.Cross(e12);
@ -407,11 +416,11 @@ SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) {
}
if(posc == 0) {
InsertConvexHow(NEG, vertex, cnt, instead);
InsertConvexHow(NEG, meta, vertex, cnt, instead);
return this;
}
if(negc == 0) {
InsertConvexHow(POS, vertex, cnt, instead);
InsertConvexHow(POS, meta, vertex, cnt, instead);
return this;
}
@ -459,15 +468,16 @@ SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) {
}
if(nneg < 3 || npos < 3) oops();
InsertConvexHow(NEG, vneg, nneg, instead);
InsertConvexHow(POS, vpos, npos, instead);
InsertConvexHow(NEG, meta, vneg, nneg, instead);
InsertConvexHow(POS, meta, vpos, npos, instead);
return this;
triangulate:
// We don't handle the special case for this; do it as triangles
SBsp3 *r = this;
for(i = 0; i < cnt - 2; i++) {
STriangle tr = { 0, vertex[0], vertex[i+1], vertex[i+2] };
STriangle tr = STriangle::From(meta,
vertex[0], vertex[i+1], vertex[i+2]);
r = r->Insert(&tr, instead);
}
return r;
@ -479,7 +489,7 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) {
if(instead->flipNormal) {
instead->atLeastOneDiscarded = true;
} else {
instead->AddTriangle(tr->a, tr->b, tr->c);
instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c);
}
return NULL;
}
@ -551,8 +561,8 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) {
} else oops();
Vector bPc = IntersectionWith(b, c);
STriangle btri = { 0, a, b, bPc };
STriangle ctri = { 0, c, a, bPc };
STriangle btri = STriangle::From(tr->meta, a, b, bPc);
STriangle ctri = STriangle::From(tr->meta, c, a, bPc);
if(bpos) {
InsertHow(POS, &btri, instead);
@ -587,17 +597,14 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) {
Vector aPb = IntersectionWith(a, b);
Vector cPa = IntersectionWith(c, a);
STriangle alone = { 0, a, aPb, cPa };
STriangle alone = STriangle::From(tr->meta, a, aPb, cPa);
Vector quad[4] = { aPb, b, c, cPa };
STriangle quad1 = { 0, aPb, b, c };
STriangle quad2 = { 0, aPb, c, cPa };
if(posc == 2 && negc == 1) {
InsertConvexHow(POS, quad, 4, instead);
InsertConvexHow(POS, tr->meta, quad, 4, instead);
InsertHow(NEG, &alone, instead);
} else {
InsertConvexHow(NEG, quad, 4, instead);
InsertConvexHow(NEG, tr->meta, quad, 4, instead);
InsertHow(POS, &alone, instead);
}
if(!instead) {
@ -799,8 +806,8 @@ void SBsp2::InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3) {
} else oops();
Vector bPc = IntersectionWith(b, c);
STriangle btri = { 0, a, b, bPc };
STriangle ctri = { 0, c, a, bPc };
STriangle btri = STriangle::From(tr->meta, a, b, bPc);
STriangle ctri = STriangle::From(tr->meta, c, a, bPc);
if(bpos) {
InsertTriangleHow(POS, &btri, m, bsp3);
@ -830,9 +837,9 @@ void SBsp2::InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3) {
Vector aPb = IntersectionWith(a, b);
Vector cPa = IntersectionWith(c, a);
STriangle alone = { 0, a, aPb, cPa };
STriangle quad1 = { 0, aPb, b, c };
STriangle quad2 = { 0, aPb, c, cPa };
STriangle alone = STriangle::From(tr->meta, a, aPb, cPa);
STriangle quad1 = STriangle::From(tr->meta, aPb, b, c );
STriangle quad2 = STriangle::From(tr->meta, aPb, c, cPa);
if(posc == 2 && negc == 1) {
InsertTriangleHow(POS, &quad1, m, bsp3);

View File

@ -22,6 +22,11 @@ bool STriangle::ContainsPoint(Vector p) {
return true;
}
STriangle STriangle::From(STriMeta meta, Vector a, Vector b, Vector c) {
STriangle tr = { 0, meta, a, b, c };
return tr;
}
void SEdgeList::Clear(void) {
l.Clear();
}

View File

@ -99,11 +99,17 @@ public:
void Clear(void);
};
typedef struct {
DWORD face;
int color;
} STriMeta;
class STriangle {
public:
int tag;
Vector a, b, c;
int tag;
STriMeta meta;
Vector a, b, c;
static STriangle From(STriMeta meta, Vector a, Vector b, Vector c);
Vector Normal(void);
bool ContainsPoint(Vector p);
};
@ -153,8 +159,9 @@ public:
void InsertHow(int how, STriangle *str, SMesh *instead);
SBsp3 *Insert(STriangle *str, SMesh *instead);
void InsertConvexHow(int how, Vector *vertex, int n, SMesh *instead);
SBsp3 *InsertConvex(Vector *vertex, int n, SMesh *instead);
void InsertConvexHow(int how, STriMeta meta, Vector *vertex, int n,
SMesh *instead);
SBsp3 *InsertConvex(STriMeta meta, Vector *vertex, int n, SMesh *instead);
void InsertInPlane(bool pos2, STriangle *tr, SMesh *m);
@ -171,7 +178,7 @@ public:
void Clear(void);
void AddTriangle(STriangle *st);
void AddTriangle(Vector a, Vector b, Vector c);
void AddTriangle(STriMeta meta, Vector a, Vector b, Vector c);
void AddTriangle(Vector n, Vector a, Vector b, Vector c);
void DoBounding(Vector v, Vector *vmax, Vector *vmin);
void GetBounding(Vector *vmax, Vector *vmin);
@ -203,7 +210,7 @@ public:
STriangleLl2 *next;
};
class SAxisAligned {
class SKdTree {
public:
static const int BY_X = 1;
static const int BY_Y = 2;
@ -211,10 +218,10 @@ public:
int which;
double c;
SAxisAligned *gt;
SAxisAligned *lt;
SKdTree *gt;
SKdTree *lt;
STriangleLl2 *tris;
STriangleLl2 *tris;
};
#endif

View File

@ -79,6 +79,7 @@ void Group::MenuGroup(int id) {
case GraphicsWindow::MNU_GROUP_EXTRUDE:
g.type = EXTRUDE;
g.opA = SS.GW.activeGroup;
g.color = RGB(150, 150, 150);
g.wrkpl.entityB = SS.GW.ActiveWorkplane();
g.subtype = ONE_SIDED;
g.name.strcpy("extrude");
@ -512,6 +513,8 @@ void Group::MakePolygons(void) {
SMesh srcm; ZERO(&srcm);
(src->poly).TriangulateInto(&srcm);
STriMeta meta = { 0, color };
// Do the bottom; that has normal pointing opposite from translate
for(i = 0; i < srcm.l.n; i++) {
STriangle *st = &(srcm.l.elem[i]);
@ -519,9 +522,9 @@ void Group::MakePolygons(void) {
bt = (st->b).Plus(tbot),
ct = (st->c).Plus(tbot);
if(flipBottom) {
outm.AddTriangle(ct, bt, at);
outm.AddTriangle(meta, ct, bt, at);
} else {
outm.AddTriangle(at, bt, ct);
outm.AddTriangle(meta, at, bt, ct);
}
}
// And the top; that has the normal pointing the same dir as translate
@ -531,9 +534,9 @@ void Group::MakePolygons(void) {
bt = (st->b).Plus(ttop),
ct = (st->c).Plus(ttop);
if(flipBottom) {
outm.AddTriangle(at, bt, ct);
outm.AddTriangle(meta, at, bt, ct);
} else {
outm.AddTriangle(ct, bt, at);
outm.AddTriangle(meta, ct, bt, at);
}
}
srcm.Clear();
@ -547,11 +550,11 @@ void Group::MakePolygons(void) {
Vector abot = (edge->a).Plus(tbot), bbot = (edge->b).Plus(tbot);
Vector atop = (edge->a).Plus(ttop), btop = (edge->b).Plus(ttop);
if(flipBottom) {
outm.AddTriangle(bbot, abot, atop);
outm.AddTriangle(bbot, atop, btop);
outm.AddTriangle(meta, bbot, abot, atop);
outm.AddTriangle(meta, bbot, atop, btop);
} else {
outm.AddTriangle(abot, bbot, atop);
outm.AddTriangle(bbot, btop, atop);
outm.AddTriangle(meta, abot, bbot, atop);
outm.AddTriangle(meta, bbot, btop, atop);
}
}
} else if(type == IMPORTED) {
@ -593,12 +596,13 @@ 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;
if(type == DRAWING_3D || type == DRAWING_WORKPLANE) {
GLfloat mpf[] = { 0.1f, 0.1f, 0.1f, 1.0 };
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
useModelColor = false;
} else {
GLfloat mpf[] = { 0.4f, 0.4f, 0.4f, 1.0 };
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
useModelColor = true;
}
// The back faces are drawn in red; should never seem them, since we
// draw closed shells, so that's a debugging aid.
@ -606,7 +610,7 @@ void Group::Draw(void) {
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb);
glEnable(GL_LIGHTING);
if(SS.GW.showShaded) glxFillMesh(&mesh);
if(SS.GW.showShaded) glxFillMesh(useModelColor, &mesh);
glDisable(GL_LIGHTING);
if(SS.GW.showMesh) glxDebugMesh(&mesh);

View File

@ -90,6 +90,7 @@ public:
bool visible;
hEntity activeWorkplane;
Expr *exprA;
DWORD color;
static const int SOLVED_OKAY = 0;
static const int DIDNT_CONVERGE = 10;

View File

@ -100,7 +100,7 @@ void glxVertex3v(Vector u);
typedef void GLX_CALLBACK glxCallbackFptr(void);
void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
void glxFillPolygon(SPolygon *p);
void glxFillMesh(SMesh *m);
void glxFillMesh(bool useModelColor, SMesh *m);
void glxDebugPolygon(SPolygon *p);
void glxDebugEdgeList(SEdgeList *l);
void glxDebugMesh(SMesh *m);

View File

@ -24,6 +24,16 @@ void TextWindow::Init(void) {
memset(this, 0, sizeof(*this));
shown = &(showns[shownIndex]);
// Default list of colors for the model material
modelColor[0] = RGB(150, 150, 150);
modelColor[1] = RGB(100, 100, 100);
modelColor[2] = RGB( 30, 30, 30);
modelColor[3] = RGB(150, 0, 0);
modelColor[4] = RGB( 0, 150, 0);
modelColor[5] = RGB( 0, 80, 80);
modelColor[6] = RGB( 0, 0, 150);
modelColor[7] = RGB( 80, 0, 80);
ClearScreen();
}
@ -104,7 +114,9 @@ void TextWindow::Printf(bool halfLine, char *fmt, ...) {
} else {
color = fmt[1];
}
if(color < 0 || color > 255) color = 0;
if((color < 0 || color > 255) && !(color & 0x80000000)) {
color = 0;
}
if(*fmt == 'F') {
fg = color;
} else {
@ -385,6 +397,13 @@ void TextWindow::ScreenChangeMeshCombine(int link, DWORD v) {
SS.GW.GeneratePerSolving();
SS.GW.ClearSuper();
}
void TextWindow::ScreenColor(int link, DWORD v) {
Group *g = SS.GetGroup(SS.TW.shown->group);
if(v < 0 || v >= MODEL_COLORS) return;
g->color = SS.TW.modelColor[v];
SS.GW.GeneratePerSolving();
SS.GW.ClearSuper();
}
void TextWindow::ScreenChangeExprA(int link, DWORD v) {
Group *g = SS.GetGroup(SS.TW.shown->group);
ShowTextEditControl(13, 10, g->exprA->Print());
@ -446,6 +465,19 @@ void TextWindow::ShowGroupInfo(void) {
(diff ? "" : "as difference"), (diff ? "as difference" : ""));
}
if(g->type == Group::EXTRUDE) {
#define TWOX(v) v v
Printf(true, "%FtMCOLOR%E " TWOX(TWOX(TWOX("%Bp%D%f%Ln %Bd%E "))),
0x80000000 | modelColor[0], 0, &TextWindow::ScreenColor,
0x80000000 | modelColor[1], 1, &TextWindow::ScreenColor,
0x80000000 | modelColor[2], 2, &TextWindow::ScreenColor,
0x80000000 | modelColor[3], 3, &TextWindow::ScreenColor,
0x80000000 | modelColor[4], 4, &TextWindow::ScreenColor,
0x80000000 | modelColor[5], 5, &TextWindow::ScreenColor,
0x80000000 | modelColor[6], 6, &TextWindow::ScreenColor,
0x80000000 | modelColor[7], 7, &TextWindow::ScreenColor);
}
Printf(true, "%Ftrequests in group");
int i, a = 0;

5
ui.h
View File

@ -17,13 +17,15 @@ public:
static const Color fgColors[];
static const Color bgColors[];
static const int MODEL_COLORS = 8;
int modelColor[MODEL_COLORS];
BYTE text[MAX_ROWS][MAX_COLS];
typedef void LinkFunction(int link, DWORD v);
static const int NOT_A_LINK = 0;
struct {
char fg;
char bg;
int bg;
int link;
DWORD data;
LinkFunction *f;
@ -91,6 +93,7 @@ public:
static void ScreenChangeOneOrTwoSides(int link, DWORD v);
static void ScreenChangeMeshCombine(int link, DWORD v);
static void ScreenColor(int link, DWORD v);
// These ones do stuff with the edit control
static void ScreenChangeExprA(int link, DWORD v);

View File

@ -183,10 +183,19 @@ static void PaintTextWnd(HDC hdc)
for(c = 0; c < min((width/TEXT_WIDTH)+1, SS.TW.MAX_COLS); c++) {
int fg = SS.TW.meta[r][c].fg;
int bg = SS.TW.meta[r][c].bg;
SetTextColor(backDc, FgColor[fg]);
SetBkColor(backDc, BgColor[bg]);
if(SS.TW.meta[r][c].link) {
SetTextColor(backDc, FgColor[fg]);
HBRUSH bgb;
if(bg & 0x80000000) {
bgb = (HBRUSH)GetStockObject(BLACK_BRUSH);
SetBkColor(backDc, bg & 0xffffff);
} else {
bgb = BgBrush[bg];
SetBkColor(backDc, BgColor[bg]);
}
if(SS.TW.meta[r][c].link && SS.TW.meta[r][c].link != 'n') {
SelectObject(backDc, LinkFont);
} else {
SelectObject(backDc, FixedFont);
@ -198,7 +207,7 @@ static void PaintTextWnd(HDC hdc)
RECT a;
a.left = x; a.right = x+TEXT_WIDTH;
a.top = y; a.bottom = y+TEXT_HEIGHT;
FillRect(backDc, &a, BgBrush[bg]);
FillRect(backDc, &a, bgb);
TextOut(backDc, x, y+2, (char *)&(SS.TW.text[r][c]), 1);
}