- added wall edge splitting for gl_seamless.

This commit is contained in:
Christoph Oelckers 2021-12-28 19:33:27 +01:00
parent f7e7476010
commit b1d8f92ded
7 changed files with 226 additions and 48 deletions

View file

@ -1062,6 +1062,7 @@ set (PCH_SOURCES
core/rendering/hw_vertexmap.cpp
core/rendering/scene/hw_clipper.cpp
core/rendering/scene/hw_walls.cpp
core/rendering/scene/hw_walls_vertex.cpp
core/rendering/scene/hw_flats.cpp
core/rendering/scene/hw_sprites.cpp
core/rendering/scene/hw_drawlistadd.cpp

View file

@ -98,8 +98,8 @@ static void ReadSectorV7(FileReader& fr, sectortype& sect)
{
sect.wallptr = fr.ReadInt16();
sect.wallnum = fr.ReadInt16();
sect.setceilingz(fr.ReadInt32());
sect.setfloorz(fr.ReadInt32());
sect.setceilingz(fr.ReadInt32(), true);
sect.setfloorz(fr.ReadInt32(), true);
sect.ceilingstat = ESectorFlags::FromInt(fr.ReadUInt16());
sect.floorstat = ESectorFlags::FromInt(fr.ReadUInt16());
sect.ceilingpicnum = fr.ReadUInt16();
@ -129,8 +129,8 @@ static void ReadSectorV6(FileReader& fr, sectortype& sect)
sect.floorpicnum = fr.ReadUInt16();
sect.ceilingheinum = clamp(fr.ReadInt16() << 5, -32768, 32767);
sect.floorheinum = clamp(fr.ReadInt16() << 5, -32768, 32767);
sect.setceilingz(fr.ReadInt32());
sect.setfloorz(fr.ReadInt32());
sect.setceilingz(fr.ReadInt32(), true);
sect.setfloorz(fr.ReadInt32(), true);
sect.ceilingshade = fr.ReadInt8();
sect.floorshade = fr.ReadInt8();
sect.ceilingxpan_ = fr.ReadUInt8();
@ -156,8 +156,8 @@ static void ReadSectorV5(FileReader& fr, sectortype& sect)
sect.floorpicnum = fr.ReadUInt16();
sect.ceilingheinum = clamp(fr.ReadInt16() << 5, -32768, 32767);
sect.floorheinum = clamp(fr.ReadInt16() << 5, -32768, 32767);
sect.setceilingz(fr.ReadInt32());
sect.setfloorz(fr.ReadInt32());
sect.setceilingz(fr.ReadInt32(), true);
sect.setfloorz(fr.ReadInt32(), true);
sect.ceilingshade = fr.ReadInt8();
sect.floorshade = fr.ReadInt8();
sect.ceilingxpan_ = fr.ReadUInt8();

View file

@ -33,13 +33,12 @@
**
*/
#include "basics.h"
#include "maptypes.h"
#include "memarena.h"
#include "gamefuncs.h"
#include "hw_vertexmap.h"
extern FMemArena sectionArena; // allocate from the same arena as the section as the data here has the same lifetime.
extern FMemArena sectionArena; // allocate from the same arena as the sections as the data here has the same lifetime.
TArray<int> vertexMap; // maps walls to the vertex data.
TArray<vertex_t> vertices;
@ -59,6 +58,7 @@ void CreateVertexMap()
verticespersector.Resize(sector.Size());
for (auto& c : countpersector) c = 0;
for (auto& c : vertexMap) c = -1;
for (unsigned i = 0; i < wall.Size(); i++)
{
if (processed[i]) continue;
@ -78,7 +78,7 @@ void CreateVertexMap()
}
});
vertices.Reserve(1);
unsigned index = vertices.Reserve(1);
auto newvert = &vertices.Last();
newvert->masterwall = walls[0];
@ -87,6 +87,11 @@ void CreateVertexMap()
newvert->dirty = true;
newvert->numheights = 0;
for (auto w : walls)
{
vertexMap[w] = index;
}
// allocate all data within this struct from the arena to simplify memory management.
auto sect = (int*)sectionArena.Alloc(sectors.Size() * sizeof(int));
newvert->sectors.Set(sect, sectors.Size());

View file

@ -223,7 +223,11 @@ public:
int CreateVertices(FFlatVertex *&ptr, bool nosplit);
//int CountVertices();
int CountVertices();
void SplitLeftEdge(FFlatVertex*& ptr);
void SplitRightEdge(FFlatVertex*& ptr);
void CountLeftEdge(unsigned& ptr);
void CountRightEdge(unsigned& ptr);
void RenderWall(HWDrawInfo *di, FRenderState &state, int textured);
void RenderFogBoundary(HWDrawInfo *di, FRenderState &state);

View file

@ -133,42 +133,6 @@ static int IsOnWall(tspritetype* tspr, int height)
return closest == nullptr? -1 : dist;
}
//==========================================================================
//
// Create vertices for one wall
//
//==========================================================================
int HWWall::CreateVertices(FFlatVertex*& ptr, bool split)
{
auto oo = ptr;
ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v);
ptr++;
ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v);
ptr++;
ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v);
ptr++;
ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v);
ptr++;
return int(ptr - oo);
}
//==========================================================================
//
// build the vertices for this wall
//
//==========================================================================
void HWWall::MakeVertices(HWDrawInfo* di, bool nosplit)
{
if (vertcount == 0)
{
auto ret = screen->mVertexData->AllocVertices(4);
vertindex = ret.second;
vertcount = CreateVertices(ret.first, false);
}
}
//==========================================================================
//
// General purpose wall rendering function

View file

@ -0,0 +1,204 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2006-2022 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
#include "basics.h"
#include "maptypes.h"
#include "memarena.h"
#include "gamefuncs.h"
#include "v_video.h"
#include "flatvertices.h"
#include "hw_vertexmap.h"
#include "hw_drawstructs.h"
EXTERN_CVAR(Bool, gl_seamless)
//==========================================================================
//
// Split left edge of wall
//
//==========================================================================
void HWWall::SplitLeftEdge(FFlatVertex *&ptr)
{
if (seg == nullptr) return;
vertex_t* vi = &vertices[vertexMap[wallnum(seg)]];
if (vi->numheights)
{
int i = 0;
float polyh1 = ztop[0] - zbottom[0];
float factv1 = polyh1 ? (tcs[UPLFT].v - tcs[LOLFT].v) / polyh1 : 0;
float factu1 = polyh1 ? (tcs[UPLFT].u - tcs[LOLFT].u) / polyh1 : 0;
while (i<vi->numheights && vi->heightlist[i] <= zbottom[0]) i++;
while (i<vi->numheights && vi->heightlist[i] < ztop[0])
{
ptr->x = glseg.x1;
ptr->y = glseg.y1;
ptr->z = vi->heightlist[i];
ptr->u = factu1*(vi->heightlist[i] - ztop[0]) + tcs[UPLFT].u;
ptr->v = factv1*(vi->heightlist[i] - ztop[0]) + tcs[UPLFT].v;
ptr++;
i++;
}
}
}
//==========================================================================
//
// Split right edge of wall
//
//==========================================================================
void HWWall::SplitRightEdge(FFlatVertex *&ptr)
{
if (seg == nullptr) return;
vertex_t* vi = &vertices[vertexMap[seg->point2]];
if (vi->numheights)
{
int i = vi->numheights - 1;
float polyh2 = ztop[1] - zbottom[1];
float factv2 = polyh2 ? (tcs[UPRGT].v - tcs[LORGT].v) / polyh2 : 0;
float factu2 = polyh2 ? (tcs[UPRGT].u - tcs[LORGT].u) / polyh2 : 0;
while (i>0 && vi->heightlist[i] >= ztop[1]) i--;
while (i>0 && vi->heightlist[i] > zbottom[1])
{
ptr->x = glseg.x2;
ptr->y = glseg.y2;
ptr->z = vi->heightlist[i];
ptr->u = factu2*(vi->heightlist[i] - ztop[1]) + tcs[UPRGT].u;
ptr->v = factv2*(vi->heightlist[i] - ztop[1]) + tcs[UPRGT].v;
ptr++;
i--;
}
}
}
//==========================================================================
//
// Create vertices for one wall
//
//==========================================================================
int HWWall::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);
ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v);
ptr++;
ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v);
ptr++;
if (split && glseg.fracright == 1) SplitRightEdge(ptr);
ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v);
ptr++;
return int(ptr - oo);
}
//==========================================================================
//
// Split left edge of wall
//
//==========================================================================
void HWWall::CountLeftEdge(unsigned &ptr)
{
vertex_t* vi = &vertices[vertexMap[wallnum(seg)]];
if (vi->numheights)
{
int i = 0;
while (i<vi->numheights && vi->heightlist[i] <= zbottom[0]) i++;
while (i<vi->numheights && vi->heightlist[i] < ztop[0])
{
ptr++;
i++;
}
}
}
//==========================================================================
//
// Split right edge of wall
//
//==========================================================================
void HWWall::CountRightEdge(unsigned &ptr)
{
vertex_t* vi = &vertices[vertexMap[seg->point2]];
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--;
}
}
}
//==========================================================================
//
//
//
//==========================================================================
int HWWall::CountVertices()
{
unsigned ptr = 4;
if (seg)
{
if (glseg.fracleft == 0) CountLeftEdge(ptr);
if (glseg.fracright == 1) CountRightEdge(ptr);
}
return (int)ptr;
}
//==========================================================================
//
// build the vertices for this wall
//
//==========================================================================
void HWWall::MakeVertices(HWDrawInfo *di, bool nosplit)
{
if (vertcount == 0)
{
bool split = (gl_seamless && !nosplit && seg != nullptr);
auto ret = screen->mVertexData->AllocVertices(split ? CountVertices() : 4);
vertindex = ret.second;
vertcount = CreateVertices(ret.first, split);
}
}

View file

@ -253,8 +253,8 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect
}
pSector->wallptr = LittleShort(load.wallptr);
pSector->wallnum = LittleShort(load.wallnum);
pSector->setceilingz(LittleLong(load.ceilingz));
pSector->setfloorz(LittleLong(load.floorz));
pSector->setceilingz(LittleLong(load.ceilingz), true);
pSector->setfloorz(LittleLong(load.floorz), true);
pSector->ceilingstat = ESectorFlags::FromInt(LittleShort(load.ceilingstat));
pSector->floorstat = ESectorFlags::FromInt(LittleShort(load.floorstat));
pSector->ceilingpicnum = LittleShort(load.ceilingpicnum);