Skip to content

Commit

Permalink
Refactor|Renderer|Vertex: Moved vertex shadow offset updates into Ver…
Browse files Browse the repository at this point in the history
…tex, cleanup
  • Loading branch information
danij-deng committed Jun 1, 2015
1 parent 986fbad commit f95d794
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 199 deletions.
9 changes: 0 additions & 9 deletions doomsday/apps/client/include/render/rend_fakeradio.h
Expand Up @@ -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).
Expand Down
25 changes: 17 additions & 8 deletions doomsday/apps/client/include/world/vertex.h
@@ -1,7 +1,7 @@
/** @file vertex.h World map vertex.
*
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2006-2013 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2006-2015 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
182 changes: 26 additions & 156 deletions 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 <jaakko.keranen@iki.fi>
* @authors Copyright © 2006-2014 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2006-2015 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
Expand All @@ -18,39 +18,42 @@
* 02110-1301 USA</small>
*/

//#include <de/memoryzone.h>
#include <de/vector1.h> /// @todo remove me
#include <de/Vector>

#include <de/Error>
#include <de/Log>

#include "de_base.h"
#include "de_render.h"
#include "render/rend_fakeradio.h"

#include <de/memoryzone.h> /// @todo remove me
#include <de/vector1.h> /// @todo remove me
#include <de/Log>
#include <de/Vector>
#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;
}
Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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())
Expand Down

0 comments on commit f95d794

Please sign in to comment.