diff --git a/doomsday/client/include/render/rend_dynlight.h b/doomsday/client/include/render/rend_dynlight.h index 51af73e9f2..723b494835 100644 --- a/doomsday/client/include/render/rend_dynlight.h +++ b/doomsday/client/include/render/rend_dynlight.h @@ -35,11 +35,11 @@ typedef struct { bool isWall; struct { struct { - walldivnode_t *firstDiv; + de::WallDivs::Intercept *firstDiv; uint divCount; } left; struct { - walldivnode_t *firstDiv; + de::WallDivs::Intercept *firstDiv; uint divCount; } right; } wall; diff --git a/doomsday/client/include/render/rend_fakeradio.h b/doomsday/client/include/render/rend_fakeradio.h index db6545a89e..e64cde2aa1 100644 --- a/doomsday/client/include/render/rend_fakeradio.h +++ b/doomsday/client/include/render/rend_fakeradio.h @@ -161,11 +161,11 @@ struct RendRadioWallSectionParms Sector const *frontSec, *backSec; struct { struct { - walldivnode_t *firstDiv; + de::WallDivs::Intercept *firstDiv; uint divCount; } left; struct { - walldivnode_t *firstDiv; + de::WallDivs::Intercept *firstDiv; uint divCount; } right; } wall; diff --git a/doomsday/client/include/render/rend_shadow.h b/doomsday/client/include/render/rend_shadow.h index 25d99abdf9..852c7df93f 100644 --- a/doomsday/client/include/render/rend_shadow.h +++ b/doomsday/client/include/render/rend_shadow.h @@ -52,11 +52,11 @@ typedef struct { bool isWall; struct { struct { - walldivnode_t *firstDiv; + de::WallDivs::Intercept *firstDiv; uint divCount; } left; struct { - walldivnode_t *firstDiv; + de::WallDivs::Intercept *firstDiv; uint divCount; } right; } wall; diff --git a/doomsday/client/include/render/rendpoly.h b/doomsday/client/include/render/rendpoly.h index 1fcf56b996..c3a327a0ea 100644 --- a/doomsday/client/include/render/rendpoly.h +++ b/doomsday/client/include/render/rendpoly.h @@ -29,7 +29,7 @@ #include -struct walldivnode_s; +#include "render/walldiv.h" typedef struct rvertex_s { float pos[3]; @@ -110,8 +110,6 @@ typedef struct rtexmapuint_s { #endif } rtexmapunit_t; -#ifdef __CLIENT__ - extern byte rendInfoRPolys; void R_PrintRendPoolInfo(void); @@ -213,19 +211,17 @@ inline void Rtu_TranslateOffset(rtexmapunit_t *rtu, float s, float t) } void R_DivVerts(rvertex_t *dst, rvertex_t const *src, - struct walldivnode_s *leftDivFirst, uint leftDivCount, - struct walldivnode_s *rightDivFirst, uint rightDivCount); + de::WallDivs::Intercept *leftDivFirst, uint leftDivCount, + de::WallDivs::Intercept *rightDivFirst, uint rightDivCount); void R_DivTexCoords(rtexcoord_t *dst, rtexcoord_t const *src, - struct walldivnode_s *leftDivFirst, uint leftDivCount, - struct walldivnode_s *rightDivFirst, uint rightDivCount, + de::WallDivs::Intercept *leftDivFirst, uint leftDivCount, + de::WallDivs::Intercept *rightDivFirst, uint rightDivCount, float bL, float tL, float bR, float tR); void R_DivVertColors(ColorRawf *dst, ColorRawf const *src, - struct walldivnode_s *leftDivFirst, uint leftDivCount, - struct walldivnode_s *rightDivFirst, uint rightDivCount, + de::WallDivs::Intercept *leftDivFirst, uint leftDivCount, + de::WallDivs::Intercept *rightDivFirst, uint rightDivCount, float bL, float tL, float bR, float tR); -#endif // __CLIENT__ - #endif // DENG_RENDER_RENDPOLY_H diff --git a/doomsday/client/include/render/walldiv.h b/doomsday/client/include/render/walldiv.h index 27e3b5f27e..06b282fdaf 100644 --- a/doomsday/client/include/render/walldiv.h +++ b/doomsday/client/include/render/walldiv.h @@ -21,50 +21,185 @@ #ifndef DENG_RENDER_WALLDIV_H #define DENG_RENDER_WALLDIV_H -#include "dd_types.h" +#include -struct walldivs_s; +/// Maximum number of walldivnode_ts in a walldivs_t dataset. +#define WALLDIVS_MAX_INTERCEPTS 64 -typedef struct walldivnode_s { - struct walldivs_s *divs; - coord_t height; -} walldivnode_t; +namespace de { -coord_t WallDivNode_Height(walldivnode_t *node); -walldivnode_t *WallDivNode_Next(walldivnode_t *node); -walldivnode_t *WallDivNode_Prev(walldivnode_t *node); +class WallDivs +{ +public: + /// Required intercept is missing. @ingroup errors + DENG2_ERROR(MissingInterceptError); -/// Maximum number of walldivnode_ts in a walldivs_t dataset. -#define WALLDIVS_MAX_NODES 64 + class Intercept + { + protected: + Intercept() : _wallDivs(0), _distance(0) {} + + public: + ddouble operator - (Intercept const &other) const + { + return distance() - other.distance(); + } + + bool operator < (Intercept const &other) const + { + return distance() < other.distance(); + } + + ddouble distance() const { return _distance; } + + bool hasNext() const + { + int idx = this - _wallDivs->_intercepts; + return (idx + 1 < _wallDivs->_interceptCount); + } + + bool hasPrev() const + { + int idx = this - _wallDivs->_intercepts; + return (idx > 0); + } + + Intercept &next() const + { + int idx = this - _wallDivs->_intercepts; + if(idx + 1 < _wallDivs->_interceptCount) + { + return _wallDivs->_intercepts[idx+1]; + } + throw WallDivs::MissingInterceptError("WallDivs::Intercept", "No next neighbor"); + } + + Intercept &prev() const + { + int idx = this - _wallDivs->_intercepts; + if(idx > 0) + { + return _wallDivs->_intercepts[idx-1]; + } + throw WallDivs::MissingInterceptError("WallDivs::Intercept", "No previous neighbor"); + } + + friend class WallDivs; + + private: + WallDivs *_wallDivs; + ddouble _distance; + }; -typedef struct walldivs_s { - uint num; - struct walldivnode_s nodes[WALLDIVS_MAX_NODES]; + typedef Intercept Intercepts[WALLDIVS_MAX_INTERCEPTS]; - walldivs_s() : num(0) +public: + WallDivs() : _interceptCount(0) { - std::memset(nodes, 0, sizeof(nodes)); + std::memset(_intercepts, 0, sizeof(_intercepts)); } -} walldivs_t; + int count() const { return _interceptCount; } -uint WallDivs_Size(walldivs_t const *wallDivs); -walldivnode_t *WallDivs_First(walldivs_t *wallDivs); -walldivnode_t *WallDivs_Last(walldivs_t *wallDivs); -walldivs_t *WallDivs_Append(walldivs_t *wallDivs, coord_t height); + inline bool isEmpty() const { return count() == 0; } -/** - * Ensure the divisions are sorted (in ascending Z order). - */ -void WallDivs_AssertSorted(walldivs_t *wallDivs); + Intercept &first() const + { + if(_interceptCount > 0) + { + return const_cast(_intercepts[0]); + } + throw MissingInterceptError("WallDivs::first", "Intercepts list is empty"); + } -/** - * Ensure the divisions do not exceed the specified range. - */ -void WallDivs_AssertInRange(walldivs_t *wallDivs, coord_t low, coord_t hi); + Intercept &last() const + { + if(_interceptCount > 0) + { + return const_cast(_intercepts[_interceptCount-1]); + } + throw MissingInterceptError("WallDivs::last", "Intercepts list is empty"); + } + void append(ddouble distance) + { + Intercept *node = &_intercepts[_interceptCount++]; + node->_wallDivs = this; + node->_distance = distance; + } + + Intercept *find(ddouble distance) const + { + for(int i = 0; i < _interceptCount; ++i) + { + Intercept *icpt = const_cast(&_intercepts[i]); + if(icpt->distance() == distance) + return icpt; + } + return 0; + } + + static int compareIntercepts(void const *e1, void const *e2) + { + ddouble const delta = (*reinterpret_cast(e1)) - (*reinterpret_cast(e2)); + if(delta > 0) return 1; + if(delta < 0) return -1; + return 0; + } + + void sort() + { + if(count() < 2) return; + + // Sorting is required. This shouldn't take too long... + // There seldom are more than two or three intercepts. + qsort(_intercepts, _interceptCount, sizeof(*_intercepts), compareIntercepts); + assertSorted(); + } + +#ifdef DENG_DEBUG + void debugPrint() const + { + LOG_DEBUG("WallDivs [%p]:") << de::dintptr(this); + for(int i = 0; i < _interceptCount; ++i) + { + Intercept const *node = &_intercepts[i]; + LOG_DEBUG(" %i: %f") << i << node->distance(); + } + } +#endif + + Intercepts const &intercepts() const + { + return _intercepts; + } + +private: + /** + * Ensure the intercepts are sorted (in ascending distance order). + */ + void assertSorted() const + { #ifdef DENG_DEBUG -void WallDivs_DebugPrint(walldivs_t *wallDivs); + if(isEmpty()) return; + + WallDivs::Intercept *node = &first(); + ddouble farthest = node->distance(); + forever + { + DENG2_ASSERT(node->distance() >= farthest); + farthest = node->distance(); + + if(!node->hasNext()) break; + node = &node->next(); + } #endif + } + + int _interceptCount; + Intercepts _intercepts; +}; + +} // namespace de #endif // DENG_RENDER_WALLDIV_H diff --git a/doomsday/client/src/map/hedge.cpp b/doomsday/client/src/map/hedge.cpp index 824dd8443c..12fa37cb96 100644 --- a/doomsday/client/src/map/hedge.cpp +++ b/doomsday/client/src/map/hedge.cpp @@ -243,99 +243,3 @@ int HEdge::property(setargs_t &args) const return false; // Continue iteration. } - -// WallDivs ---------------------------------------------------------------- -/// @todo Move the following to another file - -#include "render/walldiv.h" - -coord_t WallDivNode_Height(walldivnode_t *node) -{ - DENG2_ASSERT(node); - return node->height; -} - -walldivnode_t *WallDivNode_Next(walldivnode_t *node) -{ - DENG2_ASSERT(node); - uint idx = node - node->divs->nodes; - if(idx + 1 >= node->divs->num) return 0; - return &node->divs->nodes[idx+1]; -} - -walldivnode_t *WallDivNode_Prev(walldivnode_t *node) -{ - DENG2_ASSERT(node); - uint idx = node - node->divs->nodes; - if(idx == 0) return 0; - return &node->divs->nodes[idx-1]; -} - -uint WallDivs_Size(walldivs_t const *wd) -{ - DENG2_ASSERT(wd); - return wd->num; -} - -walldivnode_t *WallDivs_First(walldivs_t *wd) -{ - DENG2_ASSERT(wd); - return &wd->nodes[0]; -} - -walldivnode_t *WallDivs_Last(walldivs_t *wd) -{ - DENG2_ASSERT(wd); - return &wd->nodes[wd->num-1]; -} - -walldivs_t *WallDivs_Append(walldivs_t *wd, coord_t height) -{ - DENG2_ASSERT(wd); - struct walldivnode_s *node = &wd->nodes[wd->num++]; - node->divs = wd; - node->height = height; - return wd; -} - -void WallDivs_AssertSorted(walldivs_t *wd) -{ -#ifdef DENG_DEBUG - walldivnode_t *node = WallDivs_First(wd); - coord_t highest = WallDivNode_Height(node); - for(uint i = 0; i < wd->num; ++i, node = WallDivNode_Next(node)) - { - DENG2_ASSERT(node->height >= highest); - highest = node->height; - } -#else - DENG_UNUSED(wd); -#endif -} - -void WallDivs_AssertInRange(walldivs_t *wd, coord_t low, coord_t hi) -{ -#ifdef DENG_DEBUG - DENG2_ASSERT(wd); - walldivnode_t *node = WallDivs_First(wd); - for(uint i = 0; i < wd->num; ++i, node = WallDivNode_Next(node)) - { - DENG2_ASSERT(node->height >= low && node->height <= hi); - } -#else - DENG2_UNUSED3(wd, low, hi); -#endif -} - -#ifdef DENG_DEBUG -void WallDivs_DebugPrint(walldivs_t *wd) -{ - DENG2_ASSERT(wd); - LOG_DEBUG("WallDivs [%p]:") << wd; - for(uint i = 0; i < wd->num; ++i) - { - walldivnode_t *node = &wd->nodes[i]; - LOG_DEBUG(" %i: %f") << i << node->height; - } -} -#endif diff --git a/doomsday/client/src/render/rend_main.cpp b/doomsday/client/src/render/rend_main.cpp index ea7d0b034f..0cb7dd59ea 100644 --- a/doomsday/client/src/render/rend_main.cpp +++ b/doomsday/client/src/render/rend_main.cpp @@ -704,11 +704,11 @@ struct rendworldpoly_params_t coord_t segLength; Vector3f const *surfaceColor2; // Secondary color. struct { - walldivnode_t *firstDiv; + WallDivs::Intercept *firstDiv; uint divCount; } left; struct { - walldivnode_t *firstDiv; + WallDivs::Intercept *firstDiv; uint divCount; } right; } wall; @@ -1558,7 +1558,7 @@ static inline float wallSectionOpacity(Line::Side &side, int section) * @param flags @ref writeWallSectionFlags */ static bool writeWallSection(HEdge &hedge, int section, - int flags, walldivs_t *leftWallDivs, walldivs_t *rightWallDivs, + int flags, WallDivs *leftWallDivs, WallDivs *rightWallDivs, Vector2f const &materialOrigin) { BspLeaf *leaf = currentBspLeaf; @@ -1570,8 +1570,8 @@ static bool writeWallSection(HEdge &hedge, int section, if(!(surface.hasMaterial() && surface.material().isDrawable())) return false; - if(WallDivNode_Height(WallDivs_First(leftWallDivs)) >= - WallDivNode_Height(WallDivs_Last(rightWallDivs))) return true; + if(leftWallDivs->first().distance() >= + rightWallDivs->last().distance()) return true; float opacity = wallSectionOpacity(hedge.lineSide(), section); @@ -1590,8 +1590,8 @@ static bool writeWallSection(HEdge &hedge, int section, * (e.g., passing through an opaque waterfall). */ - if(viewData->current.origin[VZ] > WallDivNode_Height(WallDivs_First(leftWallDivs)) && - viewData->current.origin[VZ] < WallDivNode_Height(WallDivs_Last(rightWallDivs))) + if(viewData->current.origin[VZ] > leftWallDivs->first().distance() && + viewData->current.origin[VZ] < rightWallDivs->last().distance()) { Line const &line = hedge.line(); @@ -1627,11 +1627,9 @@ static bool writeWallSection(HEdge &hedge, int section, Vector2f materialScale((surface.flags() & DDSUF_MATERIAL_FLIPH)? -1 : 1, (surface.flags() & DDSUF_MATERIAL_FLIPV)? -1 : 1); - Vector3d texTL(hedge.fromOrigin(), - WallDivNode_Height(WallDivs_Last(leftWallDivs))); + Vector3d texTL(hedge.fromOrigin(), leftWallDivs->last().distance()); - Vector3d texBR(hedge.toOrigin(), - WallDivNode_Height(WallDivs_First(rightWallDivs))); + Vector3d texBR(hedge.toOrigin(), rightWallDivs->first().distance()); // Determine which Material to use. Material *material = 0; @@ -1771,17 +1769,17 @@ static bool writeWallSection(HEdge &hedge, int section, parm.isWall = true; parm.wall.surfaceColor2 = bottomColor; parm.wall.segLength = hedge.length(); - parm.wall.left.firstDiv = WallDivNode_Next(WallDivs_First(leftWallDivs)); // Step over first node. - parm.wall.left.divCount = WallDivs_Size(leftWallDivs)-2; - parm.wall.right.firstDiv = WallDivNode_Prev(WallDivs_Last(rightWallDivs)); // Step over last node. - parm.wall.right.divCount = WallDivs_Size(rightWallDivs)-2; + parm.wall.left.firstDiv = &leftWallDivs->first().next(); // Step over first node. + parm.wall.left.divCount = leftWallDivs->count()-2; + parm.wall.right.firstDiv = &rightWallDivs->last().prev(); // Step over last node. + parm.wall.right.divCount = rightWallDivs->count()-2; rvertex_t *rvertices; // Allocate enough vertices for the divisions too. - if(WallDivs_Size(leftWallDivs) > 2 || WallDivs_Size(rightWallDivs) > 2) + if(leftWallDivs->count() > 2 || rightWallDivs->count() > 2) { // Use two fans. - rvertices = R_AllocRendVertices(1 + WallDivs_Size(leftWallDivs) + 1 + WallDivs_Size(rightWallDivs)); + rvertices = R_AllocRendVertices(1 + leftWallDivs->count() + 1 + rightWallDivs->count()); } else { @@ -1793,19 +1791,19 @@ static bool writeWallSection(HEdge &hedge, int section, // Bottom Left. V3f_Set(rvertices[0].pos, hedge.fromOrigin().x, hedge.fromOrigin().y, - WallDivNode_Height(WallDivs_First(leftWallDivs))); + leftWallDivs->first().distance()); // Top Left. V3f_Set(rvertices[1].pos, hedge.fromOrigin().x, hedge.fromOrigin().y, - WallDivNode_Height(WallDivs_Last(leftWallDivs))); + leftWallDivs->last().distance()); // Bottom Right. V3f_Set(rvertices[2].pos, hedge.toOrigin().x, hedge.toOrigin().y, - WallDivNode_Height(WallDivs_First(rightWallDivs))); + rightWallDivs->first().distance()); // Top Right. V3f_Set(rvertices[3].pos, hedge.toOrigin().x, hedge.toOrigin().y, - WallDivNode_Height(WallDivs_Last(rightWallDivs))); + rightWallDivs->last().distance()); // Draw this section. bool opaque = renderWorldPoly(rvertices, 4, parm, ms); @@ -1847,19 +1845,19 @@ static bool writeWallSection(HEdge &hedge, int section, // Bottom Left. V3f_Set(rvertices[0].pos, hedge.fromOrigin().x, hedge.fromOrigin().y, - WallDivNode_Height(WallDivs_First(leftWallDivs))); + leftWallDivs->first().distance()); // Top Left. V3f_Set(rvertices[1].pos, hedge.fromOrigin().x, hedge.fromOrigin().y, - WallDivNode_Height(WallDivs_Last(leftWallDivs))); + leftWallDivs->last().distance()); // Bottom Right. V3f_Set(rvertices[2].pos, hedge.toOrigin().x, hedge.toOrigin().y, - WallDivNode_Height(WallDivs_First(rightWallDivs))); + rightWallDivs->first().distance()); // Top Right. V3f_Set(rvertices[3].pos, hedge.toOrigin().x, hedge.toOrigin().y, - WallDivNode_Height(WallDivs_Last(rightWallDivs))); + rightWallDivs->last().distance()); // kludge end. @@ -1897,42 +1895,31 @@ static bool writeWallSection(HEdge &hedge, int section, return opaque && !didNearBlend; } -static walldivnode_t *findWallDivNodeByZOrigin(walldivs_t *wallDivs, coord_t height) -{ - DENG2_ASSERT(wallDivs != 0); - for(uint i = 0; i < wallDivs->num; ++i) - { - walldivnode_t *node = &wallDivs->nodes[i]; - if(node->height == height) - return node; - } - return 0; -} - -static void addWallDivNodesForPlaneIntercepts(HEdge const &hedge, walldivs_t *wallDivs, - int section, coord_t bottomZ, coord_t topZ, boolean doRight) +static void addWallDivNodesForPlaneIntercepts(HEdge const &hedge, WallDivs *wallDivs, + int section, coord_t bottomZ, coord_t topZ, bool doRight) { bool const clockwise = !doRight; - // Polyobj edges are never split. - if(!hedge.hasLineSide() || hedge.line().isFromPolyobj()) return; + if(!hedge.hasLineSide()) return; - bool const isTwoSided = (hedge.line().hasFrontSections() && hedge.line().hasBackSections())? true:false; + Line::Side const &side = hedge.lineSide(); + if(side.line().isFromPolyobj()) return; // Check for neighborhood division? - if(section == Line::Side::Middle && isTwoSided) return; + if(section == Line::Side::Middle && side.hasSections() && side.back().hasSections()) + return; - // Only edges at line ends can/should be split. - if(!((&hedge == hedge.lineSide().leftHEdge() && !doRight) || - (&hedge == hedge.lineSide().rightHEdge() && doRight))) + // Only sections at line side edges can/should be split. + if(!((&hedge == side.leftHEdge() && !doRight) || + (&hedge == side.rightHEdge() && doRight))) return; if(bottomZ >= topZ) return; // Obviously no division. - Sector const *frontSec = hedge.lineSide().sectorPtr(); + Sector const *frontSec = side.sectorPtr(); // Retrieve the start owner node. - LineOwner *base = R_GetVtxLineOwner(&hedge.lineSide().vertex(doRight), &hedge.line()); + LineOwner *base = R_GetVtxLineOwner(&side.line().vertex(doRight), &side.line()); LineOwner *own = base; bool stopScan = false; do @@ -1952,7 +1939,8 @@ static void addWallDivNodesForPlaneIntercepts(HEdge const &hedge, walldivs_t *wa uint i = 0; do - { // First front, then back. + { + // First front, then back. Sector *scanSec = NULL; if(!i && iter->hasFrontSections() && iter->frontSectorPtr() != frontSec) scanSec = iter->frontSectorPtr(); @@ -1969,12 +1957,12 @@ static void addWallDivNodesForPlaneIntercepts(HEdge const &hedge, walldivs_t *wa if(plane.visHeight() > bottomZ && plane.visHeight() < topZ) { - if(!findWallDivNodeByZOrigin(wallDivs, plane.visHeight())) + if(!wallDivs->find(plane.visHeight())) { - WallDivs_Append(wallDivs, plane.visHeight()); + wallDivs->append(plane.visHeight()); // Have we reached the div limit? - if(wallDivs->num == WALLDIVS_MAX_NODES) + if(wallDivs->count() == WALLDIVS_MAX_INTERCEPTS) stopScan = true; } } @@ -2006,9 +1994,9 @@ static void addWallDivNodesForPlaneIntercepts(HEdge const &hedge, walldivs_t *wa if(z > bottomZ && z < topZ) { - if(!findWallDivNodeByZOrigin(wallDivs, z)) + if(!wallDivs->find(z)) { - WallDivs_Append(wallDivs, z); + wallDivs->append(z); // All clipped away. stopScan = true; @@ -2025,38 +2013,46 @@ static void addWallDivNodesForPlaneIntercepts(HEdge const &hedge, walldivs_t *wa } while(!stopScan); } -static int sortWallDivNode(void const *e1, void const *e2) +/** + * Ensure the divisions do not exceed the specified range. + */ +static void assertWallDivsInRange(WallDivs *wd, coord_t low, coord_t hi) { - coord_t const h1 = ((walldivnode_t *)e1)->height; - coord_t const h2 = ((walldivnode_t *)e2)->height; - if(h1 > h2) return 1; - if(h2 > h1) return -1; - return 0; +#ifdef DENG_DEBUG + if(wd->isEmpty()) return; + + WallDivs::Intercept *node = &wd->first(); + forever + { + DENG2_ASSERT(node->distance() >= low && node->distance() <= hi); + + if(!node->hasNext()) break; + node = &node->next(); + } +#else + DENG2_UNUSED3(wd, low, hi); +#endif } -static void buildWallDiv(walldivs_t *wallDivs, HEdge const &hedge, +static void buildWallDiv(WallDivs *wallDivs, HEdge const &hedge, int section, coord_t bottomZ, coord_t topZ, boolean doRight) { - DENG_ASSERT(wallDivs->num == 0); + DENG_ASSERT(wallDivs->isEmpty()); // Nodes are arranged according to their Z axis height in ascending order. // The first node is the bottom. - WallDivs_Append(wallDivs, bottomZ); + wallDivs->append(bottomZ); // Add nodes for intercepts. addWallDivNodesForPlaneIntercepts(hedge, wallDivs, section, bottomZ, topZ, doRight); // The last node is the top. - WallDivs_Append(wallDivs, topZ); - - if(!(wallDivs->num > 2)) return; + wallDivs->append(topZ); - // Sorting is required. This shouldn't take too long... - // There seldom are more than two or three nodes. - qsort(wallDivs->nodes, wallDivs->num, sizeof(*wallDivs->nodes), sortWallDivNode); + if(!(wallDivs->count() > 2)) return; - WallDivs_AssertSorted(wallDivs); - WallDivs_AssertInRange(wallDivs, bottomZ, topZ); + wallDivs->sort(); + assertWallDivsInRange(wallDivs, bottomZ, topZ); } /** @@ -2070,8 +2066,8 @@ static void buildWallDiv(walldivs_t *wallDivs, HEdge const &hedge, * @return @c true if divisions were prepared (the specified @a section has a * non-zero Z axis height). */ -static bool prepareWallDivs(HEdge &hedge, int section, walldivs_t *leftWallDivs, - walldivs_t *rightWallDivs, Vector2f *materialOrigin) +static bool prepareWallDivs(HEdge &hedge, int section, WallDivs *leftWallDivs, + WallDivs *rightWallDivs, Vector2f *materialOrigin) { DENG_ASSERT(hedge.hasLineSide()); @@ -2122,7 +2118,7 @@ static bool writeWallSections2(HEdge &hedge, int sections) // Only a "middle" section. if(!(sections & Line::Side::MiddleFlag)) return false; - walldivs_t leftWallDivs, rightWallDivs; + WallDivs leftWallDivs, rightWallDivs; Vector2f materialOrigin; bool opaque = false; @@ -2142,7 +2138,7 @@ static bool writeWallSections2(HEdge &hedge, int sections) } static bool prepareWallDivsPolyobj(Line::Side const &side, int section, - walldivs_t *leftWallDivs, walldivs_t *rightWallDivs, Vector2f *materialOrigin = 0) + WallDivs *leftWallDivs, WallDivs *rightWallDivs, Vector2f *materialOrigin = 0) { BspLeaf *leaf = currentBspLeaf; DENG_ASSERT(!isNullLeaf(leaf)); @@ -2153,11 +2149,11 @@ static bool prepareWallDivsPolyobj(Line::Side const &side, int section, if(!visible) return false; - WallDivs_Append(leftWallDivs, bottom); // First node. - WallDivs_Append(leftWallDivs, top); // Last node. + leftWallDivs->append(bottom); // First node. + leftWallDivs->append(top); // Last node. - WallDivs_Append(rightWallDivs, bottom); // First node. - WallDivs_Append(rightWallDivs, top); // Last node. + rightWallDivs->append(bottom); // First node. + rightWallDivs->append(top); // Last node. return true; } @@ -2174,7 +2170,7 @@ static bool writeWallSections2Polyobj(HEdge &hedge, int sections) // Only a "middle" section. if(!(sections & Line::Side::MiddleFlag)) return false; - walldivs_t leftWallDivs, rightWallDivs; + WallDivs leftWallDivs, rightWallDivs; Vector2f materialOrigin; bool opaque = false; @@ -2231,7 +2227,7 @@ static bool writeWallSections2Twosided(HEdge &hedge, int sections) // Middle section? if(sections & Line::Side::MiddleFlag) { - walldivs_t leftWallDivs, rightWallDivs; + WallDivs leftWallDivs, rightWallDivs; Vector2f materialOrigin; if(prepareWallDivs(hedge, Line::Side::Middle, &leftWallDivs, &rightWallDivs, @@ -2267,8 +2263,8 @@ static bool writeWallSections2Twosided(HEdge &hedge, int sections) xtop += surface.visMaterialOrigin()[VY]; // Can we make this a solid segment? - if(!(WallDivNode_Height(WallDivs_Last(&rightWallDivs)) >= xtop && - WallDivNode_Height(WallDivs_First(&leftWallDivs)) <= xbottom)) + if(!(rightWallDivs.last().distance() >= xtop && + leftWallDivs.first().distance() <= xbottom)) opaque = false; } } @@ -2277,7 +2273,7 @@ static bool writeWallSections2Twosided(HEdge &hedge, int sections) // Upper section? if(sections & Line::Side::TopFlag) { - walldivs_t leftWallDivs, rightWallDivs; + WallDivs leftWallDivs, rightWallDivs; Vector2f materialOrigin; if(prepareWallDivs(hedge, Line::Side::Top, &leftWallDivs, &rightWallDivs, @@ -2293,7 +2289,7 @@ static bool writeWallSections2Twosided(HEdge &hedge, int sections) // Lower section? if(sections & Line::Side::BottomFlag) { - walldivs_t leftWallDivs, rightWallDivs; + WallDivs leftWallDivs, rightWallDivs; Vector2f materialOrigin; if(prepareWallDivs(hedge, Line::Side::Bottom, &leftWallDivs, &rightWallDivs, diff --git a/doomsday/client/src/render/rendpoly.cpp b/doomsday/client/src/render/rendpoly.cpp index c7effbf5b9..2b56d61949 100644 --- a/doomsday/client/src/render/rendpoly.cpp +++ b/doomsday/client/src/render/rendpoly.cpp @@ -371,8 +371,8 @@ void Rtu_TranslateOffset(rtexmapunit_t *rtu, Vector2f const &st) rtu->offset[1] += st.y; } -void R_DivVerts(rvertex_t* dst, rvertex_t const* src, walldivnode_t* leftDivFirst, - uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount) +void R_DivVerts(rvertex_t *dst, rvertex_t const *src, WallDivs::Intercept *leftDivFirst, + uint leftDivCount, WallDivs::Intercept *rightDivFirst, uint rightDivCount) { #define COPYVERT(d, s) (d)->pos[VX] = (s)->pos[VX]; \ (d)->pos[VY] = (s)->pos[VY]; \ @@ -390,12 +390,12 @@ void R_DivVerts(rvertex_t* dst, rvertex_t const* src, walldivnode_t* leftDivFirs if(numR > 3) { - walldivnode_t* wdn = rightDivFirst; - for(uint n = 0; n < numR - 3; ++n, wdn = WallDivNode_Prev(wdn)) + WallDivs::Intercept *wdn = rightDivFirst; + for(uint n = 0; n < numR - 3; ++n, wdn = &wdn->prev()) { dst[numL + 2 + n].pos[VX] = src[2].pos[VX]; dst[numL + 2 + n].pos[VY] = src[2].pos[VY]; - dst[numL + 2 + n].pos[VZ] = float( WallDivNode_Height(wdn) ); + dst[numL + 2 + n].pos[VZ] = float( wdn->distance() ); } } @@ -406,20 +406,20 @@ void R_DivVerts(rvertex_t* dst, rvertex_t const* src, walldivnode_t* leftDivFirs if(numL > 3) { - walldivnode_t* wdn = leftDivFirst; - for(uint n = 0; n < numL - 3; ++n, wdn = WallDivNode_Next(wdn)) + WallDivs::Intercept *wdn = leftDivFirst; + for(uint n = 0; n < numL - 3; ++n, wdn = &wdn->next()) { dst[2 + n].pos[VX] = src[0].pos[VX]; dst[2 + n].pos[VY] = src[0].pos[VY]; - dst[2 + n].pos[VZ] = float( WallDivNode_Height(wdn) ); + dst[2 + n].pos[VZ] = float( wdn->distance() ); } } #undef COPYVERT } -void R_DivTexCoords(rtexcoord_t* dst, rtexcoord_t const* src, walldivnode_t* leftDivFirst, - uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount, +void R_DivTexCoords(rtexcoord_t *dst, rtexcoord_t const *src, WallDivs::Intercept *leftDivFirst, + uint leftDivCount, WallDivs::Intercept *rightDivFirst, uint rightDivCount, float bL, float tL, float bR, float tR) { #define COPYTEXCOORD(d, s) (d)->st[0] = (s)->st[0]; \ @@ -437,12 +437,12 @@ void R_DivTexCoords(rtexcoord_t* dst, rtexcoord_t const* src, walldivnode_t* lef if(numR > 3) { - walldivnode_t* wdn = rightDivFirst; + WallDivs::Intercept *wdn = rightDivFirst; float const height = tR - bR; float inter; - for(uint n = 0; n < numR - 3; ++n, wdn = WallDivNode_Prev(wdn)) + for(uint n = 0; n < numR - 3; ++n, wdn = &wdn->prev()) { - inter = (float( WallDivNode_Height(wdn) ) - bR) / height; + inter = (float( wdn->distance() ) - bR) / height; dst[numL + 2 + n].st[0] = src[3].st[0]; dst[numL + 2 + n].st[1] = src[2].st[1] + (src[3].st[1] - src[2].st[1]) * inter; } @@ -455,12 +455,12 @@ void R_DivTexCoords(rtexcoord_t* dst, rtexcoord_t const* src, walldivnode_t* lef if(numL > 3) { - walldivnode_t* wdn = leftDivFirst; + WallDivs::Intercept *wdn = leftDivFirst; float const height = tL - bL; float inter; - for(uint n = 0; n < numL - 3; ++n, wdn = WallDivNode_Next(wdn)) + for(uint n = 0; n < numL - 3; ++n, wdn = &wdn->next()) { - inter = (float( WallDivNode_Height(wdn) ) - bL) / height; + inter = (float( wdn->distance() ) - bL) / height; dst[2 + n].st[0] = src[0].st[0]; dst[2 + n].st[1] = src[0].st[1] + (src[1].st[1] - src[0].st[1]) * inter; } @@ -468,8 +468,8 @@ void R_DivTexCoords(rtexcoord_t* dst, rtexcoord_t const* src, walldivnode_t* lef #undef COPYTEXCOORD } -void R_DivVertColors(ColorRawf* dst, ColorRawf const* src, walldivnode_t* leftDivFirst, - uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount, +void R_DivVertColors(ColorRawf *dst, ColorRawf const *src, WallDivs::Intercept *leftDivFirst, + uint leftDivCount, WallDivs::Intercept *rightDivFirst, uint rightDivCount, float bL, float tL, float bR, float tR) { #define COPYVCOLOR(d, s) (d)->rgba[CR] = (s)->rgba[CR]; \ @@ -489,12 +489,12 @@ void R_DivVertColors(ColorRawf* dst, ColorRawf const* src, walldivnode_t* leftDi if(numR > 3) { - walldivnode_t* wdn = rightDivFirst; + WallDivs::Intercept *wdn = rightDivFirst; float const height = tR - bR; float inter; - for(uint n = 0; n < numR - 3; ++n, wdn = WallDivNode_Prev(wdn)) + for(uint n = 0; n < numR - 3; ++n, wdn = &wdn->prev()) { - inter = (float( WallDivNode_Height(wdn) ) - bR) / height; + inter = (float( wdn->distance() ) - bR) / height; for(uint c = 0; c < 4; ++c) { dst[numL + 2 + n].rgba[c] = src[2].rgba[c] + (src[3].rgba[c] - src[2].rgba[c]) * inter; @@ -509,12 +509,12 @@ void R_DivVertColors(ColorRawf* dst, ColorRawf const* src, walldivnode_t* leftDi if(numL > 3) { - walldivnode_t* wdn = leftDivFirst; + WallDivs::Intercept *wdn = leftDivFirst; float const height = tL - bL; float inter; - for(uint n = 0; n < numL - 3; ++n, wdn = WallDivNode_Next(wdn)) + for(uint n = 0; n < numL - 3; ++n, wdn = &wdn->next()) { - inter = (float( WallDivNode_Height(wdn) ) - bL) / height; + inter = (float( wdn->distance() ) - bL) / height; for(uint c = 0; c < 4; ++c) { dst[2 + n].rgba[c] = src[0].rgba[c] + (src[1].rgba[c] - src[0].rgba[c]) * inter;