diff --git a/src/groupmesh.cpp b/src/groupmesh.cpp index 261148df..6d1b2a7a 100644 --- a/src/groupmesh.cpp +++ b/src/groupmesh.cpp @@ -416,6 +416,11 @@ void Group::GenerateDisplayItems() { } } + // If we render this mesh, we need to know whether it's transparent, + // and we'll want all transparent triangles last, to make the depth test + // work correctly. + displayMesh.PrecomputeTransparency(); + displayDirty = false; } } diff --git a/src/mesh.cpp b/src/mesh.cpp index 4231a198..d8bf9591 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -34,8 +34,6 @@ void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) { AddTriangle(&t); } void SMesh::AddTriangle(const STriangle *st) { - RgbaColor color = st->meta.color; - if(!color.IsEmpty() && color.alpha != 255) isTransparent = true; l.Add(st); } @@ -1091,3 +1089,16 @@ void SOutlineList::MakeFromCopyOf(SOutlineList *sol) { l.Add(so); } } + +void SMesh::PrecomputeTransparency() { + std::sort(l.begin(), l.end(), + [&](const STriangle &sta, const STriangle &stb) { + RgbaColor colora = sta.meta.color, + colorb = stb.meta.color; + bool opaquea = colora.IsEmpty() || colora.alpha == 255, + opaqueb = colorb.IsEmpty() || colorb.alpha == 255; + + if(!opaquea || !opaqueb) isTransparent = true; + return (opaquea != opaqueb && opaquea == true); + }); +} diff --git a/src/polygon.h b/src/polygon.h index 2bd0f8ab..072cd9c1 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -276,6 +276,8 @@ public: void MakeEdgesInPlaneInto(SEdgeList *sel, Vector n, double d); void MakeOutlinesInto(SOutlineList *sol, EdgeKind type); + void PrecomputeTransparency(); + bool IsEmpty() const; void RemapFaces(Group *g, int remap); diff --git a/src/srf/surface.cpp b/src/srf/surface.cpp index a068ead3..21c628e1 100644 --- a/src/srf/surface.cpp +++ b/src/srf/surface.cpp @@ -441,7 +441,6 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) { for(i = start; i < sm->l.n; i++) { STriangle *st = &(sm->l.elem[i]); st->meta = meta; - if(st->meta.color.alpha != 255) sm->isTransparent = true; st->an = NormalAt(st->a.x, st->a.y); st->bn = NormalAt(st->b.x, st->b.y); st->cn = NormalAt(st->c.x, st->c.y);