diff --git a/src/draw.cpp b/src/draw.cpp index 47d04208..2c3d5f9e 100644 --- a/src/draw.cpp +++ b/src/draw.cpp @@ -604,14 +604,6 @@ void GraphicsWindow::Paint(void) { GLfloat ld1[4] = { (GLfloat)ld.x, (GLfloat)ld.y, (GLfloat)ld.z, 0 }; glLightfv(GL_LIGHT1, GL_POSITION, ld1); - if(SS.drawBackFaces) { - // For debugging, draw the backs of the triangles in red, so that we - // notice when a shell is open - glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1); - } else { - glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 0); - } - GLfloat ambient[4] = { (float)SS.ambientIntensity, (float)SS.ambientIntensity, (float)SS.ambientIntensity, 1 }; diff --git a/src/dsc.h b/src/dsc.h index 278fc337..9da5b344 100644 --- a/src/dsc.h +++ b/src/dsc.h @@ -399,66 +399,57 @@ public: #define RGBi(r, g, b) RgbColor::From((r), (g), (b)) #define RGBf(r, g, b) RgbColor::FromFloat((float)(r), (float)(g), (float)(b)) -#define NULL_COLOR RgbColor::Default() // Note: sizeof(class RgbColor) should be exactly 4 // class RgbColor { - uint8_t useDefault; public: - uint8_t red, green, blue; + uint8_t red, green, blue, alpha; float redF(void) const { return (float)red / 255.0f; } float greenF(void) const { return (float)green / 255.0f; } float blueF(void) const { return (float)blue / 255.0f; } - - bool UseDefault(void) const { return useDefault != 0; } + float alphaF(void) const { return (float)alpha / 255.0f; } bool Equals(RgbColor c) const { - switch(c.useDefault + useDefault) { - case 0: return - c.red == red && - c.green == green && - c.blue == blue; - case 1: return false; - case 2: return true; - } - return false; + return + c.red == red && + c.green == green && + c.blue == blue && + c.alpha == alpha; } uint32_t ToPackedInt(void) const { - return red | (uint32_t)(green << 8) | (uint32_t)(blue << 16); + return + red | + (uint32_t)(green << 8) | + (uint32_t)(blue << 16) | + (uint32_t)((255 - alpha) << 24); } - static RgbColor Default(void) { + static RgbColor From(int r, int g, int b, int a = 255) { RgbColor c; - c.useDefault = 1; - // Leave r, g, b uninitialized so that Valgrind will notice - // if they are used inadvertently - return c; - } - - static RgbColor From(int r, int g, int b) { - RgbColor c; - c.useDefault = 0; c.red = (uint8_t)r; c.green = (uint8_t)g; c.blue = (uint8_t)b; + c.alpha = (uint8_t)a; return c; } - static RgbColor FromFloat(float r, float g, float b) { + static RgbColor FromFloat(float r, float g, float b, float a = 1.0) { return From( (int)(255.1f * r), (int)(255.1f * g), - (int)(255.1f * b)); + (int)(255.1f * b), + (int)(255.1f * a)); } - static RgbColor FromPackedInt(uint32_t bgr) { + static RgbColor FromPackedInt(uint32_t bgra) { return From( - (int)((bgr) & 0xff), - (int)((bgr >> 8) & 0xff), - (int)((bgr >> 16) & 0xff)); + (int)((bgra) & 0xff), + (int)((bgra >> 8) & 0xff), + (int)((bgra >> 16) & 0xff), + (int)(255 - ((bgra >> 24) & 0xff))); } }; diff --git a/src/file.cpp b/src/file.cpp index b06aca55..ba614b45 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -315,7 +315,7 @@ bool SolveSpaceUI::SaveToFile(const char *filename) { SMesh *m = &(SK.group.elem[SK.group.n-1].runningMesh); for(i = 0; i < m->l.n; i++) { STriangle *tr = &(m->l.elem[i]); - fprintf(fh, "Triangle %08x %08x " + fprintf(fh, "Triangle %08x %08x " "%.20f %.20f %.20f %.20f %.20f %.20f %.20f %.20f %.20f\n", tr->meta.face, tr->meta.color.ToPackedInt(), CO(tr->a), CO(tr->b), CO(tr->c)); @@ -555,27 +555,25 @@ bool SolveSpaceUI::LoadEntitiesFromFile(const char *file, EntityList *le, } else if(StrStartsWith(line, "Triangle ")) { STriangle tr; ZERO(&tr); - unsigned int rgb = 0; + unsigned int rgba = 0; if(sscanf(line, "Triangle %x %x " "%lf %lf %lf %lf %lf %lf %lf %lf %lf", - &(tr.meta.face), &rgb, + &(tr.meta.face), &rgba, &(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)) != 11) - { + &(tr.c.x), &(tr.c.y), &(tr.c.z)) != 11) { oops(); } - tr.meta.color = RgbColor::FromPackedInt((uint32_t)rgb); + tr.meta.color = RgbColor::FromPackedInt((uint32_t)rgba); m->AddTriangle(&tr); } else if(StrStartsWith(line, "Surface ")) { - unsigned int rgb = 0; + unsigned int rgba = 0; if(sscanf(line, "Surface %x %x %x %d %d", - &(srf.h.v), &rgb, &(srf.face), - &(srf.degm), &(srf.degn)) != 5) - { + &(srf.h.v), &rgba, &(srf.face), + &(srf.degm), &(srf.degn)) != 5) { oops(); } - srf.color = RgbColor::FromPackedInt((uint32_t)rgb); + srf.color = RgbColor::FromPackedInt((uint32_t)rgba); } else if(StrStartsWith(line, "SCtrl ")) { int i, j; Vector c; diff --git a/src/glhelper.cpp b/src/glhelper.cpp index adf6e487..348d9221 100644 --- a/src/glhelper.cpp +++ b/src/glhelper.cpp @@ -269,28 +269,31 @@ static void StippleTriangle(STriangle *tr, bool s, RgbColor rgb) glBegin(GL_TRIANGLES); } -void ssglFillMesh(RgbColor specColor, SMesh *m, uint32_t h, uint32_t s1, uint32_t s2) +void ssglFillMesh(bool useSpecColor, RgbColor specColor, + SMesh *m, uint32_t h, uint32_t s1, uint32_t s2) { RgbColor rgbHovered = Style::Color(Style::HOVERED), rgbSelected = Style::Color(Style::SELECTED); glEnable(GL_NORMALIZE); - RgbColor prevColor = NULL_COLOR; + bool hasMaterial = false; + RgbColor prevColor; glBegin(GL_TRIANGLES); for(int i = 0; i < m->l.n; i++) { STriangle *tr = &(m->l.elem[i]); RgbColor color; - if(specColor.UseDefault()) { - color = tr->meta.color; - } else { + if(useSpecColor) { color = specColor; + } else { + color = tr->meta.color; } - if(!color.Equals(prevColor)) { - GLfloat mpf[] = { color.redF(), color.greenF(), color.blueF(), 1.0f }; + if(!hasMaterial || !color.Equals(prevColor)) { + GLfloat mpf[] = { color.redF(), color.greenF(), color.blueF(), color.alphaF() }; glEnd(); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf); prevColor = color; + hasMaterial = true; glBegin(GL_TRIANGLES); } diff --git a/src/groupmesh.cpp b/src/groupmesh.cpp index 4bd392b3..9d0fa577 100644 --- a/src/groupmesh.cpp +++ b/src/groupmesh.cpp @@ -435,11 +435,13 @@ Group *Group::RunningMeshGroup(void) { void Group::DrawDisplayItems(int t) { RgbColor specColor; + bool useSpecColor; if(t == DRAWING_3D || t == DRAWING_WORKPLANE) { // force the color to something dim specColor = Style::Color(Style::DIM_SOLID); + useSpecColor = true; } else { - specColor = RgbColor::Default(); // use the model color + useSpecColor = false; // 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. @@ -458,10 +460,19 @@ void Group::DrawDisplayItems(int t) { if(gs.faces > 1) ms2 = gs.face[1].v; if(SS.GW.showShaded) { + if(SS.drawBackFaces && !displayMesh.isTransparent) { + // For debugging, draw the backs of the triangles in red, so that we + // notice when a shell is open + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); + } else { + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); + } + glEnable(GL_LIGHTING); - ssglFillMesh(specColor, &displayMesh, mh, ms1, ms2); + ssglFillMesh(useSpecColor, specColor, &displayMesh, mh, ms1, ms2); glDisable(GL_LIGHTING); } + if(SS.GW.showEdges) { ssglDepthRangeOffset(2); ssglColorRGB(Style::Color(Style::SOLID_EDGE)); diff --git a/src/mesh.cpp b/src/mesh.cpp index 7d157d93..81f31a5c 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -32,6 +32,7 @@ void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) { AddTriangle(&t); } void SMesh::AddTriangle(STriangle *st) { + if(st->meta.color.alpha != 255) isTransparent = true; l.Add(st); } diff --git a/src/polygon.h b/src/polygon.h index 5583406a..9210c023 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -226,6 +226,7 @@ public: bool flipNormal; bool keepCoplanar; bool atLeastOneDiscarded; + bool isTransparent; void Clear(void); void AddTriangle(STriangle *st); diff --git a/src/solvespace.h b/src/solvespace.h index b66ce48d..2ad6afb2 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -300,7 +300,8 @@ void ssglAxisAlignedLineLoop(double l, double r, double t, double b); extern "C" { typedef void SSGL_CALLBACK ssglCallbackFptr(void); } void ssglTesselatePolygon(GLUtesselator *gt, SPolygon *p); void ssglFillPolygon(SPolygon *p); -void ssglFillMesh(RgbColor color, SMesh *m, uint32_t h, uint32_t s1, uint32_t s2); +void ssglFillMesh(bool useSpecColor, RgbColor color, + SMesh *m, uint32_t h, uint32_t s1, uint32_t s2); void ssglDebugPolygon(SPolygon *p); void ssglDrawEdges(SEdgeList *l, bool endpointsToo); void ssglDebugMesh(SMesh *m); diff --git a/src/srf/surface.cpp b/src/srf/surface.cpp index 9f98696b..ad789323 100644 --- a/src/srf/surface.cpp +++ b/src/srf/surface.cpp @@ -489,8 +489,7 @@ typedef struct { hSSurface hs; } TrimLine; -void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, - RgbColor color) +void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, RgbColor color) { // Make the extrusion direction consistent with respect to the normal // of the sketch we're extruding. @@ -609,8 +608,7 @@ typedef struct { hSSurface d[4]; } Revolved; -void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, - RgbColor color) +void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbColor color) { SBezierLoop *sbl; diff --git a/src/style.cpp b/src/style.cpp index 8810a2b3..bf780d09 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -22,7 +22,7 @@ const Style::Default Style::Defaults[] = { { { ANALYZE }, "Analyze", RGBf(0.0, 1.0, 1.0), 1.0, }, { { DRAW_ERROR }, "DrawError", RGBf(1.0, 0.0, 0.0), 8.0, }, { { DIM_SOLID }, "DimSolid", RGBf(0.1, 0.1, 0.1), 1.0, }, - { { 0 }, NULL, NULL_COLOR, 0.0 } + { { 0 }, NULL, RGBf(0.0, 0.0, 0.0), 0.0 } }; char *Style::CnfColor(const char *prefix) { diff --git a/src/textscreens.cpp b/src/textscreens.cpp index 0e0af1e4..a3d2b554 100644 --- a/src/textscreens.cpp +++ b/src/textscreens.cpp @@ -225,6 +225,15 @@ void TextWindow::ScreenColor(int link, uint32_t v) { SS.TW.ShowEditControlWithColorPicker(v, 3, g->color); SS.TW.edit.meaning = EDIT_GROUP_COLOR; } +void TextWindow::ScreenOpacity(int link, uint32_t v) { + Group *g = SK.GetGroup(SS.TW.shown.group); + + char str[1024]; + sprintf(str, "%.2f", g->color.alphaF()); + SS.TW.ShowEditControl(22, 11, str); + SS.TW.edit.meaning = EDIT_GROUP_OPACITY; + SS.TW.edit.group.v = g->h.v; +} void TextWindow::ScreenChangeExprA(int link, uint32_t v) { Group *g = SK.GetGroup(SS.TW.shown.group); @@ -365,10 +374,13 @@ void TextWindow::ShowGroupInfo(void) { g->type == Group::LATHE) { Printf(false, - "%Bd %Ftcolor %E%Bz %Bd (%@, %@, %@) %f%D%Lf%Fl[change]%E", + "%Bd %Ftcolor %E%Bz %Bd (%@, %@, %@) %f%D%Lf%Fl[change]%E", &g->color, g->color.redF(), g->color.greenF(), g->color.blueF(), ScreenColor, top[rows-1] + 2); + Printf(false, "%Bd %Ftopacity%E %@ %f%Lf%Fl[change]%E", + g->color.alphaF(), + &TextWindow::ScreenOpacity); } else if(g->type == Group::IMPORTED) { bool sup = g->suppress; Printf(false, " %Fd%f%LP%c suppress this group's solid model", @@ -697,6 +709,22 @@ void TextWindow::EditControlDone(const char *s) { } break; } + case EDIT_GROUP_OPACITY: { + Expr *e = Expr::From(s, true); + if(e) { + double alpha = e->Eval(); + if(alpha < 0 || alpha > 1) { + Error("Opacity must be between zero and one."); + } else { + Group *g = SK.GetGroup(edit.group); + g->color.alpha = (int)(255.1f * alpha); + SS.MarkGroupDirty(g->h); + SS.ScheduleGenerateAll(); + SS.GW.ClearSuper(); + } + } + break; + } case EDIT_TTF_TEXT: { SS.UndoRemember(); Request *r = SK.request.FindByIdNoOops(edit.request); diff --git a/src/textwin.cpp b/src/textwin.cpp index 58b5c2e1..28cfa79b 100644 --- a/src/textwin.cpp +++ b/src/textwin.cpp @@ -18,14 +18,14 @@ const TextWindow::Color TextWindow::fgColors[] = { { 'i', RGBi( 0, 255, 255) }, { 'g', RGBi(160, 160, 160) }, { 'b', RGBi(200, 200, 200) }, - { 0, NULL_COLOR } + { 0, RGBi( 0, 0, 0) } }; const TextWindow::Color TextWindow::bgColors[] = { { 'd', RGBi( 0, 0, 0) }, { 't', RGBi( 34, 15, 15) }, { 'a', RGBi( 25, 25, 25) }, { 'r', RGBi(255, 255, 255) }, - { 0, NULL_COLOR } + { 0, RGBi( 0, 0, 0) } }; bool TextWindow::SPACER = false; @@ -132,7 +132,7 @@ void TextWindow::Printf(bool halfLine, const char *fmt, ...) { char fg = 'd'; char bg = 'd'; - RgbColor bgRgb = NULL_COLOR; + RgbColor bgRgb = RGBi(0, 0, 0); int link = NOT_A_LINK; uint32_t data = 0; LinkFunction *f = NULL, *h = NULL; diff --git a/src/ui.h b/src/ui.h index 0dc299f8..1012b93f 100644 --- a/src/ui.h +++ b/src/ui.h @@ -139,6 +139,7 @@ public: EDIT_GROUP_NAME = 2, EDIT_GROUP_SCALE = 3, EDIT_GROUP_COLOR = 4, + EDIT_GROUP_OPACITY = 5, // For the configuraiton screen EDIT_LIGHT_DIRECTION = 100, EDIT_LIGHT_INTENSITY = 101, @@ -254,6 +255,7 @@ public: static void ScreenChangeGroupOption(int link, uint32_t v); static void ScreenColor(int link, uint32_t v); + static void ScreenOpacity(int link, uint32_t v); static void ScreenShowListOfStyles(int link, uint32_t v); static void ScreenShowStyleInfo(int link, uint32_t v);