From 006ebd5548409719238ba8d171e18651666ed416 Mon Sep 17 00:00:00 2001 From: danij Date: Wed, 23 May 2012 02:46:37 +0100 Subject: [PATCH] Map Renderer: Redesigned mechanism for applying geometry wall divisions This new interface is rather more flexible, allowing for further improvements to the map geometry construction. Note that the walldivs_t structure in its present form is an interim measure only and will soon be replaced entirely. --- doomsday/engine/portable/include/p_maptypes.h | 17 +- doomsday/engine/portable/include/r_data.h | 14 +- .../engine/portable/include/rend_dynlight.h | 12 +- .../engine/portable/include/rend_fakeradio.h | 14 +- .../engine/portable/include/rend_shadow.h | 16 +- doomsday/engine/portable/src/hedge.cpp | 63 +++++- doomsday/engine/portable/src/r_data.c | 137 +++++++------ doomsday/engine/portable/src/rend_dynlight.c | 16 +- doomsday/engine/portable/src/rend_fakeradio.c | 47 +++-- doomsday/engine/portable/src/rend_main.c | 181 ++++++++++-------- doomsday/engine/portable/src/rend_shadow.c | 16 +- 11 files changed, 322 insertions(+), 211 deletions(-) diff --git a/doomsday/engine/portable/include/p_maptypes.h b/doomsday/engine/portable/include/p_maptypes.h index 5a66fff689..4d2f3a4d50 100644 --- a/doomsday/engine/portable/include/p_maptypes.h +++ b/doomsday/engine/portable/include/p_maptypes.h @@ -20,18 +20,29 @@ typedef struct lineowner_s { shadowvert_t shadowOffsets; } lineowner_t; -/// Maximum number of walldivnode_ts in a walldivs_t dataset. -#define WALLDIVS_MAX_NODES 64 +struct walldivs_s; typedef struct walldivnode_s { + struct walldivs_s* divs; coord_t height; } walldivnode_t; +coord_t WallDivNode_Height(walldivnode_t* node); +walldivnode_t* WallDivNode_Next(walldivnode_t* node); +walldivnode_t* WallDivNode_Prev(walldivnode_t* node); + +/// Maximum number of walldivnode_ts in a walldivs_t dataset. +#define WALLDIVS_MAX_NODES 64 + typedef struct walldivs_s { uint num; - walldivnode_t nodes[WALLDIVS_MAX_NODES]; + struct walldivnode_s nodes[WALLDIVS_MAX_NODES]; } walldivs_t; +uint WallDivs_Size(const walldivs_t* wallDivs); +walldivnode_t* WallDivs_First(walldivs_t* wallDivs); +walldivnode_t* WallDivs_Last(walldivs_t* wallDivs); + typedef struct mvertex_s { // Vertex index. Always valid after loading and pruning of unused // vertices has occurred. diff --git a/doomsday/engine/portable/include/r_data.h b/doomsday/engine/portable/include/r_data.h index 9f7f844983..98e6075271 100644 --- a/doomsday/engine/portable/include/r_data.h +++ b/doomsday/engine/portable/include/r_data.h @@ -292,14 +292,16 @@ void R_FreeRendColors(ColorRawf* rcolors); void R_FreeRendTexCoords(rtexcoord_t* rtexcoords); void R_InfoRendVerticesPool(void); -void R_DivVerts(rvertex_t* dst, const rvertex_t* src, const walldivs_t* leftDivs, - const walldivs_t* rightDivs); +void R_DivVerts(rvertex_t* dst, const rvertex_t* src, + walldivnode_t* leftDivFirst, uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount); -void R_DivVertColors(ColorRawf* dst, const ColorRawf* src, const walldivs_t* leftDivs, - const walldivs_t* rightDivs, float bL, float tL, float bR, float tR); +void R_DivTexCoords(rtexcoord_t* dst, const rtexcoord_t* src, + walldivnode_t* leftDivFirst, uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount, + float bL, float tL, float bR, float tR); -void R_DivTexCoords(rtexcoord_t* dst, const rtexcoord_t* src, const walldivs_t* leftDivs, - const walldivs_t* rightDivs, float bL, float tL, float bR, float tR); +void R_DivVertColors(ColorRawf* dst, const ColorRawf* src, + walldivnode_t* leftDivFirst, uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount, + float bL, float tL, float bR, float tR); void R_InitTranslationTables(void); void R_UpdateTranslationTables(void); diff --git a/doomsday/engine/portable/include/rend_dynlight.h b/doomsday/engine/portable/include/rend_dynlight.h index c0f5d24d87..1cc1bb8d52 100644 --- a/doomsday/engine/portable/include/rend_dynlight.h +++ b/doomsday/engine/portable/include/rend_dynlight.h @@ -32,8 +32,16 @@ typedef struct { uint numVertices, realNumVertices; const coord_t* texTL, *texBR; boolean isWall; - const walldivs_t* leftWallDivs; - const walldivs_t* rightWallDivs; + struct { + struct { + walldivnode_t* firstDiv; + uint divCount; + } left; + struct { + walldivnode_t* firstDiv; + uint divCount; + } right; + } wall; } renderlightprojectionparams_t; /** diff --git a/doomsday/engine/portable/include/rend_fakeradio.h b/doomsday/engine/portable/include/rend_fakeradio.h index aeb387e1a5..2ff3876d51 100644 --- a/doomsday/engine/portable/include/rend_fakeradio.h +++ b/doomsday/engine/portable/include/rend_fakeradio.h @@ -38,6 +38,16 @@ typedef struct { const coord_t* segLength; const coord_t* linedefLength; const Sector* frontSec, *backSec; + struct { + struct { + walldivnode_t* firstDiv; + uint divCount; + } left; + struct { + walldivnode_t* firstDiv; + uint divCount; + } right; + } wall; } rendsegradio_params_t; /// Register the console commands, variables, etc..., of this module. @@ -54,9 +64,7 @@ void Rend_RadioUpdateLinedef(LineDef* line, boolean backSide); /** * Render FakeRadio for the given hedge section. */ -void Rend_RadioSegSection(const rvertex_t* rvertices, - const walldivs_t* leftWallDivs, const walldivs_t* rightWallDivs, - const rendsegradio_params_t* params); +void Rend_RadioSegSection(const rvertex_t* rvertices, const rendsegradio_params_t* params); /** * Render FakeRadio for the given BSP leaf. diff --git a/doomsday/engine/portable/include/rend_shadow.h b/doomsday/engine/portable/include/rend_shadow.h index a8d9bd2a9c..845e11d401 100644 --- a/doomsday/engine/portable/include/rend_shadow.h +++ b/doomsday/engine/portable/include/rend_shadow.h @@ -42,19 +42,27 @@ boolean Rend_MobjShadowsEnabled(void); */ void Rend_RenderMobjShadows(void); -/// Paramaters for Rend_RenderShadowProjections (POD). +/// Parameters for Rend_RenderShadowProjections (POD). typedef struct { uint lastIdx; const rvertex_t* rvertices; uint numVertices, realNumVertices; const coord_t* texTL, *texBR; boolean isWall; - const walldivs_t* leftWallDivs; - const walldivs_t* rightWallDivs; + struct { + struct { + walldivnode_t* firstDiv; + uint divCount; + } left; + struct { + walldivnode_t* firstDiv; + uint divCount; + } right; + } wall; } rendershadowprojectionparams_t; /** - * Render all shadows in projection list @a listIdx according to @a paramaters + * Render all shadows in projection list @a listIdx according to @a parameters * writing them to the renderering lists for the current frame. */ void Rend_RenderShadowProjections(uint listIdx, rendershadowprojectionparams_t* paramaters); diff --git a/doomsday/engine/portable/src/hedge.cpp b/doomsday/engine/portable/src/hedge.cpp index 34547161c7..de011d228c 100644 --- a/doomsday/engine/portable/src/hedge.cpp +++ b/doomsday/engine/portable/src/hedge.cpp @@ -25,6 +25,46 @@ #include "de_play.h" #include "de_refresh.h" +coord_t WallDivNode_Height(walldivnode_t* node) +{ + assert(node); + return node->height; +} + +walldivnode_t* WallDivNode_Next(walldivnode_t* node) +{ + 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) +{ + assert(node); + uint idx = node - node->divs->nodes; + if(idx == 0) return 0; + return &node->divs->nodes[idx-1]; +} + +uint WallDivs_Size(const walldivs_t* wd) +{ + assert(wd); + return wd->num; +} + +walldivnode_t* WallDivs_First(walldivs_t* wd) +{ + assert(wd); + return &wd->nodes[0]; +} + +walldivnode_t* WallDivs_Last(walldivs_t* wd) +{ + assert(wd); + return &wd->nodes[wd->num-1]; +} + static int C_DECL sortWallDivNode(const void* e1, const void* e2) { const coord_t h1 = ((walldivnode_t*)e1)->height; @@ -34,7 +74,15 @@ static int C_DECL sortWallDivNode(const void* e1, const void* e2) return 0; } -static walldivnode_t* findWallDivNodeByZOrigin(walldivs_t* wallDivs, float height) +static void addWallDivNode(walldivs_t* wd, coord_t height) +{ + assert(wd); + struct walldivnode_s* node = &wd->nodes[wd->num++]; + node->divs = wd; + node->height = height; +} + +static walldivnode_t* findWallDivNodeByZOrigin(walldivs_t* wallDivs, coord_t height) { Q_ASSERT(wallDivs); for(uint i = 0; i < wallDivs->num; ++i) @@ -110,7 +158,7 @@ static void addWallDivNodesForPlaneIntercepts(HEdge* hedge, walldivs_t* wallDivs { if(!findWallDivNodeByZOrigin(wallDivs, pln->visHeight)) { - wallDivs->nodes[wallDivs->num++].height = pln->visHeight; + addWallDivNode(wallDivs, pln->visHeight); // Have we reached the div limit? if(wallDivs->num == WALLDIVS_MAX_NODES) @@ -147,7 +195,7 @@ static void addWallDivNodesForPlaneIntercepts(HEdge* hedge, walldivs_t* wallDivs { if(!findWallDivNodeByZOrigin(wallDivs, z)) { - wallDivs->nodes[wallDivs->num++].height = z; + addWallDivNode(wallDivs, z); // Have we reached the div limit? if(wallDivs->num == WALLDIVS_MAX_NODES) @@ -170,14 +218,15 @@ static void buildWallDiv(walldivs_t* wallDivs, HEdge* hedge, { wallDivs->num = 0; - // Add the first node. - wallDivs->nodes[wallDivs->num++].height = bottomZ; + // Nodes are arranged according to their Z axis height in ascending order. + // The first node is the bottom. + addWallDivNode(wallDivs, bottomZ); // Add nodes for intercepts. addWallDivNodesForPlaneIntercepts(hedge, wallDivs, section, bottomZ, topZ, doRight); - // Add the last node. - wallDivs->nodes[wallDivs->num++].height = topZ; + // The last node is the top. + addWallDivNode(wallDivs, topZ); if(!(wallDivs->num > 2)) return; diff --git a/doomsday/engine/portable/src/r_data.c b/doomsday/engine/portable/src/r_data.c index 34bf3dc110..326492fdfb 100644 --- a/doomsday/engine/portable/src/r_data.c +++ b/doomsday/engine/portable/src/r_data.c @@ -896,30 +896,33 @@ void Rtu_TranslateOffsetv(rtexmapunit_t* rtu, float const st[2]) Rtu_TranslateOffset(rtu, st[0], st[1]); } -void R_DivVerts(rvertex_t* dst, const rvertex_t* src, const walldivs_t* leftDivs, - const walldivs_t* rightDivs) +void R_DivVerts(rvertex_t* dst, const rvertex_t* src, + walldivnode_t* leftDivFirst, uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount) { #define COPYVERT(d, s) (d)->pos[VX] = (s)->pos[VX]; \ (d)->pos[VY] = (s)->pos[VY]; \ (d)->pos[VZ] = (s)->pos[VZ]; - uint i, numL, numR; + uint const numR = 3 + (rightDivFirst && rightDivCount? rightDivCount : 0); + uint const numL = 3 + (leftDivFirst && leftDivCount ? leftDivCount : 0); - assert(leftDivs && rightDivs); - - numL = 1 + leftDivs->num; - numR = 1 + rightDivs->num; + if(numR + numL == 6) return; // Nothing to do. // Right fan: COPYVERT(&dst[numL + 0], &src[0]) COPYVERT(&dst[numL + 1], &src[3]); COPYVERT(&dst[numL + numR - 1], &src[2]); - for(i = 0; i < rightDivs->num - 2; ++i) + if(numR > 3) { - dst[numL + 2 + i].pos[VX] = src[2].pos[VX]; - dst[numL + 2 + i].pos[VY] = src[2].pos[VY]; - dst[numL + 2 + i].pos[VZ] = rightDivs->nodes[rightDivs->num-1 - 1 - i].height; + walldivnode_t* wdn = rightDivFirst; + uint n; + for(n = 0; n < numR - 3; ++n, wdn = WallDivNode_Prev(wdn)) + { + 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); + } } // Left fan: @@ -927,43 +930,49 @@ void R_DivVerts(rvertex_t* dst, const rvertex_t* src, const walldivs_t* leftDivs COPYVERT(&dst[1], &src[0]); COPYVERT(&dst[numL - 1], &src[1]); - for(i = 0; i < leftDivs->num - 2; ++i) + if(numL > 3) { - dst[2 + i].pos[VX] = src[0].pos[VX]; - dst[2 + i].pos[VY] = src[0].pos[VY]; - dst[2 + i].pos[VZ] = leftDivs->nodes[1 + i].height; + walldivnode_t* wdn = leftDivFirst; + uint n; + for(n = 0; n < numL - 3; ++n, wdn = WallDivNode_Next(wdn)) + { + 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); + } } #undef COPYVERT } -void R_DivTexCoords(rtexcoord_t* dst, const rtexcoord_t* src, const walldivs_t* leftDivs, - const walldivs_t* rightDivs, float bL, float tL, float bR, float tR) +void R_DivTexCoords(rtexcoord_t* dst, const rtexcoord_t* src, + walldivnode_t* leftDivFirst, uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount, + float bL, float tL, float bR, float tR) { #define COPYTEXCOORD(d, s) (d)->st[0] = (s)->st[0]; \ (d)->st[1] = (s)->st[1]; - uint i, numL, numR; - float height; + uint const numR = 3 + (rightDivFirst && rightDivCount? rightDivCount : 0); + uint const numL = 3 + (leftDivFirst && leftDivCount ? leftDivCount : 0); - assert(leftDivs && rightDivs); - - numL = 1 + leftDivs->num; - numR = 1 + rightDivs->num; + if(numR + numL == 6) return; // Nothing to do. // Right fan: COPYTEXCOORD(&dst[numL + 0], &src[0]); COPYTEXCOORD(&dst[numL + 1], &src[3]); COPYTEXCOORD(&dst[numL + numR-1], &src[2]); - height = tR - bR; - for(i = 0; i < rightDivs->num - 2; ++i) + if(numR > 3) { - float inter = (rightDivs->nodes[rightDivs->num-1 - 1 - i].height - bR) / height; - - dst[numL + 2 + i].st[0] = src[3].st[0]; - dst[numL + 2 + i].st[1] = src[2].st[1] + - (src[3].st[1] - src[2].st[1]) * inter; + walldivnode_t* wdn = rightDivFirst; + float height = tR - bR, inter; + uint n; + for(n = 0; n < numR - 3; ++n, wdn = WallDivNode_Prev(wdn)) + { + inter = ((float)WallDivNode_Height(wdn) - 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; + } } // Left fan: @@ -971,50 +980,52 @@ void R_DivTexCoords(rtexcoord_t* dst, const rtexcoord_t* src, const walldivs_t* COPYTEXCOORD(&dst[1], &src[0]); COPYTEXCOORD(&dst[numL - 1], &src[1]); - height = tL - bL; - for(i = 0; i < leftDivs->num - 2; ++i) + if(numL > 3) { - float inter = (leftDivs->nodes[1 + i].height - bL) / height; - - dst[2 + i].st[0] = src[0].st[0]; - dst[2 + i].st[1] = src[0].st[1] + - (src[1].st[1] - src[0].st[1]) * inter; + walldivnode_t* wdn = leftDivFirst; + float height = tL - bL, inter; + uint n; + for(n = 0; n < numL - 3; ++n, wdn = WallDivNode_Next(wdn)) + { + inter = ((float)WallDivNode_Height(wdn) - 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; + } } - #undef COPYTEXCOORD } -void R_DivVertColors(ColorRawf* dst, const ColorRawf* src, const walldivs_t* leftDivs, - const walldivs_t* rightDivs, float bL, float tL, float bR, float tR) +void R_DivVertColors(ColorRawf* dst, const ColorRawf* src, + walldivnode_t* leftDivFirst, uint leftDivCount, walldivnode_t* rightDivFirst, uint rightDivCount, + float bL, float tL, float bR, float tR) { #define COPYVCOLOR(d, s) (d)->rgba[CR] = (s)->rgba[CR]; \ (d)->rgba[CG] = (s)->rgba[CG]; \ (d)->rgba[CB] = (s)->rgba[CB]; \ (d)->rgba[CA] = (s)->rgba[CA]; - uint i, numL, numR = 3 + (rightDivs->num-2); - float height; + uint const numR = 3 + (rightDivFirst && rightDivCount? rightDivCount : 0); + uint const numL = 3 + (leftDivFirst && leftDivCount ? leftDivCount : 0); - assert(leftDivs && rightDivs); - - numL = 1 + leftDivs->num; - numR = 1 + rightDivs->num; + if(numR + numL == 6) return; // Nothing to do. // Right fan: COPYVCOLOR(&dst[numL + 0], &src[0]); COPYVCOLOR(&dst[numL + 1], &src[3]); COPYVCOLOR(&dst[numL + numR-1], &src[2]); - height = tR - bR; - for(i = 0; i < rightDivs->num - 2; ++i) + if(numR > 3) { - uint c; - float inter = (rightDivs->nodes[rightDivs->num-1 - 1 - i].height - bR) / height; - - for(c = 0; c < 4; ++c) + walldivnode_t* wdn = rightDivFirst; + float height = tR - bR, inter; + uint n, c; + for(n = 0; n < numR - 3; ++n, wdn = WallDivNode_Prev(wdn)) { - dst[numL + 2 + i].rgba[c] = src[2].rgba[c] + - (src[3].rgba[c] - src[2].rgba[c]) * inter; + inter = ((float)WallDivNode_Height(wdn) - bR) / height; + for(c = 0; c < 4; ++c) + { + dst[numL + 2 + n].rgba[c] = src[2].rgba[c] + (src[3].rgba[c] - src[2].rgba[c]) * inter; + } } } @@ -1023,16 +1034,18 @@ void R_DivVertColors(ColorRawf* dst, const ColorRawf* src, const walldivs_t* lef COPYVCOLOR(&dst[1], &src[0]); COPYVCOLOR(&dst[numL - 1], &src[1]); - height = tL - bL; - for(i = 0; i < leftDivs->num - 2; ++i) + if(numL > 3) { - uint c; - float inter = (leftDivs->nodes[1 + i].height - bL) / height; - - for(c = 0; c < 4; ++c) + walldivnode_t* wdn = leftDivFirst; + float height = tL - bL, inter; + uint n, c; + for(n = 0; n < numL - 3; ++n, wdn = WallDivNode_Next(wdn)) { - dst[2 + i].rgba[c] = src[0].rgba[c] + - (src[1].rgba[c] - src[0].rgba[c]) * inter; + inter = ((float)WallDivNode_Height(wdn) - bL) / height; + for(c = 0; c < 4; ++c) + { + dst[2 + n].rgba[c] = src[0].rgba[c] + (src[1].rgba[c] - src[0].rgba[c]) * inter; + } } } diff --git a/doomsday/engine/portable/src/rend_dynlight.c b/doomsday/engine/portable/src/rend_dynlight.c index 23e9060936..5933c37a1e 100644 --- a/doomsday/engine/portable/src/rend_dynlight.c +++ b/doomsday/engine/portable/src/rend_dynlight.c @@ -59,7 +59,7 @@ int RIT_RenderLightProjectionIterator(const dynlight_t* dyn, void* paramaters) rtexcoords[3].st[0] = rtexcoords[2].st[0] = dyn->s[1]; rtexcoords[2].st[1] = rtexcoords[0].st[1] = dyn->t[1]; - if(p->leftWallDivs->num > 2 || p->rightWallDivs->num > 2) + if(p->wall.left.divCount || p->wall.right.divCount) { // We need to subdivide the projection quad. float bL, tL, bR, tR; @@ -82,9 +82,9 @@ int RIT_RenderLightProjectionIterator(const dynlight_t* dyn, void* paramaters) bR = p->rvertices[2].pos[VZ]; tR = p->rvertices[3].pos[VZ]; - R_DivVerts(rvertices, origVerts, p->leftWallDivs, p->rightWallDivs); - R_DivTexCoords(rtexcoords, origTexCoords, p->leftWallDivs, p->rightWallDivs, bL, tL, bR, tR); - R_DivVertColors(rcolors, origColors, p->leftWallDivs, p->rightWallDivs, bL, tL, bR, tR); + R_DivVerts(rvertices, origVerts, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount); + R_DivTexCoords(rtexcoords, origTexCoords, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); + R_DivVertColors(rcolors, origColors, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); } else { @@ -114,13 +114,13 @@ int RIT_RenderLightProjectionIterator(const dynlight_t* dyn, void* paramaters) RL_LoadDefaultRtus(); RL_Rtu_SetTextureUnmanaged(RTU_PRIMARY, dyn->texture); - if(p->isWall && (p->leftWallDivs->num > 2 || p->rightWallDivs->num > 2)) + if(p->isWall && (p->wall.left.divCount || p->wall.right.divCount)) { RL_AddPolyWithCoords(PT_FAN, RPF_DEFAULT|RPF_LIGHT, - 1 + p->rightWallDivs->num, rvertices + 1 + p->leftWallDivs->num, - rcolors + 1 + p->leftWallDivs->num, rtexcoords + 1 + p->leftWallDivs->num, NULL); + 3 + p->wall.right.divCount, rvertices + 3 + p->wall.left.divCount, + rcolors + 3 + p->wall.left.divCount, rtexcoords + 3 + p->wall.left.divCount, NULL); RL_AddPolyWithCoords(PT_FAN, RPF_DEFAULT|RPF_LIGHT, - 1 + p->leftWallDivs->num, rvertices, rcolors, rtexcoords, NULL); + 3 + p->wall.left.divCount, rvertices, rcolors, rtexcoords, NULL); } else { diff --git a/doomsday/engine/portable/src/rend_fakeradio.c b/doomsday/engine/portable/src/rend_fakeradio.c index 869dc63eee..474bc823d6 100644 --- a/doomsday/engine/portable/src/rend_fakeradio.c +++ b/doomsday/engine/portable/src/rend_fakeradio.c @@ -964,17 +964,16 @@ static void quadTexCoords(rtexcoord_t* tc, const rvertex_t* rverts, tc[0].st[1] = tc[3].st[1] + (rverts[3].pos[VZ] - rverts[2].pos[VZ]) / texHeight; } -static void renderShadowSeg(const rvertex_t* origVertices, const walldivs_t* leftWallDivs, - const walldivs_t* rightWallDivs, const rendershadowseg_params_t* p, - const float shadowRGB[3], float shadowDark) +static void renderShadowSeg(const rvertex_t* origVertices, const rendershadowseg_params_t* segp, + const rendsegradio_params_t* p) { float texOrigin[2][3]; ColorRawf* rcolors; rtexcoord_t* rtexcoords; uint realNumVertices = 4; - if(leftWallDivs->num > 2 || rightWallDivs->num > 2) - realNumVertices = 1 + leftWallDivs->num + 1 + rightWallDivs->num; + if(p->wall.left.divCount || p->wall.right.divCount) + realNumVertices = 3 + p->wall.left.divCount + 3 + p->wall.right.divCount; else realNumVertices = 4; @@ -992,19 +991,19 @@ static void renderShadowSeg(const rvertex_t* origVertices, const walldivs_t* lef rtexcoords = R_AllocRendTexCoords(realNumVertices); rcolors = R_AllocRendColors(realNumVertices); - quadTexCoords(rtexcoords, origVertices, p->wallLength, p->texWidth, - p->texHeight, texOrigin, p->texOffset, - p->horizontal); + quadTexCoords(rtexcoords, origVertices, segp->wallLength, segp->texWidth, + segp->texHeight, texOrigin, segp->texOffset, + segp->horizontal); - setRendpolyColor(rcolors, 4, shadowRGB, shadowDark * p->shadowMul); + setRendpolyColor(rcolors, 4, p->shadowRGB, p->shadowDark * segp->shadowMul); if(rendFakeRadio != 2) { // Write multiple polys depending on rend params. RL_LoadDefaultRtus(); - RL_Rtu_SetTextureUnmanaged(RTU_PRIMARY, GL_PrepareLSTexture(p->texture)); + RL_Rtu_SetTextureUnmanaged(RTU_PRIMARY, GL_PrepareLSTexture(segp->texture)); - if(leftWallDivs->num > 2 || rightWallDivs->num > 2) + if(p->wall.left.divCount || p->wall.right.divCount) { float bL, tL, bR, tR; rvertex_t* rvertices; @@ -1027,15 +1026,15 @@ static void renderShadowSeg(const rvertex_t* origVertices, const walldivs_t* lef bR = origVertices[2].pos[VZ]; tR = origVertices[3].pos[VZ]; - R_DivVerts(rvertices, origVertices, leftWallDivs, rightWallDivs); - R_DivTexCoords(rtexcoords, origTexCoords, leftWallDivs, rightWallDivs, bL, tL, bR, tR); - R_DivVertColors(rcolors, origColors, leftWallDivs, rightWallDivs, bL, tL, bR, tR); + R_DivVerts(rvertices, origVertices, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount); + R_DivTexCoords(rtexcoords, origTexCoords, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); + R_DivVertColors(rcolors, origColors, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); RL_AddPolyWithCoords(PT_FAN, RPF_DEFAULT|RPF_SHADOW, - 1 + rightWallDivs->num, rvertices + 1 + leftWallDivs->num, rcolors + 1 + leftWallDivs->num, - rtexcoords + 1 + leftWallDivs->num, NULL); + 3 + p->wall.right.divCount, rvertices + 3 + p->wall.left.divCount, rcolors + 3 + p->wall.left.divCount, + rtexcoords + 3 + p->wall.left.divCount, NULL); RL_AddPolyWithCoords(PT_FAN, RPF_DEFAULT|RPF_SHADOW, - 1 + leftWallDivs->num, rvertices, rcolors, rtexcoords, NULL); + 3 + p->wall.left.divCount, rvertices, rcolors, rtexcoords, NULL); R_FreeRendVertices(rvertices); } @@ -1054,7 +1053,6 @@ static void renderShadowSeg(const rvertex_t* origVertices, const walldivs_t* lef * Create the appropriate FakeRadio shadow polygons for the wall segment. */ static void rendRadioSegSection(const rvertex_t* rvertices, - const walldivs_t* leftWallDivs, const walldivs_t* rightWallDivs, const rendsegradio_params_t* p) { const coord_t* fFloor, *fCeil, *bFloor, *bCeil; @@ -1088,7 +1086,7 @@ static void rendRadioSegSection(const rvertex_t* rvertices, setTopShadowParams(¶ms, p->shadowSize, rvertices[1].pos[VZ], p->segOffset, p->segLength, fFloor, fCeil, p->botCn, p->topCn, p->sideCn, p->spans); - renderShadowSeg(rvertices, leftWallDivs, rightWallDivs, ¶ms, p->shadowRGB, p->shadowDark); + renderShadowSeg(rvertices, ¶ms, p); } } @@ -1105,7 +1103,7 @@ static void rendRadioSegSection(const rvertex_t* rvertices, setBottomShadowParams(¶ms, p->shadowSize, rvertices[1].pos[VZ], p->segOffset, p->segLength, fFloor, fCeil, p->botCn, p->topCn, p->sideCn, p->spans); - renderShadowSeg(rvertices, leftWallDivs, rightWallDivs, ¶ms, p->shadowRGB, p->shadowDark); + renderShadowSeg(rvertices, ¶ms, p); } } @@ -1126,7 +1124,7 @@ static void rendRadioSegSection(const rvertex_t* rvertices, bottomGlow, topGlow, p->segOffset, p->segLength, fFloor, fCeil, bFloor, bCeil, p->linedefLength, p->sideCn); - renderShadowSeg(rvertices, leftWallDivs, rightWallDivs, ¶ms, p->shadowRGB, p->shadowDark); + renderShadowSeg(rvertices, ¶ms, p); } /* @@ -1142,18 +1140,17 @@ static void rendRadioSegSection(const rvertex_t* rvertices, bottomGlow, topGlow, p->segOffset, p->segLength, fFloor, fCeil, bFloor, bCeil, p->linedefLength, p->sideCn); - renderShadowSeg(rvertices, leftWallDivs, rightWallDivs, ¶ms, p->shadowRGB, p->shadowDark); + renderShadowSeg(rvertices, ¶ms, p); } } -void Rend_RadioSegSection(const rvertex_t* rvertices, const walldivs_t* leftWallDivs, - const walldivs_t* rightWallDivs, const rendsegradio_params_t* params) +void Rend_RadioSegSection(const rvertex_t* rvertices, const rendsegradio_params_t* params) { if(!rvertices || !params) return; // Disabled? if(!rendFakeRadio || levelFullBright) return; - rendRadioSegSection(rvertices, leftWallDivs, rightWallDivs, params); + rendRadioSegSection(rvertices, params); } /** diff --git a/doomsday/engine/portable/src/rend_main.c b/doomsday/engine/portable/src/rend_main.c index 7c51977751..aadd239e7f 100644 --- a/doomsday/engine/portable/src/rend_main.c +++ b/doomsday/engine/portable/src/rend_main.c @@ -748,19 +748,28 @@ typedef struct { uint elmIdx; biassurface_t* bsuf; -// Wall only (todo). - const coord_t* segLength; - const float* surfaceColor2; // Secondary color. +// Wall only: + struct { + const coord_t* segLength; + const float* surfaceColor2; // Secondary color. + struct { + walldivnode_t* firstDiv; + uint divCount; + } left; + struct { + walldivnode_t* firstDiv; + uint divCount; + } right; + } wall; } rendworldpoly_params_t; static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, - const walldivs_t* leftWallDivs, const walldivs_t* rightWallDivs, const rendworldpoly_params_t* p, const materialsnapshot_t* msA, float inter, const materialsnapshot_t* msB) { boolean useLights = false, useShadows = false, hasDynlights = false; rtexcoord_t* primaryCoords = NULL, *interCoords = NULL, *modCoords = NULL; - uint realNumVertices = ((p->isWall && (leftWallDivs->num > 2 || rightWallDivs->num > 2))? 1 + leftWallDivs->num + 1 + rightWallDivs->num : numVertices); + uint realNumVertices = ((p->isWall && (p->wall.left.divCount || p->wall.right.divCount))? 3 + p->wall.left.divCount + 3 + p->wall.right.divCount : numVertices); ColorRawf* rcolors; ColorRawf* shinyColors = NULL; rtexcoord_t* shinyTexCoords = NULL; @@ -832,15 +841,15 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, if(p->isWall) { // Primary texture coordinates. - quadTexCoords(primaryCoords, rvertices, *p->segLength, p->texTL); + quadTexCoords(primaryCoords, rvertices, *p->wall.segLength, p->texTL); // Blend texture coordinates. if(interRTU && !drawAsVisSprite) - quadTexCoords(interCoords, rvertices, *p->segLength, p->texTL); + quadTexCoords(interCoords, rvertices, *p->wall.segLength, p->texTL); // Shiny texture coordinates. if(shinyRTU && !drawAsVisSprite) - quadShinyTexCoords(shinyTexCoords, &rvertices[1], &rvertices[2], *p->segLength); + quadShinyTexCoords(shinyTexCoords, &rvertices[1], &rvertices[2], *p->wall.segLength); // First light texture coordinates. if(modTex && RL_IsMTexLights()) @@ -965,14 +974,14 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, } // Bottom color (if different from top)? - if(p->isWall && p->surfaceColor2) + if(p->isWall && p->wall.surfaceColor2) { float vColor[4]; // Blend sector light+color+surfacecolor - vColor[CR] = p->surfaceColor2[CR] * p->sectorLightColor[CR]; - vColor[CG] = p->surfaceColor2[CG] * p->sectorLightColor[CG]; - vColor[CB] = p->surfaceColor2[CB] * p->sectorLightColor[CB]; + vColor[CR] = p->wall.surfaceColor2[CR] * p->sectorLightColor[CR]; + vColor[CG] = p->wall.surfaceColor2[CG] * p->sectorLightColor[CG]; + vColor[CB] = p->wall.surfaceColor2[CB] * p->sectorLightColor[CB]; vColor[CA] = 1; lightVertex(&rcolors[0], &rvertices[0], llL, vColor); @@ -1037,7 +1046,7 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, * This is needed because all masked polys must be sorted (sprites * are masked polys). Otherwise there will be artifacts. */ - Rend_AddMaskedPoly(rvertices, rcolors, *p->segLength, msA->material, + Rend_AddMaskedPoly(rvertices, rcolors, *p->wall.segLength, msA->material, p->texOffset, p->blendMode, p->lightListIdx, glowing); R_FreeRendTexCoords(primaryCoords); @@ -1060,11 +1069,16 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, params.numVertices = numVertices; params.realNumVertices = realNumVertices; params.lastIdx = 0; - params.isWall = p->isWall; - params.leftWallDivs = leftWallDivs; - params.rightWallDivs = rightWallDivs; params.texTL = p->texTL; params.texBR = p->texBR; + params.isWall = p->isWall; + if(p->isWall) + { + params.wall.left.firstDiv = p->wall.left.firstDiv; + params.wall.left.divCount = p->wall.left.divCount; + params.wall.right.firstDiv = p->wall.right.firstDiv; + params.wall.right.divCount = p->wall.right.divCount; + } hasDynlights = (0 != Rend_RenderLightProjections(p->lightListIdx, ¶ms)); } @@ -1077,11 +1091,16 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, params.rvertices = rvertices; params.numVertices = numVertices; params.realNumVertices = realNumVertices; - params.isWall = p->isWall; - params.leftWallDivs = leftWallDivs; - params.rightWallDivs = rightWallDivs; params.texTL = p->texTL; params.texBR = p->texBR; + params.isWall = p->isWall; + if(p->isWall) + { + params.wall.left.firstDiv = p->wall.left.firstDiv; + params.wall.left.divCount = p->wall.left.divCount; + params.wall.right.firstDiv = p->wall.right.firstDiv; + params.wall.right.divCount = p->wall.right.divCount; + } Rend_RenderShadowProjections(p->shadowListIdx, ¶ms); } @@ -1136,7 +1155,7 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, } // Write multiple polys depending on rend params. - if(p->isWall && (leftWallDivs->num > 2 || rightWallDivs->num > 2)) + if(p->isWall && (p->wall.left.divCount || p->wall.right.divCount)) { float bL, tL, bR, tR; rvertex_t origVerts[4]; @@ -1158,16 +1177,16 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, bR = origVerts[2].pos[VZ]; tR = origVerts[3].pos[VZ]; - R_DivVerts(rvertices, origVerts, leftWallDivs, rightWallDivs); - R_DivTexCoords(primaryCoords, origTexCoords, leftWallDivs, rightWallDivs, bL, tL, bR, tR); - R_DivVertColors(rcolors, origColors, leftWallDivs, rightWallDivs, bL, tL, bR, tR); + R_DivVerts(rvertices, origVerts, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount); + R_DivTexCoords(primaryCoords, origTexCoords, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); + R_DivVertColors(rcolors, origColors, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); if(interCoords) { rtexcoord_t origTexCoords2[4]; memcpy(origTexCoords2, interCoords, sizeof(rtexcoord_t) * 4); - R_DivTexCoords(interCoords, origTexCoords2, leftWallDivs, rightWallDivs, bL, tL, bR, tR); + R_DivTexCoords(interCoords, origTexCoords2, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); } if(modCoords) @@ -1175,7 +1194,7 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, rtexcoord_t origTexCoords5[4]; memcpy(origTexCoords5, modCoords, sizeof(rtexcoord_t) * 4); - R_DivTexCoords(modCoords, origTexCoords5, leftWallDivs, rightWallDivs, bL, tL, bR, tR); + R_DivTexCoords(modCoords, origTexCoords5, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); } if(shinyTexCoords) @@ -1183,25 +1202,25 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, rtexcoord_t origShinyTexCoords[4]; memcpy(origShinyTexCoords, shinyTexCoords, sizeof(rtexcoord_t) * 4); - R_DivTexCoords(shinyTexCoords, origShinyTexCoords, leftWallDivs, rightWallDivs, bL, tL, bR, tR); + R_DivTexCoords(shinyTexCoords, origShinyTexCoords, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); } if(shinyColors) { ColorRawf origShinyColors[4]; memcpy(origShinyColors, shinyColors, sizeof(ColorRawf) * 4); - R_DivVertColors(shinyColors, origShinyColors, leftWallDivs, rightWallDivs, bL, tL, bR, tR); + R_DivVertColors(shinyColors, origShinyColors, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); } RL_AddPolyWithCoordsModulationReflection(PT_FAN, p->flags | (hasDynlights? RPF_HAS_DYNLIGHTS : 0), - 1 + rightWallDivs->num, rvertices + 1 + leftWallDivs->num, rcolors + 1 + leftWallDivs->num, - primaryCoords + 1 + leftWallDivs->num, interCoords? interCoords + 1 + leftWallDivs->num : NULL, - modTex, &modColor, modCoords? modCoords + 1 + leftWallDivs->num : NULL, - shinyColors + 1 + leftWallDivs->num, shinyTexCoords? shinyTexCoords + 1 + leftWallDivs->num : NULL, - shinyMaskRTU? primaryCoords + 1 + leftWallDivs->num : NULL); + 3 + p->wall.right.divCount, rvertices + 3 + p->wall.left.divCount, rcolors + 3 + p->wall.left.divCount, + primaryCoords + 3 + p->wall.left.divCount, interCoords? interCoords + 3 + p->wall.left.divCount : NULL, + modTex, &modColor, modCoords? modCoords + 3 + p->wall.left.divCount : NULL, + shinyColors + 3 + p->wall.left.divCount, shinyTexCoords? shinyTexCoords + 3 + p->wall.left.divCount : NULL, + shinyMaskRTU? primaryCoords + 3 + p->wall.left.divCount : NULL); RL_AddPolyWithCoordsModulationReflection(PT_FAN, p->flags | (hasDynlights? RPF_HAS_DYNLIGHTS : 0), - 1 + leftWallDivs->num, rvertices, rcolors, + 3 + p->wall.left.divCount, rvertices, rcolors, primaryCoords, interCoords, modTex, &modColor, modCoords, shinyColors, shinyTexCoords, shinyMaskRTU? primaryCoords : NULL); @@ -1230,37 +1249,27 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, !(p->alpha < 1 || !msA->isOpaque || p->blendMode > 0)); } -static boolean doRenderHEdge(HEdge* hedge, - const pvec3f_t normal, - float alpha, - float lightLevel, float lightLevelDL, - float lightLevelDR, - const float* lightColor, - uint lightListIdx, - uint shadowListIdx, - const walldivs_t* leftWallDivs, const walldivs_t* rightWallDivs, - boolean skyMask, - boolean addFakeRadio, - vec3d_t texTL, vec3d_t texBR, - float const texOffset[2], - float const texScale[2], - blendmode_t blendMode, - const float* color, const float* color2, - biassurface_t* bsuf, uint elmIdx /*tmp*/, - const materialsnapshot_t* msA, float inter, - const materialsnapshot_t* msB, - boolean isTwosidedMiddle) +static boolean doRenderHEdge(HEdge* hedge, const pvec3f_t normal, + float alpha, float lightLevel, float lightLevelDL, float lightLevelDR, + const float* lightColor, uint lightListIdx, uint shadowListIdx, + walldivs_t* leftWallDivs, walldivs_t* rightWallDivs, + boolean skyMask, boolean addFakeRadio, vec3d_t texTL, vec3d_t texBR, + float const texOffset[2], float const texScale[2], + blendmode_t blendMode, const float* color, const float* color2, + biassurface_t* bsuf, uint elmIdx /*tmp*/, + const materialsnapshot_t* msA, float inter, const materialsnapshot_t* msB, + boolean isTwosidedMiddle) { rendworldpoly_params_t params; - SideDef* side = (hedge->lineDef? HEDGE_SIDEDEF(hedge) : NULL); - rvertex_t* rvertices; + SideDef* side = (hedge->lineDef? HEDGE_SIDEDEF(hedge) : NULL); + rvertex_t* rvertices; // Init the params. memset(¶ms, 0, sizeof(params)); params.flags = RPF_DEFAULT | (skyMask? RPF_SKYMASK : 0); params.isWall = true; - params.segLength = &hedge->length; + params.wall.segLength = &hedge->length; params.forceOpaque = (alpha < 0? true : false); params.alpha = (alpha < 0? 1 : alpha); params.mapObject = hedge; @@ -1274,19 +1283,23 @@ static boolean doRenderHEdge(HEdge* hedge, params.surfaceLightLevelDR = lightLevelDR; params.sectorLightColor = lightColor; params.surfaceColor = color; - params.surfaceColor2 = color2; + params.wall.surfaceColor2 = color2; params.glowing = msA? msA->glowing : 0; params.blendMode = blendMode; params.texOffset = texOffset; params.texScale = texScale; params.lightListIdx = lightListIdx; params.shadowListIdx = shadowListIdx; + params.wall.left.firstDiv = WallDivNode_Next(WallDivs_First(leftWallDivs)); // Step over first node. + params.wall.left.divCount = WallDivs_Size(leftWallDivs)-2; + params.wall.right.firstDiv = WallDivNode_Prev(WallDivs_Last(rightWallDivs)); // Step over last node. + params.wall.right.divCount = WallDivs_Size(rightWallDivs)-2; // Allocate enough vertices for the divisions too. - if(leftWallDivs->num > 2 || rightWallDivs->num > 2) + if(WallDivs_Size(leftWallDivs) > 2 || WallDivs_Size(rightWallDivs) > 2) { // Use two fans. - rvertices = R_AllocRendVertices(1 + leftWallDivs->num + 1 + rightWallDivs->num); + rvertices = R_AllocRendVertices(1 + WallDivs_Size(leftWallDivs) + 1 + WallDivs_Size(rightWallDivs)); } else { @@ -1297,22 +1310,22 @@ static boolean doRenderHEdge(HEdge* hedge, // Vertex coords. // Bottom Left. V2f_Copyd(rvertices[0].pos, hedge->HE_v1origin); - rvertices[0].pos[VZ] = (float)leftWallDivs->nodes[0].height; + rvertices[0].pos[VZ] = (float)WallDivNode_Height(WallDivs_First(leftWallDivs)); // Top Left. V2f_Copyd(rvertices[1].pos, hedge->HE_v1origin); - rvertices[1].pos[VZ] = (float)leftWallDivs->nodes[leftWallDivs->num-1].height; + rvertices[1].pos[VZ] = (float)WallDivNode_Height(WallDivs_Last(leftWallDivs)); // Bottom Right. V2f_Copyd(rvertices[2].pos, hedge->HE_v2origin); - rvertices[2].pos[VZ] = (float)rightWallDivs->nodes[0].height; + rvertices[2].pos[VZ] = (float)WallDivNode_Height(WallDivs_First(rightWallDivs)); // Top Right. V2f_Copyd(rvertices[3].pos, hedge->HE_v2origin); - rvertices[3].pos[VZ] = (float)rightWallDivs->nodes[rightWallDivs->num-1].height; + rvertices[3].pos[VZ] = (float)WallDivNode_Height(WallDivs_Last(rightWallDivs)); // Draw this hedge. - if(renderWorldPoly(rvertices, 4, leftWallDivs, rightWallDivs, ¶ms, msA, inter, msB)) + if(renderWorldPoly(rvertices, 4, ¶ms, msA, inter, msB)) { // Drawn poly was opaque. // Render Fakeradio polys for this hedge? if(!(params.flags & RPF_SKYMASK) && addFakeRadio) @@ -1328,6 +1341,10 @@ static boolean doRenderHEdge(HEdge* hedge, radioParams.segOffset = &hedge->offset; radioParams.segLength = &hedge->length; radioParams.frontSec = hedge->sector; + radioParams.wall.left.firstDiv = params.wall.left.firstDiv; + radioParams.wall.left.divCount = params.wall.left.divCount; + radioParams.wall.right.firstDiv = params.wall.right.firstDiv; + radioParams.wall.right.divCount = params.wall.right.divCount; if(!isTwosidedMiddle && !(hedge->twin && !HEDGE_SIDEDEF(hedge->twin))) { @@ -1343,19 +1360,19 @@ static boolean doRenderHEdge(HEdge* hedge, // Bottom Left. V2f_Copyd(rvertices[0].pos, hedge->HE_v1origin); - rvertices[0].pos[VZ] = (float)leftWallDivs->nodes[0].height; + rvertices[0].pos[VZ] = (float)WallDivNode_Height(WallDivs_First(leftWallDivs)); // Top Left. V2f_Copyd(rvertices[1].pos, hedge->HE_v1origin); - rvertices[1].pos[VZ] = (float)leftWallDivs->nodes[leftWallDivs->num-1].height; + rvertices[1].pos[VZ] = (float)WallDivNode_Height(WallDivs_Last(leftWallDivs)); // Bottom Right. V2f_Copyd(rvertices[2].pos, hedge->HE_v2origin); - rvertices[2].pos[VZ] = (float)rightWallDivs->nodes[0].height; + rvertices[2].pos[VZ] = (float)WallDivNode_Height(WallDivs_First(rightWallDivs)); // Top Right. V2f_Copyd(rvertices[3].pos, hedge->HE_v2origin); - rvertices[3].pos[VZ] = (float)rightWallDivs->nodes[rightWallDivs->num-1].height; + rvertices[3].pos[VZ] = (float)WallDivNode_Height(WallDivs_Last(rightWallDivs)); // kludge end. @@ -1372,7 +1389,7 @@ static boolean doRenderHEdge(HEdge* hedge, { // Shadows are black. radioParams.shadowRGB[CR] = radioParams.shadowRGB[CG] = radioParams.shadowRGB[CB] = 0; - Rend_RadioSegSection(rvertices, leftWallDivs, rightWallDivs, &radioParams); + Rend_RadioSegSection(rvertices, &radioParams); } } } @@ -1498,7 +1515,7 @@ static void renderPlane(BspLeaf* bspLeaf, planetype_t type, coord_t height, } } - renderWorldPoly(rvertices, numVertices, NULL, NULL, ¶ms, msA, inter, blended? msB : NULL); + renderWorldPoly(rvertices, numVertices, ¶ms, msA, inter, blended? msB : NULL); R_FreeRendVertices(rvertices); } @@ -1558,7 +1575,7 @@ static void Rend_RenderPlane(planetype_t type, coord_t height, static boolean rendHEdgeSection(HEdge* hedge, SideDefSection section, int flags, float lightLevel, const float* lightColor, - const walldivs_t* leftWallDivs, const walldivs_t* rightWallDivs, + walldivs_t* leftWallDivs, walldivs_t* rightWallDivs, float const matOffset[2]) { SideDef* frontSide = HEDGE_SIDEDEF(hedge); @@ -1567,7 +1584,8 @@ static boolean rendHEdgeSection(HEdge* hedge, SideDefSection section, float alpha; if(!Surface_IsDrawable(surface)) return false; - if(leftWallDivs->nodes[0].height >= rightWallDivs->nodes[rightWallDivs->num-1].height) return true; + if(WallDivNode_Height(WallDivs_First(leftWallDivs)) >= + WallDivNode_Height(WallDivs_Last(rightWallDivs))) return true; alpha = (section == SS_MIDDLE? surface->rgba[3] : 1.0f); @@ -1583,8 +1601,8 @@ static boolean rendHEdgeSection(HEdge* hedge, SideDefSection section, * an opaque waterfall). */ - if(viewData->current.origin[VZ] > leftWallDivs->nodes[0].height && - viewData->current.origin[VZ] < rightWallDivs->nodes[rightWallDivs->num-1].height) + if(viewData->current.origin[VZ] > WallDivNode_Height(WallDivs_First(leftWallDivs)) && + viewData->current.origin[VZ] < WallDivNode_Height(WallDivs_Last(rightWallDivs))) { LineDef* lineDef = hedge->lineDef; vec2d_t result; @@ -1627,10 +1645,10 @@ static boolean rendHEdgeSection(HEdge* hedge, SideDefSection section, texScale[1] = ((surface->flags & DDSUF_MATERIAL_FLIPV)? -1 : 1); V2d_Copy(texTL, hedge->HE_v1origin); - texTL[VZ] = leftWallDivs->nodes[leftWallDivs->num-1].height; + texTL[VZ] = WallDivNode_Height(WallDivs_Last(leftWallDivs)); V2d_Copy(texBR, hedge->HE_v2origin); - texBR[VZ] = rightWallDivs->nodes[0].height; + texBR[VZ] = WallDivNode_Height(WallDivs_First(rightWallDivs)); // Determine which Material to use. if(devRendSkyMode && HEDGE_BACK_SECTOR(hedge) && @@ -1750,13 +1768,10 @@ static boolean rendHEdgeSection(HEdge* hedge, SideDefSection section, opaque = doRenderHEdge(hedge, surface->normal, ((flags & RHF_FORCE_OPAQUE)? -1 : alpha), - lightLevel, - deltaL, deltaR, - lightColor, + lightLevel, deltaL, deltaR, lightColor, lightListIdx, shadowListIdx, leftWallDivs, rightWallDivs, - !!(rpFlags & RPF_SKYMASK), - !!(flags & RHF_ADD_RADIO), + !!(rpFlags & RPF_SKYMASK), !!(flags & RHF_ADD_RADIO), texTL, texBR, matOffset, texScale, blendMode, color, color2, hedge->bsuf[section], (uint) section, @@ -1896,8 +1911,8 @@ static boolean Rend_RenderHEdgeTwosided(HEdge* hedge) xtop += suf->visOffset[VY]; // Can we make this a solid segment? - if(!(rightWallDivs.nodes[rightWallDivs.num-1].height >= xtop && - leftWallDivs.nodes[0].height <= xbottom)) + if(!(WallDivNode_Height(WallDivs_Last(&rightWallDivs)) >= xtop && + WallDivNode_Height(WallDivs_First(&leftWallDivs)) <= xbottom)) solidSeg = false; } } diff --git a/doomsday/engine/portable/src/rend_shadow.c b/doomsday/engine/portable/src/rend_shadow.c index bb32cc5d97..5f9a5f82f1 100644 --- a/doomsday/engine/portable/src/rend_shadow.c +++ b/doomsday/engine/portable/src/rend_shadow.c @@ -228,7 +228,7 @@ int RIT_RenderShadowProjectionIterator(const shadowprojection_t* sp, void* param rtexcoords[3].st[0] = rtexcoords[2].st[0] = sp->s[1]; rtexcoords[2].st[1] = rtexcoords[0].st[1] = sp->t[1]; - if(p->leftWallDivs->num > 2 || p->rightWallDivs->num > 2) + if(p->wall.left.divCount || p->wall.right.divCount) { // We need to subdivide the projection quad. float bL, tL, bR, tR; @@ -251,9 +251,9 @@ int RIT_RenderShadowProjectionIterator(const shadowprojection_t* sp, void* param bR = p->rvertices[2].pos[VZ]; tR = p->rvertices[3].pos[VZ]; - R_DivVerts(rvertices, origVerts, p->leftWallDivs, p->rightWallDivs); - R_DivTexCoords(rtexcoords, origTexCoords, p->leftWallDivs, p->rightWallDivs, bL, tL, bR, tR); - R_DivVertColors(rcolors, origColors, p->leftWallDivs, p->rightWallDivs, bL, tL, bR, tR); + R_DivVerts(rvertices, origVerts, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount); + R_DivTexCoords(rtexcoords, origTexCoords, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); + R_DivVertColors(rcolors, origColors, p->wall.left.firstDiv, p->wall.left.divCount, p->wall.right.firstDiv, p->wall.right.divCount, bL, tL, bR, tR); } else { @@ -280,13 +280,13 @@ int RIT_RenderShadowProjectionIterator(const shadowprojection_t* sp, void* param memcpy(rvertices, p->rvertices, sizeof(rvertex_t) * p->numVertices); } - if(p->isWall && (p->leftWallDivs->num > 2 || p->rightWallDivs->num > 2)) + if(p->isWall && (p->wall.left.divCount || p->wall.right.divCount)) { RL_AddPolyWithCoords(PT_FAN, RPF_DEFAULT|RPF_SHADOW, - 1 + p->rightWallDivs->num, rvertices + 1 + p->leftWallDivs->num, - rcolors + 1 + p->leftWallDivs->num, rtexcoords + 1 + p->leftWallDivs->num, NULL); + 3 + p->wall.right.divCount, rvertices + 3 + p->wall.left.divCount, + rcolors + 3 + p->wall.left.divCount, rtexcoords + 3 + p->wall.left.divCount, NULL); RL_AddPolyWithCoords(PT_FAN, RPF_DEFAULT|RPF_SHADOW, - 1 + p->leftWallDivs->num, rvertices, rcolors, rtexcoords, NULL); + 3 + p->wall.left.divCount, rvertices, rcolors, rtexcoords, NULL); } else {