From 2e9fdce08ad3f5d1eeac1f15863db2c31031119a Mon Sep 17 00:00:00 2001 From: danij Date: Tue, 30 Apr 2013 14:26:48 +0100 Subject: [PATCH] Refactor|Map Renderer: Further cleanup of wall section light level smoothing algorithm --- doomsday/client/src/render/rend_main.cpp | 114 +++++++++++------------ 1 file changed, 56 insertions(+), 58 deletions(-) diff --git a/doomsday/client/src/render/rend_main.cpp b/doomsday/client/src/render/rend_main.cpp index 90a813c883..8911af35fa 100644 --- a/doomsday/client/src/render/rend_main.cpp +++ b/doomsday/client/src/render/rend_main.cpp @@ -1489,6 +1489,8 @@ static Line::Side *findSideBlendNeighbor(Line::Side const &side, bool right, bin { LineOwner const *farVertOwner = side.line().vertexOwner(side.lineSideId() ^ (int)right); + if(diff) *diff = 0; + Line *neighbor; if(R_SideBackClosed(side)) { @@ -1509,81 +1511,79 @@ static Line::Side *findSideBlendNeighbor(Line::Side const &side, bool right, bin return &neighbor->back(); } +/** + * Determines whether light level delta smoothing should be performed for + * the given pair of map surfaces (which are assumed to share an edge). + * + * Yes if the angle between the two lines is less than 45 degrees. + * @todo Should be user customizable with a Material property. -ds + * + * @param sufA The "left" map surface which shares an edge with @a sufB. + * @param sufB The "right" map surface which shares an edge with @a sufA. + * @param angleDiff Angle difference (i.e., normal delta) between the two surfaces. + */ +static bool shouldSmoothLightLevels(Surface &sufA, Surface &sufB, binangle_t angleDiff) +{ + DENG_UNUSED(sufA); + DENG_UNUSED(sufB); + return INRANGE_OF(angleDiff, BANG_180, BANG_45); +} + /** * The DOOM lighting model applies a sector light level delta when drawing walls * based on their 2D world angle. * * @param side Line side to calculate light level deltas for. - * @param deltaL Light delta for the left edge written here. Can be @c 0. - * @param deltaR Light delta for the right edge written here. Can be @c 0. + * @param deltaL Light delta for the left edge written here. + * @param deltaR Light delta for the right edge written here. * * @todo: Use the half-edge rings instead of LineOwners. */ -static void sideLightLevelDeltas(Line::Side const &side, float *deltaL, float *deltaR) +static void sideLightLevelDeltas(Line::Side &side, float &deltaL, float &deltaR) { - // Disabled? - if(!(rendLightWallAngle > 0)) - { - if(deltaL) *deltaL = 0; - if(deltaR) *deltaR = 0; + deltaL = 0; + deltaR = 0; + + // Are light level deltas disabled? + if(rendLightWallAngle <= 0) return; - } - Vector3f sideNormal = side.middle().normal(); - float delta = calcLightLevelDelta(sideNormal); + deltaL = deltaR = calcLightLevelDelta(side.middle().normal()); - // If smoothing is disabled use this delta for left and right edges. - // Must forcibly disable smoothing for polyobj lines as they have - // no owner rings. - if(!rendLightWallAngleSmooth || side.line().isFromPolyobj()) - { - if(deltaL) *deltaL = delta; - if(deltaR) *deltaR = delta; - return; - } + // Is delta smoothing disabled? + if(!rendLightWallAngleSmooth) return; + // ...always for polyobj lines (no owner rings). + if(side.line().isFromPolyobj()) return; - // Find the left neighbour line for which we will calculate the - // lightlevel delta and then blend with this to produce the value for - // the left edge. Blend iff the angle between the two lines is less - // than 45 degrees. - if(deltaL) - { - binangle_t diff = 0; - Line::Side *other = findSideBlendNeighbor(side, false /*left neighbor*/, &diff); - if(other && INRANGE_OF(diff, BANG_180, BANG_45)) - { - Vector3f otherNormal = other->middle().normal(); + /* + * Smoothing is enabled, so find the neighbor sides for each edge which + * we will use to calculate the averaged lightlevel delta for each. + */ + binangle_t angleDiff; - // Average normals. - otherNormal += sideNormal; - otherNormal *= 1.f / 2; + if(Line::Side *otherSide = findSideBlendNeighbor(side, false /*left neighbor*/, &angleDiff)) + { + Surface &sufA = side.middle(); + Surface &sufB = otherSide->middle(); - *deltaL = calcLightLevelDelta(otherNormal); - } - else + if(shouldSmoothLightLevels(sufA, sufB, angleDiff)) { - *deltaL = delta; + // Average normals. + Vector3f avgNormal = Vector3f(sufA.normal() + sufB.normal()) / 2; + deltaL = calcLightLevelDelta(avgNormal); } } - // Do the same for the right edge but with the right neighbor line. - if(deltaR) + // Do the same for the right edge but with the right neighbor side. + if(Line::Side *otherSide = findSideBlendNeighbor(side, true /*right neighbor*/, &angleDiff)) { - binangle_t diff = 0; - Line::Side *other = findSideBlendNeighbor(side, true /*right neighbor*/, &diff); - if(other && INRANGE_OF(diff, BANG_180, BANG_45)) + Surface &sufA = side.middle(); + Surface &sufB = otherSide->middle(); + if(shouldSmoothLightLevels(sufA, sufB, angleDiff)) { - Vector3f otherNormal = other->middle().normal(); - // Average normals. - otherNormal += sideNormal; - otherNormal *= 1.f / 2; - - *deltaR = calcLightLevelDelta(otherNormal); - } - else - { - *deltaR = delta; + Vector3f avgNormal = Vector3f(sufA.normal() + sufB.normal()) / 2; + deltaR = calcLightLevelDelta(avgNormal); } } } @@ -1670,12 +1670,10 @@ static bool writeWallSection(HEdge &hedge, int section, Vector2f materialScale((surface.flags() & DDSUF_MATERIAL_FLIPH)? -1 : 1, (surface.flags() & DDSUF_MATERIAL_FLIPV)? -1 : 1); - Vector3d texTL(hedge.fromOrigin().x, - hedge.fromOrigin().y, + Vector3d texTL(hedge.fromOrigin(), WallDivNode_Height(WallDivs_Last(leftWallDivs))); - Vector3d texBR(hedge.toOrigin().x, - hedge.toOrigin().y, + Vector3d texBR(hedge.toOrigin(), WallDivNode_Height(WallDivs_First(rightWallDivs))); // Determine which Material to use. @@ -1790,7 +1788,7 @@ static bool writeWallSection(HEdge &hedge, int section, } else { - sideLightLevelDeltas(hedge.lineSide(), &deltaL, &deltaR); + sideLightLevelDeltas(hedge.lineSide(), deltaL, deltaR); // Linear interpolation of the line light deltas to the edges of the hedge. coord_t const &lineLength = hedge.line().length();