Skip to content

Commit

Permalink
ShadowEdge: Reworking newly abstracted ShadowEdge (ironing out some o…
Browse files Browse the repository at this point in the history
…bvious bugs)
  • Loading branch information
danij-deng committed May 8, 2013
1 parent 0845afc commit a1c46fe
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 62 deletions.
40 changes: 36 additions & 4 deletions doomsday/client/include/render/shadowedge.h
Expand Up @@ -41,16 +41,48 @@ class ShadowEdge

void prepare(int planeIndex);

/**
* Returns the "side openness" factor for the shadow edge. This factor is
* a measure of how open the @em open range is on "this" edge of the
* shadowing surface.
*
* @see sectorOpenness()
*/
float openness() const;

float sideOpenness() const;
/**
* Returns the "sector openness" factor for the shadow edge. This factor is
* a measure of how open the @em open range is on the sector edge of the
* shadowing surface.
*
* @see openness()
*/
float sectorOpenness() const;

/**
* Returns the origin of the @em outer vertex (that which is incident with
* a map vertex from some line of the sector boundary).
*
* @see inner()
*/
Vector3d const &outer() const;

/**
* Returns the origin of the @em inner vertex (that which extends away from
* the "outer" vertex and across the shadowed surface).
*
* @see outer()
*/
Vector3d const &inner() const;

Vector3d const &outer() const;

/**
* Returns the length of the shadow edge, which is measured as the distance
* from the outer vertex origin to the inner origin.
*
* @see outer(), inner()
*/
inline coord_t length() const {
return Vector3d(outer() - inner()).abs().length();
return Vector3d(inner() - outer()).abs().length();
}

private:
Expand Down
21 changes: 10 additions & 11 deletions doomsday/client/src/render/rend_fakeradio.cpp
Expand Up @@ -473,7 +473,6 @@ static void scanNeighbors(shadowcorner_t top[2], shadowcorner_t bottom[2],
static void scanEdges(shadowcorner_t topCorners[2], shadowcorner_t bottomCorners[2],
shadowcorner_t sideCorners[2], edgespan_t spans[2], Line::Side const &side)
{
Line const &line = side.line();
int const lineSideId = side.lineSideId();

std::memset(sideCorners, 0, sizeof(shadowcorner_t) * 2);
Expand All @@ -482,11 +481,11 @@ static void scanEdges(shadowcorner_t topCorners[2], shadowcorner_t bottomCorners
for(int i = 0; i < 2; ++i)
{
binangle_t diff = 0;
LineOwner *vo = line.vertexOwner(i ^ lineSideId);
LineOwner *vo = side.line().vertexOwner(i ^ lineSideId);

Line *other = R_FindSolidLineNeighbor(side.sectorPtr(), &line, vo,
Line *other = R_FindSolidLineNeighbor(side.sectorPtr(), &side.line(), vo,
CPP_BOOL(i), &diff);
if(other && other != &line)
if(other && other != &side.line())
{
if(diff > BANG_180)
{
Expand Down Expand Up @@ -1188,8 +1187,8 @@ static void writeShadowSection2(ShadowEdge const &leftEdge, ShadowEdge const &ri
static uint const floorIndices[][4] = {{0, 1, 2, 3}, {1, 2, 3, 0}};
static uint const ceilIndices[][4] = {{0, 3, 2, 1}, {1, 0, 3, 2}};

float const outerLeftAlpha = de::min(shadowDark * (1 - leftEdge.openness()), 1.f);
float const outerRightAlpha = de::min(shadowDark * (1 - rightEdge.openness()), 1.f);
float const outerLeftAlpha = de::min(shadowDark * (1 - leftEdge.sectorOpenness()), 1.f);
float const outerRightAlpha = de::min(shadowDark * (1 - rightEdge.sectorOpenness()), 1.f);

if(!(outerLeftAlpha > .0001 && outerRightAlpha > .0001)) return;

Expand Down Expand Up @@ -1237,13 +1236,13 @@ static void writeShadowSection2(ShadowEdge const &leftEdge, ShadowEdge const &ri

// Left outer.
rcolors[idx[0]].rgba[CA] = outerLeftAlpha;
if(leftEdge.sideOpenness() < 1)
rcolors[idx[0]].rgba[CA] *= 1 - leftEdge.sideOpenness();
if(leftEdge.openness() < 1)
rcolors[idx[0]].rgba[CA] *= 1 - leftEdge.openness();

// Right outer.
rcolors[idx[1]].rgba[CA] = outerRightAlpha;
if(rightEdge.sideOpenness() < 1)
rcolors[idx[1]].rgba[CA] *= 1 - rightEdge.sideOpenness();
if(rightEdge.openness() < 1)
rcolors[idx[1]].rgba[CA] *= 1 - rightEdge.openness();

if(rendFakeRadio == 2) return;

Expand Down Expand Up @@ -1276,7 +1275,7 @@ static void writeShadowSection(BspLeaf &bspLeaf, int planeIndex, Line::Side &sid
leftEdge.prepare(planeIndex);
rightEdge.prepare(planeIndex);

if(leftEdge.openness() >= 1 && rightEdge.openness() >= 1) return;
if(leftEdge.sectorOpenness() >= 1 && rightEdge.sectorOpenness() >= 1) return;

writeShadowSection2(leftEdge, rightEdge, suf->normal()[VZ] > 0, shadowDark);
}
Expand Down
101 changes: 54 additions & 47 deletions doomsday/client/src/render/shadowedge.cpp
Expand Up @@ -36,15 +36,15 @@ DENG2_PIMPL_NOREF(ShadowEdge)

Vector3d inner;
Vector3d outer;
float sectorOpenness;
float openness;
float sideOpenness;

Instance(BspLeaf &bspLeaf, Line::Side &side, int edge)
: bspLeaf(&bspLeaf),
side(&side),
edge(edge),
openness(0),
sideOpenness(0)
sectorOpenness(0),
openness(0)
{}
};

Expand Down Expand Up @@ -107,24 +107,27 @@ void ShadowEdge::prepare(int planeIndex)
{
Plane const &plane = d->side->sector().plane(planeIndex);

// Determine the 'openness' of the edge. If the edge is open, there won't be
// a shadow at all. Open neighbors cause some changes in the polygon corner
// vertices (placement, opacity).
coord_t fz = 0, bz = 0, bhz = 0;
if(d->side->back().hasSections())
// Determine the 'openness' of the wall edge sector. If the sector is open,
// there won't be a shadow at all. Open neighbor sectors cause some changes
// in the polygon corner vertices (placement, opacity).

d->sectorOpenness = -1; // Init for sanity check.

if(d->side->back().hasSections() && d->side->back().hasSector())
{
Sector const *frontSec = d->side->sectorPtr();
Sector const *backSec = d->side->back().sectorPtr();

coord_t fz = 0, bz = 0, bhz = 0;
setRelativeHeights(frontSec, backSec, planeIndex, &fz, &bz, &bhz);

Surface const &wallEdgeSurface = d->side->surface(planeIndex == Plane::Ceiling? Line::Side::Top : Line::Side::Bottom);

d->openness = -1; // Init for sanity check.
d->sectorOpenness = -1;

if(fz < bz && !wallEdgeSurface.hasMaterial())
{
d->openness = 2; // Consider it fully open.
d->sectorOpenness = 2; // Consider it fully open.
}
else
{
Expand All @@ -136,16 +139,16 @@ void ShadowEdge::prepare(int planeIndex)
{
if(backSec->planeSurface(otherPlaneIndex).hasSkyMaskedMaterial())
{
d->openness = 2; // Consider it fully open.
d->sectorOpenness = 2; // Consider it fully open.
}
else
{
d->openness = opennessFactor(fz, bz, bhz);
d->sectorOpenness = opennessFactor(fz, bz, bhz);
}
}
else
{
d->openness = 0; // Consider it fully closed.
d->sectorOpenness = 0; // Consider it fully closed.
}
}
else
Expand All @@ -155,70 +158,74 @@ void ShadowEdge::prepare(int planeIndex)
// the location of any secret areas (false walls)).
if(R_MiddleMaterialCoversOpening(*d->side))
{
d->openness = 0; // Consider it fully closed.
d->sectorOpenness = 0; // Consider it fully closed.
}
else
{
d->openness = opennessFactor(fz, bz, bhz);
d->sectorOpenness = opennessFactor(fz, bz, bhz);
}
}
}

// Sanity check.
DENG_ASSERT(d->openness >= 0);
}
else
{
d->sectorOpenness = 0;
}

// Sanity check.
DENG_ASSERT(d->sectorOpenness >= 0);

// Only calculate the remaining values when the edge is at least partially open.
if(d->openness >= 1) return;
if(d->sectorOpenness >= 1) return;

// Find the neighbor of this edge and determine its 'openness'.
// Find the neighbor of this wall section and determine the relative
// 'openness' of it's plane heights vs those of "this" wall section.

LineOwner *vo = d->side->line().vertexOwner(d->side->lineSideId() ^ d->edge)->_link[d->edge ^ 1];
Line *neighbor = &vo->line();

if(neighbor != &d->side->line() && !neighbor->hasBackSections() &&
(neighbor->isBspWindow()) &&
neighbor->frontSectorPtr() != d->bspLeaf->sectorPtr())
if(neighbor == &d->side->line())
{
// A one-way window, open side.
d->sideOpenness = 1;
d->openness = 1; // Fully open.
}
else if(!(neighbor == &d->side->line() || !neighbor->hasBackSections()))
else if(neighbor->isSelfReferencing()) /// @todo Skip over these? -ds
{
d->openness = 1;
}
else
{
// Choose the correct side of the neighbor (determined by which vertex is shared).
Line::Side *otherSide;
if(&neighbor->vertex(d->edge ^ 1) == &d->side->vertex(d->edge))
otherSide = &neighbor->front();
else
otherSide = &neighbor->back();

Sector *othersec = otherSide->sectorPtr();

if(R_MiddleMaterialCoversOpening(otherSide->back()))
int x = d->side->lineSideId() ^ d->edge;
Line::Side *otherSide = &neighbor->side(&d->side->line().vertex(x) == &neighbor->from()? d->edge ^ 1 : d->edge);
if(!otherSide->hasSections() && otherSide->back().hasSector())
{
d->sideOpenness = 0;
// A one-way window, open side.
d->openness = 1;
}
else if(neighbor->isSelfReferencing())
else if(!otherSide->hasSector() ||
(otherSide->back().hasSector() && R_MiddleMaterialCoversOpening(*otherSide)))
{
d->sideOpenness = 1;
d->openness = 0;
}
else
else if(otherSide->back().hasSector())
{
// Its a normal neighbor.
if(otherSide->sectorPtr() != d->side->sectorPtr() &&
!((plane.type() == Plane::Floor && othersec->ceiling().visHeight() <= plane.visHeight()) ||
(plane.type() == Plane::Ceiling && othersec->floor().height() >= plane.visHeight())))
Sector const *backSec = otherSide->back().sectorPtr();
if(backSec != d->side->sectorPtr() &&
!((plane.type() == Plane::Floor && backSec->ceiling().visHeight() <= plane.visHeight()) ||
(plane.type() == Plane::Ceiling && backSec->floor().height() >= plane.visHeight())))
{
Sector const *frontSec = d->side->sectorPtr();
Sector const *backSec = otherSide->sectorPtr();

coord_t fz = 0, bz = 0, bhz = 0;
setRelativeHeights(frontSec, backSec, planeIndex, &fz, &bz, &bhz);
d->sideOpenness = opennessFactor(fz, bz, bhz);

d->openness = opennessFactor(fz, bz, bhz);
}
}
}

if(d->sideOpenness < 1)
if(d->openness < 1)
{
vo = d->side->line().vertexOwner(d->side->lineSideId() ^ d->edge);
if(d->edge) vo = &vo->prev();
Expand Down Expand Up @@ -250,9 +257,9 @@ float ShadowEdge::openness() const
return d->openness;
}

float ShadowEdge::sideOpenness() const
float ShadowEdge::sectorOpenness() const
{
return d->sideOpenness;
return d->sectorOpenness;
}

} // namespace de

0 comments on commit a1c46fe

Please sign in to comment.