diff --git a/src/hwrenderer/data/flatvertices.cpp b/src/hwrenderer/data/flatvertices.cpp index 20e139c586..c19169db36 100644 --- a/src/hwrenderer/data/flatvertices.cpp +++ b/src/hwrenderer/data/flatvertices.cpp @@ -35,6 +35,13 @@ #include "hwrenderer/data/buffers.h" #include "hwrenderer/scene/hw_renderstate.h" +namespace VertexBuilder +{ + TArray BuildVertices(); +} + +using VertexContainers = TArray; + //========================================================================== // @@ -158,54 +165,22 @@ static F3DFloor *Find3DFloor(sector_t *target, sector_t *model) // //========================================================================== -int FFlatVertexBuffer::CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FFlatVertexBuffer::FIndexGenerationInfo &gen) +int FFlatVertexBuffer::CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, VertexContainer &verts) { - if (sub->numlines < 3) return -1; - - int idx = ibo_data.Reserve((sub->numlines - 2) * 3); - int idxc = idx; - int firstndx = gen.GetIndex(sub->firstline[0].v1); - int secondndx = gen.GetIndex(sub->firstline[1].v1); - for (unsigned int k = 2; knumlines; k++) - { - auto ndx = gen.GetIndex(sub->firstline[k].v1); - - ibo_data[idx++] = vi + firstndx; - ibo_data[idx++] = vi + secondndx; - ibo_data[idx++] = vi + ndx; - secondndx = ndx; - } - return idx; -} - -//========================================================================== -// -// Creates the vertices for one plane in one subsector -// -//========================================================================== - -int FFlatVertexBuffer::CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FFlatVertexBuffer::FIndexGenerationInfo &gen) -{ - int rt = ibo_data.Size(); - int vi = vbo_shadowdata.Reserve(gen.vertices.Size()); + int vi = vbo_shadowdata.Reserve(verts.vertices.Size()); float diff; // Create the actual vertices. if (sec->transdoor && floor) diff = -1.f; else diff = 0.f; - for (unsigned i = 0; i < gen.vertices.Size(); i++) + for (unsigned i = 0; i < verts.vertices.Size(); i++) { - vbo_shadowdata[vi + i].SetFlatVertex(gen.vertices[i], plane); + vbo_shadowdata[vi + i].SetFlatVertex(verts.vertices[i].vertex, plane); vbo_shadowdata[vi + i].z += diff; } - - // Create the indices for the subsectors - for (int j = 0; jsubsectorcount; j++) - { - subsector_t *sub = sec->subsectors[j]; - CreateIndexedSubsectorVertices(sub, plane, floor, vi, gen); - } - sec->ibocount = ibo_data.Size() - rt; + + int rt = ibo_data.size(); + ibo_data.Append(verts.indices); return rt; } @@ -215,19 +190,20 @@ int FFlatVertexBuffer::CreateIndexedSectorVertices(sector_t *sec, const secplane // //========================================================================== -int FFlatVertexBuffer::CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray &gen) +int FFlatVertexBuffer::CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, VertexContainers &verts) { sec->vboindex[h] = vbo_shadowdata.Size(); // First calculate the vertices for the sector itself sec->vboheight[h] = sec->GetPlaneTexZ(h); - sec->iboindex[h] = CreateIndexedSectorVertices(sec, plane, floor, gen[sec->Index()]); + sec->ibocount = verts.indices.Size(); + sec->iboindex[h] = CreateIndexedSectorVertices(sec, plane, floor, verts[sec->Index()]); // Next are all sectors using this one as heightsec TArray &fakes = sec->e->FakeFloor.Sectors; for (unsigned g = 0; g < fakes.Size(); g++) { sector_t *fsec = fakes[g]; - fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]); + fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fsec, plane, false, verts[fsec->Index()]); } // and finally all attached 3D floors @@ -244,7 +220,7 @@ int FFlatVertexBuffer::CreateIndexedVertices(int h, sector_t *sec, const secplan if (dotop || dobottom) { - auto ndx = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]); + auto ndx = CreateIndexedSectorVertices(fsec, plane, false, verts[fsec->Index()]); if (dotop) ffloor->top.vindex = ndx; if (dobottom) ffloor->bottom.vindex = ndx; } @@ -263,26 +239,13 @@ int FFlatVertexBuffer::CreateIndexedVertices(int h, sector_t *sec, const secplan void FFlatVertexBuffer::CreateIndexedFlatVertices() { - TArray gen; - gen.Resize(level.sectors.Size()); - // This must be generated up front so that the following code knows how many vertices a sector contains. - for (unsigned i = 0; i < level.sectors.Size(); i++) - { - for (int j = 0; j < level.sectors[i].subsectorcount; j++) - { - auto sub = level.sectors[i].subsectors[j]; - for (unsigned k = 0; k < sub->numlines; k++) - { - auto vert = sub->firstline[k].v1; - gen[i].AddVertex(vert); - } - } - } + auto verts = VertexBuilder::BuildVertices(); + for (int h = sector_t::floor; h <= sector_t::ceiling; h++) { for (auto &sec : level.sectors) { - CreateIndexedVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor, gen); + CreateIndexedVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor, verts); } } diff --git a/src/hwrenderer/data/flatvertices.h b/src/hwrenderer/data/flatvertices.h index c554483792..13a8d31307 100644 --- a/src/hwrenderer/data/flatvertices.h +++ b/src/hwrenderer/data/flatvertices.h @@ -62,31 +62,6 @@ class FFlatVertexBuffer static const unsigned int BUFFER_SIZE = 2000000; static const unsigned int BUFFER_SIZE_TO_USE = 1999500; - - // Temporary data for creating an indexed buffer - struct FIndexGenerationInfo - { - TArray vertices; - TMap vertexmap; - - uint32_t AddVertex(vertex_t *vert) - { - auto check = vertexmap.CheckKey(vert); - if (check != nullptr) return *check; - auto index = vertices.Push(vert); - vertexmap[vert] = index; - return index; - } - - uint32_t GetIndex(vertex_t *vert) - { - auto check = vertexmap.CheckKey(vert); - if (check != nullptr) return *check; - return ~0; - } - }; - - public: enum { @@ -140,9 +115,9 @@ public: } private: - int CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FIndexGenerationInfo &gen); - int CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FIndexGenerationInfo &gen); - int CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray &gen); + int CreateIndexedSectionVertices(subsector_t *sub, const secplane_t &plane, int floor, VertexContainer &cont); + int CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, VertexContainer &cont); + int CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, VertexContainers &cont); void CreateIndexedFlatVertices(); void UpdatePlaneVertices(sector_t *sec, int plane); @@ -154,4 +129,4 @@ public: }; -#endif \ No newline at end of file +#endif diff --git a/src/hwrenderer/data/hw_sections.cpp b/src/hwrenderer/data/hw_sections.cpp index 2c698386c2..31c1986e6a 100644 --- a/src/hwrenderer/data/hw_sections.cpp +++ b/src/hwrenderer/data/hw_sections.cpp @@ -40,7 +40,6 @@ using DoublePoint = std::pair; template<> struct THashTraits { - // Use all bits when hashing doubles instead of converting them to ints. hash_t Hash(const DoublePoint &key) { return (hash_t)SuperFastHash((const char*)(const void*)&key, sizeof(key)); @@ -48,6 +47,15 @@ template<> struct THashTraits int Compare(const DoublePoint &left, const DoublePoint &right) { return left != right; } }; +template<> struct THashTraits +{ + hash_t Hash(const FSectionVertex &key) + { + return (int)(((intptr_t)key.vertex) >> 4) ^ (key.qualifier << 16); + } + int Compare(const FSectionVertex &left, const FSectionVertex &right) { return left.vertex != right.vertex && left.qualifier != right.qualifier; } +}; + struct WorkSectionLine { @@ -613,112 +621,6 @@ public: } - //============================================================================= - // - // - // - //============================================================================= - - // Temporary data for creating an indexed buffer - struct VertexIndexGenerationInfo - { - TArray vertices; - TMap vertexmap; - - TArray indices; - - uint32_t AddVertex(vertex_t *vert) - { - auto check = vertexmap.CheckKey(vert); - if (check != nullptr) return *check; - auto index = vertices.Push(vert); - vertexmap[vert] = index; - return index; - } - - uint32_t GetIndex(vertex_t *vert) - { - auto check = vertexmap.CheckKey(vert); - if (check != nullptr) return *check; - return ~0u; - } - - uint32_t AddIndexForVertex(vertex_t *vert) - { - return indices.Push(GetIndex(vert)); - } - - uint32_t AddIndex(uint32_t indx) - { - return indices.Push(indx); - } - }; - - //============================================================================= - // - // - // - //============================================================================= - - void CreateIndexedSubsectorVertices(subsector_t *sub, VertexIndexGenerationInfo &gen) - { - if (sub->numlines < 3) return; - - uint32_t startindex = gen.indices.Size(); - - if ((sub->flags & SSECF_HOLE) && sub->numlines > 3) - { - // Hole filling "subsectors" are not necessarily convex so they require real triangulation. - // These things are extremely rare so performance is secondary here. - - using Point = std::pair; - std::vector> polygon; - std::vector *curPoly; - - for (unsigned i = 0; i < sub->numlines; i++) - { - polygon.resize(1); - curPoly = &polygon.back(); - curPoly->push_back({ sub->firstline[i].v1->fX(), sub->firstline[i].v1->fY() }); - } - auto indices = mapbox::earcut(polygon); - for (auto vti : indices) - { - gen.AddIndexForVertex(sub->firstline[vti].v1); - } - } - else - { - int firstndx = gen.GetIndex(sub->firstline[0].v1); - int secondndx = gen.GetIndex(sub->firstline[1].v1); - for (unsigned int k = 2; k < sub->numlines; k++) - { - gen.AddIndex(firstndx); - gen.AddIndex(secondndx); - auto ndx = gen.GetIndex(sub->firstline[k].v1); - gen.AddIndex(ndx); - secondndx = ndx; - } - } - } - - - void CreateVerticesForSection(FSectionContainer &output, FSection §ion) - { - VertexIndexGenerationInfo gen; - - for (auto sub : section.subsectors) - { - CreateIndexedSubsectorVertices(sub, gen); - } - section.vertexindex = output.allVertices.Size(); - section.vertexcount = gen.vertices.Size(); - section.indexindex = output.allVertexIndices.Size(); - section.indexcount = gen.indices.Size(); - output.allVertices.Append(gen.vertices); - output.allVertexIndices.Append(gen.indices); - } - //============================================================================= // @@ -815,7 +717,7 @@ public: output.sectionForSubsectorPtr[ssi] = curgroup; } numsubsectors += group.subsectors.Size(); - CreateVerticesForSection(output, dest); + CreateVerticesForSection(output, dest, true); curgroup++; } } @@ -892,4 +794,186 @@ void CreateSections(FSectionContainer &container) CCMD(printsections) { PrintSections(level.sections); -} \ No newline at end of file +} + + + +//============================================================================= +// +// One sector's vertex data. +// +//============================================================================= + +struct VertexContainer +{ + TArray vertices; + TMap vertexmap; + bool perSubsector = false; + + TArray indices; + + uint32_t AddVertex(FSectionVertex *vert) + { + auto check = vertexmap.CheckKey(vert); + if (check != nullptr) return *check; + auto index = vertices.Push(*vert); + vertexmap[vert] = index; + return index; + } + + uint32_t AddVertex(vertex_t *vert, int qualifier) + { + FSectionVertex vertx = { vert, qualifier}; + return AddVertex(&vertx); + } + + uint32_t GetIndex(FSectionVertex *vert) + { + auto check = vertexmap.CheckKey(vert); + if (check != nullptr) return *check; + return ~0u; + } + + uint32_t GetIndex(vertex_t *vert, int qualifier) + { + FSectionVertex vertx = { vert, qualifier}; + return GetIndex(&vertx); + } + + uint32_t AddIndexForVertex(FSectionVertex *vert) + { + return indices.Push(GetIndex(vert)); + } + + uint32_t AddIndexForVertex(vertex_t *vert, int qualifier) + { + return indices.Push(GetIndex(vert, qualifier)); + } + + uint32_t AddIndex(uint32_t indx) + { + return indices.Push(indx); + } +}; + + +//============================================================================= +// +// Creates vertex meshes for sector planes +// +//============================================================================= + +namespace VertexBuilder +{ + + //============================================================================= + // + // + // + //============================================================================= + + static void CreateVerticesForSubsector(subsector_t *sub, VertexContainer &gen, int qualifier) + { + if (sub->numlines < 3) return; + + uint32_t startindex = gen.indices.Size(); + + if ((sub->flags & SSECF_HOLE) && sub->numlines > 3) + { + // Hole filling "subsectors" are not necessarily convex so they require real triangulation. + // These things are extremely rare so performance is secondary here. + + using Point = std::pair; + std::vector> polygon; + std::vector *curPoly; + + for (unsigned i = 0; i < sub->numlines; i++) + { + polygon.resize(1); + curPoly = &polygon.back(); + curPoly->push_back({ sub->firstline[i].v1->fX(), sub->firstline[i].v1->fY() }); + } + auto indices = mapbox::earcut(polygon); + for (auto vti : indices) + { + gen.AddIndexForVertex(sub->firstline[vti].v1, qualifier); + } + } + else + { + int firstndx = gen.GetIndex(sub->firstline[0].v1, qualifier); + int secondndx = gen.GetIndex(sub->firstline[1].v1, qualifier); + for (unsigned int k = 2; k < sub->numlines; k++) + { + gen.AddIndex(firstndx); + gen.AddIndex(secondndx); + auto ndx = gen.GetIndex(sub->firstline[k].v1, qualifier); + gen.AddIndex(ndx); + secondndx = ndx; + } + } + } + + //============================================================================= + // + // + // + //============================================================================= + + static void TriangulateSection(FSection §, VertexContainer &gen, int qualifier) + { + if (sect.segments.Size() < 3) return; + + // todo + } + + //============================================================================= + // + // + // + //============================================================================= + + + static void CreateVerticesForSection(FSection §ion, VertexContainer &gen, bool useSubsectors) + { + section.vertexindex = gen.indices.Size(); + + if (useSubsectors) + { + for (auto sub : section.subsectors) + { + CreateVerticesForSubsector(sub, gen, -1); + } + } + else + { + TriangulateSection(section, gen, -1); + } + section.vertexcount = gen.indices.Size() - section.vertexindex; + } + + //========================================================================== + // + // Creates the vertices for one plane in one subsector + // + //========================================================================== + + static void CreateVerticesForSector(sector_t *sec, VertexContainer gen) + { + auto sections = level.sections.SectionsForSector(sec); + for (auto §ion :sections) + { + CreateVerticesForSection( section, gen, true); + } + } + + TArray BuildVertices() + { + TArray verticesPerSector(level.sectors.Size(), true); + for (unsigned i=0; i allLines; TArray allSections; - TArray allVertices; - TArray allVertexIndices; TArray allSides; TArray allSubsectors; TArray allIndices; @@ -159,8 +161,6 @@ public: allLines.Clear(); allSections.Clear(); allIndices.Clear(); - allVertexIndices.Clear(); - allVertices.Clear(); allSides.Clear(); allSubsectors.Clear(); } @@ -170,8 +170,6 @@ public: allLines.ShrinkToFit(); allSections.ShrinkToFit(); allIndices.ShrinkToFit(); - allVertexIndices.ShrinkToFit(); - allVertices.ShrinkToFit(); allSides.ShrinkToFit(); allSubsectors.ShrinkToFit(); } @@ -180,4 +178,4 @@ public: void CreateSections(FSectionContainer &container); -#endif \ No newline at end of file +#endif