From 73844f7202b6b72ddeb26623efa1fd47ce6b514d Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 18 Nov 2016 10:56:35 +0000 Subject: [PATCH] Draw triangle back faces like the front, unless we draw them in red. The configuration option "draw back faces in red" aids debugging, in that it allows to visually identify a non-watertight mesh. When it is disabled, or when the mesh is transparent, we used to not draw them at all before this commit; after, they are drawn just like the front faces. This has two consequences: 1. Inner surfaces of non-watertight meshes are not see-through anymore. That used to be the behavior in version 2.0, and it was accidentally broken in 2.1. 2. Transparent meshes look *much* better. 3. Solids made from a union of a non-transparent and a transparent one look sensibly at all. This commit also updates the OpenGL 1 renderer to let it render such meshes correctly. --- src/groupmesh.cpp | 2 ++ src/render/rendergl1.cpp | 32 ++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/groupmesh.cpp b/src/groupmesh.cpp index 365423fa..261148df 100644 --- a/src/groupmesh.cpp +++ b/src/groupmesh.cpp @@ -476,6 +476,8 @@ void Group::DrawMesh(DrawMeshAs how, Canvas *canvas) { fillBack.layer = fillFront.layer; fillBack.color = RgbaColor::FromFloat(1.0f, 0.1f, 0.1f); hcfBack = canvas->GetFill(fillBack); + } else { + hcfBack = hcfFront; } // Draw the shaded solid into the depth buffer for hidden line removal, diff --git a/src/render/rendergl1.cpp b/src/render/rendergl1.cpp index 95decf9e..832a1724 100644 --- a/src/render/rendergl1.cpp +++ b/src/render/rendergl1.cpp @@ -600,30 +600,40 @@ void OpenGl1Renderer::DrawPolygon(const SPolygon &p, hFill hcf) { void OpenGl1Renderer::DrawMesh(const SMesh &m, hFill hcfFront, hFill hcfBack) { UnSelectPrimitive(); - Fill *frontFill = SelectFill(hcfFront); - ssglMaterialRGBA(GL_FRONT, frontFill->color); + RgbaColor frontColor = {}, + backColor = {}; + Fill *frontFill = SelectFill(hcfFront); + frontColor = frontFill->color; + + ssglMaterialRGBA(GL_FRONT, frontFill->color); if(hcfBack.v != 0) { Fill *backFill = fills.FindById(hcfBack); + backColor = backFill->color; ssassert(frontFill->layer == backFill->layer && frontFill->zIndex == backFill->zIndex, "frontFill and backFill should belong to the same depth range"); ssassert(frontFill->pattern == backFill->pattern, "frontFill and backFill should have the same pattern"); - ssglMaterialRGBA(GL_BACK, backFill->color); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); + ssglMaterialRGBA(GL_BACK, backFill->color); } else { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); } - RgbaColor frontColor = {}; + RgbaColor triangleColor = {}; glEnable(GL_LIGHTING); glBegin(GL_TRIANGLES); for(const STriangle &tr : m.l) { - if(frontFill->color.IsEmpty()) { - if(frontColor.IsEmpty() || !frontColor.Equals(tr.meta.color)) { - frontColor = tr.meta.color; - ssglMaterialRGBA(GL_FRONT, frontColor); + if(frontColor.IsEmpty() || backColor.IsEmpty()) { + if(triangleColor.IsEmpty() || !triangleColor.Equals(tr.meta.color)) { + triangleColor = tr.meta.color; + if(frontColor.IsEmpty()) { + ssglMaterialRGBA(GL_FRONT, triangleColor); + } + if(backColor.IsEmpty()) { + ssglMaterialRGBA(GL_BACK, triangleColor); + } } } @@ -714,6 +724,11 @@ void OpenGl1Renderer::UpdateProjection(bool flip) { 0, 0, 1, 0, 0, 0, clp, 1); glMultMatrixd(mat); + + // If we flip the framebuffer, then we also flip the handedness + // of the coordinate system, and so the face winding order. + glFrontFace(flip ? GL_CW : GL_CCW); + // Before that, we apply the rotation Vector projRight = camera.projRight, projUp = camera.projUp, @@ -723,6 +738,7 @@ void OpenGl1Renderer::UpdateProjection(bool flip) { n.x, n.y, n.z, 0, 0, 0, 0, 1); glMultMatrixd(mat); + // And before that, the translation Vector offset = camera.offset; MakeMatrix(mat, 1, 0, 0, offset.x,