From f95d794af684a3481e7f79b777988893d61ae2f0 Mon Sep 17 00:00:00 2001 From: danij Date: Mon, 1 Jun 2015 17:43:47 +0100 Subject: [PATCH] Refactor|Renderer|Vertex: Moved vertex shadow offset updates into Vertex, cleanup --- .../client/include/render/rend_fakeradio.h | 9 - doomsday/apps/client/include/world/vertex.h | 25 ++- .../apps/client/src/render/r_fakeradio.cpp | 182 +++--------------- doomsday/apps/client/src/world/vertex.cpp | 150 ++++++++++++--- 4 files changed, 167 insertions(+), 199 deletions(-) diff --git a/doomsday/apps/client/include/render/rend_fakeradio.h b/doomsday/apps/client/include/render/rend_fakeradio.h index 807c0e1dcb..7952afb53c 100644 --- a/doomsday/apps/client/include/render/rend_fakeradio.h +++ b/doomsday/apps/client/include/render/rend_fakeradio.h @@ -113,15 +113,6 @@ LineSideRadioData &Rend_RadioDataForLineSide(LineSide &side); */ void Rend_RadioUpdateForLineSide(LineSide &side); -/** - * Updates all the shadow offsets for the given vertex. - * - * @pre Lineowner rings must be set up. - * - * @param vtx Vertex to be updated. - */ -void Rend_RadioUpdateVertexShadowOffsets(Vertex &vtx); - /** * Returns the global shadow darkness factor, derived from values in Config. * Assumes that light level adaptation has @em NOT yet been applied (it will be). diff --git a/doomsday/apps/client/include/world/vertex.h b/doomsday/apps/client/include/world/vertex.h index b4c353a457..432bd35a41 100644 --- a/doomsday/apps/client/include/world/vertex.h +++ b/doomsday/apps/client/include/world/vertex.h @@ -1,7 +1,7 @@ /** @file vertex.h World map vertex. * * @authors Copyright © 2003-2013 Jaakko Keränen - * @authors Copyright © 2006-2013 Daniel Swanson + * @authors Copyright © 2006-2015 Daniel Swanson * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -51,12 +51,12 @@ class Vertex : public de::MapElement, public de::MeshElement /// Head of the LineOwner rings (an array of [numLineOwners] size). The /// owner ring is a doubly, circularly linked list. The head is the owner /// with the lowest angle and the next-most being that with greater angle. - LineOwner *_lineOwners; - uint _numLineOwners; ///< Total number of line owners. + LineOwner *_lineOwners = nullptr; + uint _numLineOwners = 0; ///< Total number of line owners. // Total numbers of line owners. - uint _onesOwnerCount; - uint _twosOwnerCount; + uint _onesOwnerCount = 0; + uint _twosOwnerCount = 0; public: Vertex(de::Mesh &mesh, de::Vector2d const &origin = de::Vector2d()); @@ -92,7 +92,16 @@ class Vertex : public de::MapElement, public de::MeshElement */ inline void setOrigin(float x, float y) { return setOrigin(de::Vector2d(x, y)); } -public: // Deprecated ---------------------------------------------------------- +#if __CLIENT__ + /** + * Update all FakeRadio shadow offset coordinates for the vertex. + * + * @pre Lineowner rings must be set up. + */ + void updateShadowOffsets(); +#endif + +public: // Deprecated --------------------------------------------------------------------- /** * Returns the total number of Line owners for the vertex. @@ -130,7 +139,7 @@ class Vertex : public de::MapElement, public de::MeshElement int property(DmuArgs &args) const; private: - DENG2_PRIVATE(d) + de::Vector2d _origin; ///< Map-space coordinates. }; -#endif // DENG_WORLD_VERTEX_H +#endif // DENG_WORLD_VERTEX_H diff --git a/doomsday/apps/client/src/render/r_fakeradio.cpp b/doomsday/apps/client/src/render/r_fakeradio.cpp index ba339f1615..629bf875bd 100644 --- a/doomsday/apps/client/src/render/r_fakeradio.cpp +++ b/doomsday/apps/client/src/render/r_fakeradio.cpp @@ -1,7 +1,7 @@ /** @file r_fakeradio.cpp Faked Radiosity Lighting. * * @authors Copyright © 2003-2014 Jaakko Keränen - * @authors Copyright © 2006-2014 Daniel Swanson + * @authors Copyright © 2006-2015 Daniel Swanson * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -18,39 +18,42 @@ * 02110-1301 USA */ -//#include -#include /// @todo remove me -#include - -#include -#include - #include "de_base.h" -#include "de_render.h" +#include "render/rend_fakeradio.h" +#include /// @todo remove me +#include /// @todo remove me +#include +#include #include "world/blockmap.h" #include "world/lineowner.h" #include "world/map.h" #include "ConvexSubspace" #include "Face" +#include "MaterialAnimator" #include "SectorCluster" #include "Surface" #include "Vertex" -#include "render/rend_fakeradio.h" +#include "render/rend_main.h" using namespace de; static LineSideRadioData *lineSideRadioData; +LineSideRadioData &Rend_RadioDataForLineSide(LineSide &side) +{ + return lineSideRadioData[side.line().indexInMap() * 2 + (side.isBack()? 1 : 0)]; +} + bool Rend_RadioLineCastsShadow(Line const &line) { if(line.definesPolyobj()) return false; if(line.isSelfReferencing()) return false; // Lines with no other neighbor do not qualify for shadowing. - if(&line.v1Owner()->next().line() == &line || - &line.v2Owner()->next().line() == &line) return false; + if(&line.v1Owner()->next().line() == &line || &line.v2Owner()->next().line() == &line) + return false; return true; } @@ -72,134 +75,6 @@ bool Rend_RadioPlaneCastsShadow(Plane const &plane) return true; } -LineSideRadioData &Rend_RadioDataForLineSide(LineSide &side) -{ - return lineSideRadioData[side.line().indexInMap() * 2 + (side.isBack()? 1 : 0)]; -} - -/** - * Given two lines "connected" by shared origin coordinates (0, 0) at a "corner" - * vertex, calculate the point which lies @a distA away from @a lineA and also - * @a distB from @a lineB. The point should also be the nearest point to the - * origin (in case of parallel lines). - * - * @param lineADirection Direction vector for the "left" line. - * @param dist1 Distance from @a lineA to offset the corner point. - * @param lineBDirection Direction vector for the "right" line. - * @param dist2 Distance from @a lineB to offset the corner point. - * - * Return values: - * @param point Coordinates for the corner point are written here. Can be @c 0. - * @param lp Coordinates for the "extended" point are written here. Can be @c 0. - */ -static void cornerNormalPoint(Vector2d const &lineADirection, double dist1, - Vector2d const &lineBDirection, double dist2, - Vector2d *point, Vector2d *lp) -{ - // Any work to be done? - if(!point && !lp) return; - - // Length of both lines. - double len1 = lineADirection.length(); - double len2 = lineBDirection.length(); - - // Calculate normals for both lines. - Vector2d norm1(-lineADirection.y / len1 * dist1, lineADirection.x / len1 * dist1); - Vector2d norm2( lineBDirection.y / len2 * dist2, -lineBDirection.x / len2 * dist2); - - // Do we need to calculate the extended points, too? Check that - // the extension does not bleed too badly outside the legal shadow - // area. - if(lp) - { - *lp = lineBDirection / len2 * dist2; - } - - // Do we need to determine the intercept point? - if(!point) return; - - // Normal shift to produce the lines we need to find the intersection. - Partition lineA(lineADirection, norm1); - Partition lineB(lineBDirection, norm2); - - if(!lineA.isParallelTo(lineB)) - { - *point = lineA.intercept(lineB); - return; - } - - // Special case: parallel - // There will be no intersection at any point therefore it will not be - // possible to determine our corner point (so just use a normal as the - // point instead). - *point = norm1; -} - -/** - * @return The width (world units) of the shadow edge. It is scaled depending on - * the length of @a edge. - */ -static double shadowEdgeWidth(Vector2d const &edge) -{ - double const normalWidth = 20; //16; - double const maxWidth = 60; - - // A long edge? - double length = edge.length(); - if(length > 600) - { - double w = length - 600; - if(w > 1000) - w = 1000; - return normalWidth + w / 1000 * maxWidth; - } - - return normalWidth; -} - -void Rend_RadioUpdateVertexShadowOffsets(Vertex &vtx) -{ - if(!vtx.lineOwnerCount()) return; - - Vector2d leftDir, rightDir; - - LineOwner *base = vtx.firstLineOwner(); - LineOwner *own = base; - do - { - Line const &lineB = own->line(); - Line const &lineA = own->next().line(); - - if(&lineB.from() == &vtx) - { - rightDir = lineB.direction(); - } - else - { - rightDir = -lineB.direction(); - } - - if(&lineA.from() == &vtx) - { - leftDir = -lineA.direction(); - } - else - { - leftDir = lineA.direction(); - } - - // The left side is always flipped. - leftDir *= -1; - - cornerNormalPoint(leftDir, shadowEdgeWidth(leftDir), - rightDir, shadowEdgeWidth(rightDir), - &own->_shadowOffsets.inner, - &own->_shadowOffsets.extended); - - own = &own->next(); - } while(own != base); -} - void Rend_RadioInitForMap(Map &map) { Time begunAt; @@ -211,28 +86,23 @@ void Rend_RadioInitForMap(Map &map) map.forAllVertexs([] (Vertex &vertex) { - Rend_RadioUpdateVertexShadowOffsets(vertex); + vertex.updateShadowOffsets(); return LoopContinue; }); - /** - * The algorithm: - * - * 1. Use the BSP leaf blockmap to look for all the blocks that are - * within the line's shadow bounding box. - * - * 2. Check the ConvexSubspaces whose sector is the same as the line. - * - * 3. If any of the shadow points are in the subspace, or any of the - * shadow edges cross one of the subspace's edges (not parallel), - * link the line to the ConvexSubspace. - */ + /// The algorithm: + /// + /// 1. Use the BSP leaf blockmap to look for all the blocks that are within the line's shadow + /// bounding box. + /// 2. Check the ConvexSubspaces whose sector is the same as the line. + /// 3. If any of the shadow points are in the subspace, or any of the shadow edges cross one + /// of the subspace's edges (not parallel), link the line to the ConvexSubspace. map.forAllLines([] (Line &line) { if(Rend_RadioLineCastsShadow(line)) { // For each side of the line. - for(int i = 0; i < 2; ++i) + for(dint i = 0; i < 2; ++i) { LineSide &side = line.side(i); @@ -259,8 +129,8 @@ void Rend_RadioInitForMap(Map &map) int const localValidCount = validCount; line.map().subspaceBlockmap().forAllInBox(box, [&box, &side, &localValidCount] (void *object) { - ConvexSubspace &sub = *(ConvexSubspace *)object; - if(sub.validCount() != localValidCount) // not yet processed + auto &sub = *(ConvexSubspace *)object; + if(sub.validCount() != localValidCount) // not yet processed { sub.setValidCount(localValidCount); if(&sub.sector() == side.sectorPtr()) diff --git a/doomsday/apps/client/src/world/vertex.cpp b/doomsday/apps/client/src/world/vertex.cpp index 0df9b19652..747ffec3e8 100644 --- a/doomsday/apps/client/src/world/vertex.cpp +++ b/doomsday/apps/client/src/world/vertex.cpp @@ -1,7 +1,7 @@ /** @file vertex.cpp World map vertex. * * @authors Copyright © 2003-2013 Jaakko Keränen - * @authors Copyright © 2006-2013 Daniel Swanson + * @authors Copyright © 2006-2015 Daniel Swanson * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -21,41 +21,33 @@ #include "de_base.h" #include "world/vertex.h" +#include #include "Line" -#include "world/lineowner.h" /// @todo remove me +#include "world/lineowner.h" /// @todo remove me #include "Sector" - -#include +#if __CLIENT__ +# include "partition.h" +#endif using namespace de; -DENG2_PIMPL_NOREF(Vertex) -{ - Vector2d origin; ///< In map space. - Instance(Vector2d const &origin) : origin(origin) - {} -}; - Vertex::Vertex(Mesh &mesh, Vector2d const &origin) : MapElement(DMU_VERTEX) , MeshElement(mesh) - , _lineOwners(0) - , _numLineOwners(0) - , _onesOwnerCount(0) - , _twosOwnerCount(0) - , d(new Instance(origin)) -{} +{ + _origin = origin; +} Vector2d const &Vertex::origin() const { - return d->origin; + return _origin; } void Vertex::setOrigin(Vector2d const &newOrigin) { - if(d->origin != newOrigin) + if(_origin != newOrigin) { - d->origin = newOrigin; + _origin = newOrigin; DENG2_FOR_AUDIENCE(OriginChange, i) { i->vertexOriginChanged(*this); @@ -68,24 +60,24 @@ int Vertex::property(DmuArgs &args) const switch(args.prop) { case DMU_X: - args.setValue(DMT_VERTEX_ORIGIN, &d->origin.x, 0); + args.setValue(DMT_VERTEX_ORIGIN, &_origin.x, 0); break; case DMU_Y: - args.setValue(DMT_VERTEX_ORIGIN, &d->origin.y, 0); + args.setValue(DMT_VERTEX_ORIGIN, &_origin.y, 0); break; case DMU_XY: - args.setValue(DMT_VERTEX_ORIGIN, &d->origin.x, 0); - args.setValue(DMT_VERTEX_ORIGIN, &d->origin.y, 1); + args.setValue(DMT_VERTEX_ORIGIN, &_origin.x, 0); + args.setValue(DMT_VERTEX_ORIGIN, &_origin.y, 1); break; default: return MapElement::property(args); } - return false; // Continue iteration. + return false; // Continue iteration. } // --------------------------------------------------------------------------- -uint Vertex::lineOwnerCount() const +duint Vertex::lineOwnerCount() const { return _numLineOwners; } @@ -115,3 +107,109 @@ LineOwner *Vertex::firstLineOwner() const { return _lineOwners; } + +#if __CLIENT__ + +/** + * Given two lines "connected" by shared origin coordinates (0, 0) at a "corner" + * vertex, calculate the point which lies @a distA away from @a lineA and also + * @a distB from @a lineB. The point should also be the nearest point to the + * origin (in case of parallel lines). + * + * @param lineADirection Direction vector for the "left" line. + * @param dist1 Distance from @a lineA to offset the corner point. + * @param lineBDirection Direction vector for the "right" line. + * @param dist2 Distance from @a lineB to offset the corner point. + * + * Return values: + * @param point Coordinates for the corner point are written here. Can be @c nullptr. + * @param lp Coordinates for the "extended" point are written here. Can be @c nullptr. + */ +static void cornerNormalPoint(Vector2d const &lineADirection, ddouble dist1, + Vector2d const &lineBDirection, ddouble dist2, + Vector2d *point, Vector2d *lp) +{ + // Any work to be done? + if(!point && !lp) return; + + // Length of both lines. + ddouble len1 = lineADirection.length(); + ddouble len2 = lineBDirection.length(); + + // Calculate normals for both lines. + Vector2d norm1(-lineADirection.y / len1 * dist1, lineADirection.x / len1 * dist1); + Vector2d norm2( lineBDirection.y / len2 * dist2, -lineBDirection.x / len2 * dist2); + + // Do we need to calculate the extended points, too? Check that + // the extension does not bleed too badly outside the legal shadow + // area. + if(lp) + { + *lp = lineBDirection / len2 * dist2; + } + + // Do we need to determine the intercept point? + if(point) + { + // Normal shift to produce the lines we need to find the intersection. + Partition lineA(lineADirection, norm1); + Partition lineB(lineBDirection, norm2); + + if(lineA.isParallelTo(lineB)) + { + // There will be no intersection at any point therefore it will not be + // possible to determine our corner point (so just use a normal as the + // point instead). + *point = norm1; + } + else + { + *point = lineA.intercept(lineB); + } + } +} + +/** + * Returns the width (world units) of a shadow edge (scaled depending on the length of @a edge). + */ +static ddouble shadowEdgeWidth(Vector2d const &edge) +{ + ddouble const normalWidth = 20; //16; + ddouble const maxWidth = 60; + + // A long edge? + ddouble length = edge.length(); + if(length > 600) + { + ddouble w = length - 600; + if(w > 1000) w = 1000; + return normalWidth + w / 1000 * maxWidth; + } + + return normalWidth; +} + +void Vertex::updateShadowOffsets() +{ + LineOwner *base = firstLineOwner(); + if(!base) return; + + LineOwner *own = base; + do + { + Line const &lineB = own->line(); + Line const &lineA = own->next().line(); + + Vector2d const rightDir = (&lineB.from() == this? lineB.direction() : -lineB.direction()); + Vector2d const leftDir = (&lineA.from() == this? -lineA.direction() : lineA.direction()) * -1; // Always flipped. + + cornerNormalPoint(leftDir, shadowEdgeWidth(leftDir), + rightDir, shadowEdgeWidth(rightDir), + &own->_shadowOffsets.inner, + &own->_shadowOffsets.extended); + + own = &own->next(); + } while(own != base); +} + +#endif // __CLIENT__