From 2d50f535ff666a9cb0a0d3fe97c31f07e5a6f9a8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 31 May 2018 22:14:24 +0200 Subject: [PATCH] - fixed and simplified the vertex counter for wall polygons. This is now allowed to overestimate the number of vertices to reduce computation time for a rarely occuring special case that was eating most of the time and was causing errors with some walls. --- src/hwrenderer/scene/hw_drawstructs.h | 5 +- src/hwrenderer/scene/hw_walls.cpp | 1 + src/hwrenderer/scene/hw_walls_vertex.cpp | 111 +++++++++++++---------- 3 files changed, 68 insertions(+), 49 deletions(-) diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 5758cf0b8c..8dcc4632aa 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -250,12 +250,15 @@ public: void ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &normal); void ProcessDecals(HWDrawInfo *di); - void CreateVertices(FFlatVertex *&ptr, bool nosplit); + int CreateVertices(FFlatVertex *&ptr, bool nosplit); void SplitLeftEdge (FFlatVertex *&ptr); void SplitRightEdge(FFlatVertex *&ptr); void SplitUpperEdge(FFlatVertex *&ptr); void SplitLowerEdge(FFlatVertex *&ptr); + void CountLeftEdge (unsigned &ptr); + void CountRightEdge(unsigned &ptr); + int CountVertices(); public: diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index 1ed41122a3..b70c4ebf83 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -1522,6 +1522,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ } v1 = seg->v1; v2 = seg->v2; + flags |= GLWF_NOSPLITLOWER | GLWF_NOSPLITLOWER; // seg-splitting not needed for single segs. } diff --git a/src/hwrenderer/scene/hw_walls_vertex.cpp b/src/hwrenderer/scene/hw_walls_vertex.cpp index 6d74a23697..b0042baffa 100644 --- a/src/hwrenderer/scene/hw_walls_vertex.cpp +++ b/src/hwrenderer/scene/hw_walls_vertex.cpp @@ -170,8 +170,9 @@ void GLWall::SplitRightEdge(FFlatVertex *&ptr) // //========================================================================== -void GLWall::CreateVertices(FFlatVertex *&ptr, bool split) +int GLWall::CreateVertices(FFlatVertex *&ptr, bool split) { + auto oo = ptr; ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v); ptr++; if (split && glseg.fracleft == 0) SplitLeftEdge(ptr); @@ -184,6 +185,58 @@ void GLWall::CreateVertices(FFlatVertex *&ptr, bool split) ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v); ptr++; if (split && !(flags & GLWF_NOSPLITLOWER) && seg->sidedef->numsegs > 1) SplitLowerEdge(ptr); + return int(ptr - oo); +} + + +//========================================================================== +// +// Split left edge of wall +// +//========================================================================== + +void GLWall::CountLeftEdge(unsigned &ptr) +{ + if (vertexes[0] == NULL) return; + + vertex_t * vi = vertexes[0]; + + if (vi->numheights) + { + int i = 0; + + while (inumheights && vi->heightlist[i] <= zbottom[0]) i++; + while (inumheights && vi->heightlist[i] < ztop[0]) + { + ptr++; + i++; + } + } +} + +//========================================================================== +// +// Split right edge of wall +// +//========================================================================== + +void GLWall::CountRightEdge(unsigned &ptr) +{ + if (vertexes[1] == NULL) return; + + vertex_t * vi = vertexes[1]; + + if (vi->numheights) + { + int i = vi->numheights - 1; + + while (i>0 && vi->heightlist[i] >= ztop[1]) i--; + while (i>0 && vi->heightlist[i] > zbottom[1]) + { + ptr++; + i--; + } + } } //========================================================================== @@ -194,49 +247,13 @@ void GLWall::CreateVertices(FFlatVertex *&ptr, bool split) int GLWall::CountVertices() { - int cnt = 4; - vertex_t * vi = vertexes[0]; - if (glseg.fracleft == 0 && vi != nullptr && vi->numheights) - { - int i = 0; - - while (inumheights && vi->heightlist[i] <= zbottom[0]) i++; - while (inumheights && vi->heightlist[i] < ztop[0]) - { - i++; - cnt++; - } - } - auto sidedef = seg->sidedef; - constexpr auto NOSPLIT_LOWER_UPPER = GLWF_NOSPLITLOWER | GLWF_NOSPLITUPPER; - const bool canSplit = (flags & NOSPLIT_LOWER_UPPER) != NOSPLIT_LOWER_UPPER; - if (canSplit && sidedef->numsegs > 1) - { - int cnt2 = 0; - for (int i = sidedef->numsegs - 2; i >= 0; i--) - { - float sidefrac = sidedef->segs[i]->sidefrac; - if (sidefrac >= glseg.fracright) continue; - if (sidefrac <= glseg.fracleft) break; - cnt2++; - } - const bool splitBoth = !(flags & NOSPLIT_LOWER_UPPER); - if (splitBoth) cnt2 <<= 1; - cnt += cnt2; - } - vi = vertexes[1]; - if (glseg.fracright == 1 && vi != nullptr && vi->numheights) - { - int i = 0; - - while (inumheights && vi->heightlist[i] <= zbottom[1]) i++; - while (inumheights && vi->heightlist[i] < ztop[1]) - { - i++; - cnt++; - } - } - return cnt; + unsigned ptr = 4; + if (glseg.fracleft == 0) CountLeftEdge(ptr); + if (glseg.fracright == 1) CountRightEdge(ptr); + // This may allocate a few vertices too many in case of a split linedef but this is a rare case that isn't worth the required overhead for a precise calculation. + if (!(flags & GLWF_NOSPLITUPPER)) ptr += seg->sidedef->numsegs - 1; + if (!(flags & GLWF_NOSPLITLOWER)) ptr += seg->sidedef->numsegs - 1; + return (int)ptr; } //========================================================================== @@ -250,11 +267,9 @@ void GLWall::MakeVertices(HWDrawInfo *di, bool nosplit) if (vertcount == 0) { bool split = (gl_seamless && !nosplit && seg->sidedef != nullptr && !(seg->sidedef->Flags & WALLF_POLYOBJ) && !(flags & GLWF_NOSPLIT)); - vertcount = split ? CountVertices() : 4; - - auto ret = di->AllocVertices(vertcount); + auto ret = di->AllocVertices(split ? CountVertices() : 4); vertindex = ret.second; - CreateVertices(ret.first, split); + vertcount = CreateVertices(ret.first, split); } }