From 007ad223dcb6c11f5a0c459a7f5a483dc09ba31b Mon Sep 17 00:00:00 2001 From: danij Date: Tue, 9 Apr 2013 22:05:45 +0100 Subject: [PATCH] Refactor|LineDef: Extracted obsolete functionality from LineDef - unitVector() moved to particle renderer - lightLevelDelta() moved to map geometry construction --- doomsday/client/include/map/linedef.h | 28 +-- doomsday/client/src/map/linedef.cpp | 193 +++---------------- doomsday/client/src/render/rend_main.cpp | 133 ++++++++++++- doomsday/client/src/render/rend_particle.cpp | 42 +++- 4 files changed, 193 insertions(+), 203 deletions(-) diff --git a/doomsday/client/include/map/linedef.h b/doomsday/client/include/map/linedef.h index baa82e5e16..f7382f0245 100644 --- a/doomsday/client/include/map/linedef.h +++ b/doomsday/client/include/map/linedef.h @@ -68,7 +68,7 @@ class HEdge; ///@} /** - * Map line. + * World map line. * * Despite sharing it's name with a map element present in the id Tech 1 map * format, this component has a notably different design and slightly different @@ -672,32 +672,6 @@ class LineDef : public de::MapElement return pointOnSide(point); } - /** - * Calculate a unit vector parallel to the line. - * - * @todo No longer needed (Surface has tangent space vectors). - * - * @param unitVector Unit vector is written here. - */ - void unitVector(pvec2f_t unitVec) const; - -#ifdef __CLIENT__ - - /** - * The DOOM lighting model applies a sector light level delta when drawing - * line segments based on their 2D world angle. - * - * @param side Side of the line we are interested in. - * @param deltaL Light delta for the left edge written here. Can be @c NULL. - * @param deltaR Light delta for the right edge written here. Can be @c NULL. - * - * @deprecated Now that we store surface tangent space normals use those - * rather than angles. @todo Remove me. - */ - void lightLevelDelta(int side, float *deltaL, float *deltaR) const; - -#endif // __CLIENT__ - /** * Get a property value, selected by DMU_* name. * diff --git a/doomsday/client/src/map/linedef.cpp b/doomsday/client/src/map/linedef.cpp index e72201e30a..e6cfe92b60 100644 --- a/doomsday/client/src/map/linedef.cpp +++ b/doomsday/client/src/map/linedef.cpp @@ -1,4 +1,4 @@ -/** @file linedef.h Map LineDef. +/** @file linedef.h World Map Line. * * @authors Copyright © 2003-2013 Jaakko Keränen * @authors Copyright © 2006-2013 Daniel Swanson @@ -24,7 +24,6 @@ #include #include "de_base.h" -//#include "de_render.h" #include "m_misc.h" #include "Materials" @@ -146,47 +145,6 @@ DENG2_PIMPL(LineDef) { std::memset(mapped, 0, sizeof(mapped)); } - -#ifdef __CLIENT__ - - /** - * @param line LineDef instance. - * @param ignoreOpacity @c true= do not consider Material opacity. - * @return @c true if this LineDef's side is considered "closed" (i.e., - * there is no opening through which the back Sector can be seen). - * Tests consider all Planes which interface with this and the "middle" - * Material used on the relative front side (if any). - */ - bool backClosedForBlendNeighbor(int side, bool ignoreOpacity) const - { - if(!front.hasSideDef()) return false; - if(!back.hasSideDef()) return true; - - Sector const *frontSec = self.sectorPtr(side); - Sector const *backSec = self.sectorPtr(side^1); - if(frontSec == backSec) return false; // Never. - - if(frontSec && backSec) - { - if(backSec->floor().visHeight() >= backSec->ceiling().visHeight()) return true; - if(backSec->ceiling().visHeight() <= frontSec->floor().visHeight()) return true; - if(backSec->floor().visHeight() >= frontSec->ceiling().visHeight()) return true; - } - - return R_MiddleMaterialCoversLineOpening(&self, side, ignoreOpacity); - } - - LineDef *findBlendNeighbor(byte side, byte right, binangle_t *diff) const - { - LineOwner const *farVertOwner = self.vertexOwner(right^side); - if(backClosedForBlendNeighbor(side, true/*ignore opacity*/)) - { - return R_FindSolidLineNeighbor(self.sectorPtr(side), &self, farVertOwner, right, diff); - } - return R_FindLineNeighbor(self.sectorPtr(side), &self, farVertOwner, right, diff); - } - -#endif // __CLIENT__ }; LineDef::LineDef() @@ -220,23 +178,6 @@ void LineDef::setOrigIndex(uint newIndex) d->origIndex = newIndex; } -int LineDef::validCount() const -{ - return _validCount; -} - -bool LineDef::isMappedByPlayer(int playerNum) const -{ - DENG2_ASSERT(playerNum >= 0 && playerNum < DDMAXPLAYERS); - return d->mapped[playerNum]; -} - -void LineDef::markMappedByPlayer(int playerNum, bool yes) -{ - DENG2_ASSERT(playerNum >= 0 && playerNum < DDMAXPLAYERS); - d->mapped[playerNum] = yes; -} - bool LineDef::isBspWindow() const { return (_inFlags & LF_BSPWINDOW) != 0; @@ -275,9 +216,20 @@ LineOwner *LineDef::vertexOwner(int to) const return to? _vo2 : _vo1; } -binangle_t LineDef::angle() const +AABoxd const &LineDef::aaBox() const { - return _angle; + return d->aaBox; +} + +void LineDef::updateAABox() +{ + V2d_InitBox(d->aaBox.arvec2, _v1->origin()); + V2d_AddToBox(d->aaBox.arvec2, _v2->origin()); +} + +coord_t LineDef::length() const +{ + return _length; } const_pvec2d_t &LineDef::direction() const @@ -290,14 +242,15 @@ slopetype_t LineDef::slopeType() const return d->slopeType; } -coord_t LineDef::length() const +void LineDef::updateSlopeType() { - return _length; + V2d_Subtract(_direction, _v2->origin(), _v1->origin()); + d->slopeType = M_SlopeType(_direction); } -AABoxd const &LineDef::aaBox() const +binangle_t LineDef::angle() const { - return d->aaBox; + return _angle; } int LineDef::boxOnSide(AABoxd const &box) const @@ -333,113 +286,22 @@ int LineDef::boxOnSide_FixedPrecision(AABoxd const &box) const return M_BoxOnLineSide_FixedPrecision(boxx, pos, delta); } -void LineDef::updateSlopeType() -{ - V2d_Subtract(_direction, _v2->origin(), _v1->origin()); - d->slopeType = M_SlopeType(_direction); -} - -void LineDef::unitVector(pvec2f_t unitvec) const -{ - coord_t len = M_ApproxDistance(_direction[VX], _direction[VY]); - if(len) - { - unitvec[VX] = _direction[VX] / len; - unitvec[VY] = _direction[VY] / len; - } - else - { - unitvec[VX] = unitvec[VY] = 0; - } -} - -void LineDef::updateAABox() -{ - V2d_InitBox(d->aaBox.arvec2, _v1->origin()); - V2d_AddToBox(d->aaBox.arvec2, _v2->origin()); -} - -#ifdef __CLIENT__ -static float calcLightLevelDelta(Vector2f const &normal) +bool LineDef::isMappedByPlayer(int playerNum) const { - return (1.0f / 255) * (normal.x * 18) * rendLightWallAngle; + DENG2_ASSERT(playerNum >= 0 && playerNum < DDMAXPLAYERS); + return d->mapped[playerNum]; } -static Vector2f calcNormal(LineDef const &line, byte side) +void LineDef::markMappedByPlayer(int playerNum, bool yes) { - return Vector2f((line.vertexOrigin(side^1)[VY] - line.vertexOrigin(side) [VY]) / line.length(), - (line.vertexOrigin(side) [VX] - line.vertexOrigin(side^1)[VX]) / line.length()); + DENG2_ASSERT(playerNum >= 0 && playerNum < DDMAXPLAYERS); + d->mapped[playerNum] = yes; } -void LineDef::lightLevelDelta(int side, float *deltaL, float *deltaR) const +int LineDef::validCount() const { - // Disabled? - if(!(rendLightWallAngle > 0)) - { - if(deltaL) *deltaL = 0; - if(deltaR) *deltaR = 0; - return; - } - - Vector2f normal = calcNormal(*this, side); - float delta = calcLightLevelDelta(normal); - - // If smoothing is disabled use this delta for left and right edges. - // Must forcibly disable smoothing for polyobj linedefs as they have - // no owner rings. - if(!rendLightWallAngleSmooth || (_inFlags & LF_POLYOBJ)) - { - if(deltaL) *deltaL = delta; - if(deltaR) *deltaR = delta; - return; - } - - // Find the left neighbour linedef 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 linedefs is less - // than 45 degrees. - if(deltaL) - { - binangle_t diff = 0; - LineDef *other = d->findBlendNeighbor(side, 0, &diff); - if(other && INRANGE_OF(diff, BANG_180, BANG_45)) - { - Vector2f otherNormal = calcNormal(*other, &other->v2() != &vertex(side)); - - // Average normals. - otherNormal += normal; - otherNormal.x /= 2; otherNormal.y /= 2; - - *deltaL = calcLightLevelDelta(otherNormal); - } - else - { - *deltaL = delta; - } - } - - // Do the same for the right edge but with the right neighbor linedef. - if(deltaR) - { - binangle_t diff = 0; - LineDef *other = d->findBlendNeighbor(side, 1, &diff); - if(other && INRANGE_OF(diff, BANG_180, BANG_45)) - { - Vector2f otherNormal = calcNormal(*other, &other->v1() != &vertex(side^1)); - - // Average normals. - otherNormal += normal; - otherNormal.x /= 2; otherNormal.y /= 2; - - *deltaR = calcLightLevelDelta(otherNormal); - } - else - { - *deltaR = delta; - } - } + return _validCount; } -#endif int LineDef::property(setargs_t &args) const { @@ -554,6 +416,7 @@ int LineDef::setProperty(setargs_t const &args) DMU_SetValue(DMT_LINEDEF_FLAGS, &_flags, &args, 0); #ifdef __CLIENT__ + /// @todo Surface should observe. if(hasFrontSideDef()) { SideDef &frontDef = frontSideDef(); diff --git a/doomsday/client/src/render/rend_main.cpp b/doomsday/client/src/render/rend_main.cpp index cfebcf10e4..d5c51f402c 100644 --- a/doomsday/client/src/render/rend_main.cpp +++ b/doomsday/client/src/render/rend_main.cpp @@ -1522,6 +1522,137 @@ static void Rend_RenderPlane(Plane::Type type, coord_t height, } } +static float calcLightLevelDelta(Vector2f const &normal) +{ + return (1.0f / 255) * (normal.x * 18) * rendLightWallAngle; +} + +static Vector2f calcLineNormal(LineDef const &line, byte side) +{ + return Vector2f((line.vertexOrigin(side^1)[VY] - line.vertexOrigin(side) [VY]) / line.length(), + (line.vertexOrigin(side) [VX] - line.vertexOrigin(side^1)[VX]) / line.length()); +} + +/** + * @param line LineDef instance. + * @param ignoreOpacity @c true= do not consider Material opacity. + * @return @c true if this LineDef's side is considered "closed" (i.e., + * there is no opening through which the back Sector can be seen). + * Tests consider all Planes which interface with this and the "middle" + * Material used on the relative front side (if any). + */ +static bool lineBackClosedForBlend(LineDef const &line, int side, bool ignoreOpacity) +{ + if(!line.front().hasSideDef()) return false; + if(!line.back().hasSideDef()) return true; + + Sector const *frontSec = line.sectorPtr(side); + Sector const *backSec = line.sectorPtr(side^1); + if(frontSec == backSec) return false; // Never. + + if(frontSec && backSec) + { + if(backSec->floor().visHeight() >= backSec->ceiling().visHeight()) return true; + if(backSec->ceiling().visHeight() <= frontSec->floor().visHeight()) return true; + if(backSec->floor().visHeight() >= frontSec->ceiling().visHeight()) return true; + } + + return R_MiddleMaterialCoversLineOpening(&line, side, ignoreOpacity); +} + +static LineDef *findLineBlendNeighbor(LineDef const &line, byte side, byte right, + binangle_t *diff) +{ + LineOwner const *farVertOwner = line.vertexOwner(right^side); + if(lineBackClosedForBlend(line, side, true/*ignore opacity*/)) + { + return R_FindSolidLineNeighbor(line.sectorPtr(side), &line, farVertOwner, right, diff); + } + return R_FindLineNeighbor(line.sectorPtr(side), &line, farVertOwner, right, diff); +} + +/** + * The DOOM lighting model applies a sector light level delta when drawing + * line segments based on their 2D world angle. + * + * @param line Line to calculate light level deltas for. + * @param side Side of the line we are interested in. + * @param deltaL Light delta for the left edge written here. Can be @c NULL. + * @param deltaR Light delta for the right edge written here. Can be @c NULL. + * + * @deprecated Now that we store surface tangent space normals use those + * rather than angles. @todo Remove me. + */ +static void lineLightLevelDeltas(LineDef const &line, int side, + float *deltaL, float *deltaR) +{ + // Disabled? + if(!(rendLightWallAngle > 0)) + { + if(deltaL) *deltaL = 0; + if(deltaR) *deltaR = 0; + return; + } + + Vector2f normal = calcLineNormal(line, side); + float delta = calcLightLevelDelta(normal); + + // If smoothing is disabled use this delta for left and right edges. + // Must forcibly disable smoothing for polyobj linedefs as they have + // no owner rings. + if(!rendLightWallAngleSmooth || line.isFromPolyobj()) + { + if(deltaL) *deltaL = delta; + if(deltaR) *deltaR = delta; + return; + } + + // Find the left neighbour linedef 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 linedefs is less + // than 45 degrees. + if(deltaL) + { + binangle_t diff = 0; + LineDef *other = findLineBlendNeighbor(line, side, 0, &diff); + if(other && INRANGE_OF(diff, BANG_180, BANG_45)) + { + Vector2f otherNormal = calcLineNormal(*other, &other->v2() != &line.vertex(side)); + + // Average normals. + otherNormal += normal; + otherNormal.x /= 2; otherNormal.y /= 2; + + *deltaL = calcLightLevelDelta(otherNormal); + } + else + { + *deltaL = delta; + } + } + + // Do the same for the right edge but with the right neighbor linedef. + if(deltaR) + { + binangle_t diff = 0; + LineDef *other = findLineBlendNeighbor(line, side, 1, &diff); + if(other && INRANGE_OF(diff, BANG_180, BANG_45)) + { + Vector2f otherNormal = calcLineNormal(*other, &other->v1() != &line.vertex(side^1)); + + // Average normals. + otherNormal += normal; + otherNormal.x /= 2; otherNormal.y /= 2; + + *deltaR = calcLightLevelDelta(otherNormal); + } + else + { + *deltaR = delta; + } + } +} + /** * @defgroup rendHEdgeFlags Rend Half-edge Flags * Flags for rendHEdgeSection() @@ -1731,7 +1862,7 @@ static boolean rendHEdgeSection(HEdge *hedge, SideDefSection section, else { LineDef const &line = hedge->line(); - line.lightLevelDelta(hedge->lineSideId(), &deltaL, &deltaR); + lineLightLevelDeltas(line, hedge->lineSideId(), &deltaL, &deltaR); // Linear interpolation of the linedef light deltas to the edges of the hedge. float diff = deltaR - deltaL; diff --git a/doomsday/client/src/render/rend_particle.cpp b/doomsday/client/src/render/rend_particle.cpp index 2d19ccf909..f3375c2c35 100644 --- a/doomsday/client/src/render/rend_particle.cpp +++ b/doomsday/client/src/render/rend_particle.cpp @@ -496,6 +496,27 @@ static void setupModelParamsForParticle(rendmodelparams_t* params, } } +/** + * Calculate a unit vector parallel to @a line. + * + * @todo No longer needed (Surface has tangent space vectors). + * + * @param unitVect Unit vector is written here. + */ +static void lineUnitVector(LineDef const &line, pvec2f_t unitVec) +{ + coord_t len = M_ApproxDistance(line.direction()[VX], line.direction()[VY]); + if(len) + { + unitVec[VX] = line.direction()[VX] / len; + unitVec[VY] = line.direction()[VY] / len; + } + else + { + unitVec[VX] = unitVec[VY] = 0; + } +} + static void renderParticles(int rtype, boolean withBlend) { float leftoff[3], rightoff[3]; @@ -723,7 +744,6 @@ static void renderParticles(int rtype, boolean withBlend) else if(flatOnWall) { vec2d_t origin, projected; - float line[2]; // There will be a slight approximation on the XY plane since // the particles aren't that accurate when it comes to wall @@ -744,23 +764,25 @@ static void renderParticles(int rtype, boolean withBlend) projected[VY] += diff[VY] / dist * gap; } - pt->contact->unitVector(line); + DENG_ASSERT(pt->contact != 0); + float unitvec[2]; + lineUnitVector(*pt->contact, unitvec); glTexCoord2f(0, 0); - glVertex3d(projected[VX] - size * line[VX], center[VY] - size, - projected[VY] - size * line[VY]); + glVertex3d(projected[VX] - size * unitvec[VX], center[VY] - size, + projected[VY] - size * unitvec[VY]); glTexCoord2f(1, 0); - glVertex3d(projected[VX] - size * line[VX], center[VY] + size, - projected[VY] - size * line[VY]); + glVertex3d(projected[VX] - size * unitvec[VX], center[VY] + size, + projected[VY] - size * unitvec[VY]); glTexCoord2f(1, 1); - glVertex3d(projected[VX] + size * line[VX], center[VY] + size, - projected[VY] + size * line[VY]); + glVertex3d(projected[VX] + size * unitvec[VX], center[VY] + size, + projected[VY] + size * unitvec[VY]); glTexCoord2f(0, 1); - glVertex3d(projected[VX] + size * line[VX], center[VY] - size, - projected[VY] + size * line[VY]); + glVertex3d(projected[VX] + size * unitvec[VX], center[VY] - size, + projected[VY] + size * unitvec[VY]); } else {