Skip to content

Commit

Permalink
BiasSurface: Cleanup; more apidocs
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Aug 1, 2013
1 parent 34c6c4c commit 0b8c4f7
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 81 deletions.
45 changes: 35 additions & 10 deletions doomsday/client/include/render/biassurface.h
Expand Up @@ -29,8 +29,7 @@ class BiasSource;
class BiasTracker;

/**
* Stores surface data for the Shadow Bias lighting model (e.g., per-vertex
* illumination and casted source lighting contributions).
* @ingroup render
*/
class BiasSurface
{
Expand All @@ -42,7 +41,7 @@ class BiasSurface
/**
* Construct a new surface.
*
* @param size Number of vertices.
* @param size Number of vertices.
*/
BiasSurface(int size);

Expand All @@ -55,16 +54,38 @@ class BiasSurface

void setLastUpdateOnFrame(uint newLastUpdateFrameNumber);

void clearAffected();

void addAffected(float intensity, BiasSource *source);

void updateAffection(BiasTracker &changes);
/**
* Remove all light contributors. Existing contributions are put into a
* "latent" state, so that if they are added again the contribution is then
* re-activated and no lighting changes will occur (appears seamless).
*
* @see addContributor()
*/
void clearContributors();

void updateAfterMove();
/**
* Add a new light contributor. After which lighting changes at the source
* will be tracked and routed to map point illuminations when necessary
* (i.e., when lighting is next evaluated for the point).
*
* All contributors are assigned a unique index (when added) that can be
* used to reference the contributor later.
*
* @note At most @ref VertexIllum::MAX_CONTRIBUTORS can contribute lighting.
* Once capacity is reached adding a new contributor will result in the
* weakest contributor (i.e., smallest intensity when added) being dropped
* and it's index assigned to the 'new' contributor. If the weakest is the
* new contributor then nothing will happen.
*
* @param source Source of the light contribution.
* @param intensity Strength of the contribution from the source.
*
* @see contributor()
*/
void addContributor(BiasSource *source, float intensity);

/**
* Returns a light source contributor by @a index.
* Returns the source of a light contributor by @a index.
*/
BiasSource &contributor(int index) const;

Expand All @@ -74,6 +95,10 @@ class BiasSurface
*/
uint timeOfLatestContributorUpdate() const;

void updateAffection(BiasTracker &changes);

void updateAfterMove();

/**
* Perform lighting for the supplied geometry. It is assumed that this
* geometry has the @em same number of vertices as the bias surface.
Expand Down
149 changes: 82 additions & 67 deletions doomsday/client/src/render/biassurface.cpp
Expand Up @@ -38,32 +38,27 @@ using namespace de;
/// Ignore intensities below this threshold when accumulating contributions.
static float const MIN_INTENSITY = .005f;

/// Maximum number of sources which can contribute light to a vertex.
static int const MAX_CONTRIBUTORS = 6;

static int lightSpeed = 130; //cvar
static int devUpdateAffected = true; //cvar
static int devUseSightCheck = true; //cvar

static byte activeContributors;
static byte changedContributions;

/**
* Stores map point lighting information for the Shadow Bias lighting model.
* Used in conjunction with a BiasSurface (for routing change notifications).
*
* @ingroup render
*/
class VertexIllum
{
BiasSurface &surface; ///< The owning surface.
Vector3f color; ///< Current light color.
Vector3f dest; ///< Destination light color (interpolated to).
uint updateTime; ///< When the value was calculated.
bool interpolating; ///< Set to @c true during interpolation.

/**
* Cast lighting contributions from each source that affects the map point.
* Order is the same as that in the affected surface.
*/
Vector3f casted[MAX_CONTRIBUTORS];
public:
/// Maximum number of light contributions.
static int const MAX_CONTRIBUTORS = 6;

public:
VertexIllum(BiasSurface &surface)
VertexIllum(BiasSurface *surface)
: surface(surface),
updateTime(0),
interpolating(false)
Expand All @@ -88,16 +83,19 @@ class VertexIllum
{
if(activeContributors & changedContributions)
{
/// @todo Do not assume the current map.
Map &map = App_World().map();

/*
* Recalculate the contribution for each light.
* We can reuse the previously calculated value for a source
* if it hasn't changed.
* We can reuse the previously calculated value for a source if
* it hasn't changed.
*/
for(int i = 0; i < MAX_CONTRIBUTORS; ++i)
{
if(activeContributors & changedContributions & (1 << i))
{
updateContribution(i, point, normalAtPoint);
updateContribution(i, point, normalAtPoint, map.bspRoot());
}
}
}
Expand All @@ -110,6 +108,7 @@ class VertexIllum
}

/// @copydoc evaluate()
/// @todo refactor away
void evaluate(ColorRawf &color, Vector3d const &point,
Vector3f const &normalAtPoint, uint biasTime)
{
Expand All @@ -121,7 +120,7 @@ class VertexIllum

private:
/**
* Returns a previous light contribution by unique contributor index.
* Returns a previous light contribution by unique contributor @a index.
*/
inline Vector3f &contribution(int index)
{
Expand All @@ -132,7 +131,8 @@ class VertexIllum
/**
* Update any changed lighting contributions.
*
* @param surfacePoint Position of the vertex in the map coordinate space.
* @param activeContributors Bit field denoting the active contributors.
* @param biasTime Time in milliseconds of the last bias frame update.
*/
void applyLightingChanges(byte activeContributors, uint biasTime)
{
Expand Down Expand Up @@ -181,23 +181,24 @@ class VertexIllum
// This is what we will be interpolating to.
dest = newColor;
interpolating = true;
updateTime = surface.timeOfLatestContributorUpdate();
updateTime = surface->timeOfLatestContributorUpdate();
}

#undef COLOR_CHANGE_THRESHOLD
}

/**
* Update the lighting contribution for the specified contributor @a index.
* Update lighting contribution for the specified contributor @a index.
*
* @param index Unique index of the contributor.
* @param point Point in the map to evaluate.
* @param normalAtPoint Surface normal at @a point.
* @param bspRoot Root BSP element for the map.
*/
void updateContribution(int index, Vector3d const &point,
Vector3f const &normalAtPoint)
Vector3f const &normalAtPoint, MapElement &bspRoot)
{
BiasSource const &source = surface.contributor(index);
BiasSource const &source = surface->contributor(index);

Vector3f &casted = contribution(index);

Expand All @@ -215,12 +216,9 @@ class VertexIllum

Vector3d sourceToSurface = source.origin() - point;

/// @todo Do not assume the current map.
MapElement &bspRoot = App_World().map().bspRoot();

if(devUseSightCheck &&
!LineSightTest(source.origin(),
point + sourceToSurface / 100).trace(bspRoot))
!LineSightTest(source.origin(), point + sourceToSurface / 100)
.trace(bspRoot))
{
// LOS fail.
// This affecting source does not contribute any light.
Expand All @@ -244,7 +242,10 @@ class VertexIllum
}

/**
* Interpolate between current and destination.
* Interpolate color from current to destination.
*
* @param result Interpolated color will be written here.
* @param currentTime Time in milliseconds of the last bias frame update.
*/
void lerp(Vector3f &result, uint currentTime)
{
Expand All @@ -269,6 +270,18 @@ class VertexIllum
result = color + (dest - color) * inter;
}
}

BiasSurface *surface; ///< The "control" surface.
Vector3f color; ///< Current light color.
Vector3f dest; ///< Destination light color (interpolated to).
uint updateTime; ///< When the value was calculated.
bool interpolating; ///< Set to @c true during interpolation.

/**
* Cast lighting contributions from each source that affects the map point.
* Order is the same as that in the affected surface.
*/
Vector3f casted[MAX_CONTRIBUTORS];
};

struct Contributor
Expand All @@ -277,6 +290,8 @@ struct Contributor
float influence;
};

#define MAX_CONTRIBUTORS VertexIllum::MAX_CONTRIBUTORS

/**
* @todo Defer allocation of most data -- adopt a 'fly-weight' approach.
*
Expand Down Expand Up @@ -353,12 +368,12 @@ void BiasSurface::setLastUpdateOnFrame(uint newLastUpdateFrameNumber)
d->lastUpdateOnFrame = newLastUpdateFrameNumber;
}

void BiasSurface::clearAffected()
void BiasSurface::clearContributors()
{
d->activeContributors = 0;
}

void BiasSurface::addAffected(float intensity, BiasSource *source)
void BiasSurface::addContributor(BiasSource *source, float intensity)
{
if(!source) return;

Expand Down Expand Up @@ -434,40 +449,6 @@ void BiasSurface::addAffected(float intensity, BiasSource *source)
d->activeContributors |= 1 << slot;
}

void BiasSurface::updateAffection(BiasTracker &changes)
{
// All contributions from changed sources will need to be updated.

Contributor *ctbr = d->contributors;
for(int i = 0; i < MAX_CONTRIBUTORS; ++i, ctbr++)
{
if(!ctbr->source)
continue;

/// @todo optimize: This O(n) lookup can be avoided if we 1) reference
/// sources by unique in-map index, and 2) re-index source references
/// here upon deletion. The assumption being that affection changes
/// occur far more frequently.
if(changes.check(App_World().map().toIndex(*ctbr->source)))
{
d->changedContributions |= 1 << i;
break;
}
}
}

void BiasSurface::updateAfterMove()
{
Contributor *ctbr = d->contributors;
for(int i = 0; i < MAX_CONTRIBUTORS; ++i, ctbr++)
{
if(ctbr->source)
{
ctbr->source->forceUpdate();
}
}
}

BiasSource &BiasSurface::contributor(int index) const
{
if(index >= 0 && index < MAX_CONTRIBUTORS &&
Expand Down Expand Up @@ -508,6 +489,40 @@ uint BiasSurface::timeOfLatestContributorUpdate() const
return latest;
}

void BiasSurface::updateAffection(BiasTracker &changes)
{
// All contributions from changed sources will need to be updated.

Contributor *ctbr = d->contributors;
for(int i = 0; i < MAX_CONTRIBUTORS; ++i, ctbr++)
{
if(!ctbr->source)
continue;

/// @todo optimize: This O(n) lookup can be avoided if we 1) reference
/// sources by unique in-map index, and 2) re-index source references
/// here upon deletion. The assumption being that affection changes
/// occur far more frequently.
if(changes.check(App_World().map().toIndex(*ctbr->source)))
{
d->changedContributions |= 1 << i;
break;
}
}
}

void BiasSurface::updateAfterMove()
{
Contributor *ctbr = d->contributors;
for(int i = 0; i < MAX_CONTRIBUTORS; ++i, ctbr++)
{
if(ctbr->source)
{
ctbr->source->forceUpdate();
}
}
}

void BiasSurface::lightPoly(Vector3f const &surfaceNormal, uint biasTime,
int vertCount, rvertex_t const *positions, ColorRawf *colors)
{
Expand All @@ -519,7 +534,7 @@ void BiasSurface::lightPoly(Vector3f const &surfaceNormal, uint biasTime,
{
for(int i = 0; i < d->illums.count(); ++i)
{
d->illums[i] = new VertexIllum(*this);
d->illums[i] = new VertexIllum(this);
}
}

Expand Down
4 changes: 2 additions & 2 deletions doomsday/client/src/world/bspleaf.cpp
Expand Up @@ -295,7 +295,7 @@ DENG2_PIMPL(BspLeaf)

bsuf.setLastUpdateOnFrame(lastChangeFrame);

bsuf.clearAffected();
bsuf.clearContributors();

Plane const &plane = sector->plane(group);
Surface const &surface = plane.surface();
Expand Down Expand Up @@ -325,7 +325,7 @@ DENG2_PIMPL(BspLeaf)
if(sourceToSurface.dot(surface.normal()) < 0)
continue;

bsuf.addAffected(source->evaluateIntensity() / de::max(distance, 1.0), source);
bsuf.addContributor(source, source->evaluateIntensity() / de::max(distance, 1.0));
}
}

Expand Down
4 changes: 2 additions & 2 deletions doomsday/client/src/world/segment.cpp
Expand Up @@ -104,7 +104,7 @@ DENG2_PIMPL(Segment)

bsuf.setLastUpdateOnFrame(lastChangeFrame);

bsuf.clearAffected();
bsuf.clearContributors();

Surface const &surface = lineSide->middle();
Vector2d const &from = self.from().origin();
Expand All @@ -130,7 +130,7 @@ DENG2_PIMPL(Segment)
if(sourceToSurface.dot(surface.normal()) < 0)
continue;

bsuf.addAffected(source->evaluateIntensity() / de::max(distance, 1.0), source);
bsuf.addContributor(source, source->evaluateIntensity() / de::max(distance, 1.0));
}
}
#endif
Expand Down

0 comments on commit 0b8c4f7

Please sign in to comment.