diff --git a/source/common/utility/filereadermusicinterface.h b/source/common/utility/filereadermusicinterface.h index 70fc3b107..f261f9dd0 100644 --- a/source/common/utility/filereadermusicinterface.h +++ b/source/common/utility/filereadermusicinterface.h @@ -19,4 +19,5 @@ inline ZMusicCustomReader *GetMusicReader(FileReader& fr) delete zr; }; return zcr; -} \ No newline at end of file +} + diff --git a/source/core/rendering/hw_sections.cpp b/source/core/rendering/hw_sections.cpp index 62e595868..943f8920f 100644 --- a/source/core/rendering/hw_sections.cpp +++ b/source/core/rendering/hw_sections.cpp @@ -679,7 +679,7 @@ nexti:; // calculate the rest. auto texture = tileGetTexture(plane ? sectorp->ceilingpicnum : sectorp->floorpicnum); - UVCalculator uvcalc(sectorp, plane, texture, offset); + UVCalculator1 uvcalc(sectorp, plane, texture, offset); entry.texcoords.Resize(entry.vertices.Size()); for (unsigned i = 0; i < entry.vertices.Size(); i++) diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index c01bd51bb..72208942e 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -98,17 +98,17 @@ void HWFlat::MakeVertices() bool canvas = texture->isHardwareCanvas(); if (Sprite == nullptr) { -#if 0 if (section != nullptr) { - auto mesh = sectionGeometry.get(section, plane, geoofs); + TArray* pIndices; + auto mesh = sectionGeometry.get(section, plane, geoofs, &pIndices); - auto ret = screen->mVertexData->AllocVertices(mesh->indices.Size()); + auto ret = screen->mVertexData->AllocVertices(pIndices->Size()); auto vp = ret.first; float base = (plane == 0 ? sec->floorz : sec->ceilingz) * (1 / -256.f); - for (unsigned i = 0; i < mesh->indices.Size(); i++) + for (unsigned i = 0; i < pIndices->Size(); i++) { - auto ii = mesh->indicess[i]; + auto ii = (*pIndices)[i]; auto& pt = mesh->vertices[ii]; auto& uv = mesh->texcoords[ii]; vp->SetVertex(pt.X, base + pt.Z, pt.Y); @@ -116,10 +116,9 @@ void HWFlat::MakeVertices() vp++; } vertindex = ret.second; - vertcount = mesh->indices.Size(); + vertcount = pIndices->Size(); } else -#endif { auto mesh = sectorGeometry.get(oldsection, plane, geoofs); if (!mesh) return; diff --git a/source/core/sectorgeometry.cpp b/source/core/sectorgeometry.cpp index 39da7d9fe..0a19b04c3 100644 --- a/source/core/sectorgeometry.cpp +++ b/source/core/sectorgeometry.cpp @@ -45,6 +45,7 @@ #include "nodebuilder/nodebuild.h" SectorGeometry sectorGeometry; +SectionGeometry sectionGeometry; //========================================================================== // @@ -316,10 +317,10 @@ ETriangulateResult TriangulateOutlineLibtess(const FOutline& polygon, int count, int result = tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_POLYGONS, 3, 2, 0); if (!result) - { + { tessDeleteTess(tess); return ETriangulateResult::Failed; - } + } const float* verts = tessGetVertices(tess); const int* vinds = tessGetVertexIndices(tess); @@ -418,7 +419,7 @@ ETriangulateResult TriangulateOutlineNodeBuild(const FOutline& polygon, int coun // //========================================================================== -bool SectionGeometry::ValidateSection(Section2* section, int plane, const FVector2& offset) +bool SectionGeometry::ValidateSection(Section2* section, int plane) { auto sec = section->sector; auto& sdata = data[section->index]; @@ -457,10 +458,116 @@ bool SectionGeometry::ValidateSection(Section2* section, int plane, const FVecto } +//========================================================================== +// +// +// +//========================================================================== + +bool SectionGeometry::CreateMesh(Section2* section) +{ + auto outline = BuildOutline(section); + FOutline foutline; + int count = OutlineToFloat(outline, foutline); + if (count == -1) return false; // gotta wait... + TArray meshVertices; + TArray meshIndices; + ETriangulateResult result = ETriangulateResult::Failed; + + auto& sdata = data[section->index]; + + if (!(section->flags & NoEarcut)) + { + result = TriangulateOutlineEarcut(foutline, count, sdata.meshVertices, sdata.meshIndices); + } + if (result == ETriangulateResult::Failed && !(section->flags & NoLibtess)) + { + section->flags |= NoEarcut; + result = TriangulateOutlineLibtess(foutline, count, sdata.meshVertices, sdata.meshIndices); + } + if (result == ETriangulateResult::Failed) + { + section->flags |= NoLibtess; + result = TriangulateOutlineNodeBuild(foutline, count, sdata.meshVertices, meshIndices); + } + section->flags &= ~EDirty::GeometryDirty; + return true; +} + +//========================================================================== +// +// assumes that the geometry has already been validated. +// +//========================================================================== + +void SectionGeometry::CreatePlaneMesh(Section2* section, int plane, const FVector2& offset) +{ + auto sectorp = section->sector; + // calculate the rest. + auto texture = tileGetTexture(plane ? sectorp->ceilingpicnum : sectorp->floorpicnum); + auto& sdata = data[section->index]; + auto& entry = sdata.planes[plane]; + int fz = sectorp->floorz, cz = sectorp->ceilingz; + sectorp->floorz = sectorp->ceilingz = 0; + + UVCalculator uvcalc(sectorp, plane, texture, offset); + + entry.vertices.Resize(sdata.meshVertices.Size()); + entry.texcoords.Resize(entry.vertices.Size()); + + for (unsigned i = 0; i < entry.vertices.Size(); i++) + { + auto& org = sdata.meshVertices[i]; + auto& pt = entry.vertices[i]; + auto& tc = entry.texcoords[i]; + + pt.XY() = org; + PlanesAtPoint(sectorp, (pt.X * 16), (pt.Y * -16), plane ? &pt.Z : nullptr, !plane ? &pt.Z : nullptr); + tc = uvcalc.GetUV(int(pt.X * 16.), int(pt.Y * -16.), pt.Z); + } + entry.normal = CalcNormal(sectorp, plane); + sectorp->floorz = fz; + sectorp->ceilingz = cz; +} + +//========================================================================== +// +// +// +//========================================================================== + void SectionGeometry::MarkDirty(sectortype* sector) { for (auto section : sections2PerSector[sectnum(sector)]) { data[section->index].dirty = sector->dirty; } + sector->dirty = 0; +} + +//========================================================================== +// +// +// +//========================================================================== + +SectionGeometryPlane* SectionGeometry::get(Section2* section, int plane, const FVector2& offset, TArray** pIndices) +{ + if (!section || section->index >= data.Size()) return nullptr; + auto sectp = section->sector; + if (sectp->dirty) MarkDirty(sectp); + if (section->flags & EDirty::GeometryDirty) + { + bool res = CreateMesh(section); + if (!res) + { + section->flags &= ~EDirty::GeometryDirty; // sector is in an invalid state, so pretend the old setup is still valid. Happens in some SW maps. + } + } + if (!ValidateSection(section, plane)) + { + CreatePlaneMesh(section, plane, offset); + } + *pIndices = &data[section->index].meshIndices; + return &data[section->index].planes[plane]; } diff --git a/source/core/sectorgeometry.h b/source/core/sectorgeometry.h index 39641e259..bcfe8d044 100644 --- a/source/core/sectorgeometry.h +++ b/source/core/sectorgeometry.h @@ -56,9 +56,13 @@ enum GeomFlags CeilingDone = 8, }; +using SectionGeometryPlane = SectorGeometryPlane; + struct SectionGeometryData { SectorGeometryPlane planes[2]; + TArray meshVertices; // flat vertices. Stored separately so that plane changes won't require completely new triangulation. + TArray meshIndices; sectortype compare[2] = {}; vec2_t poscompare[2] = {}; vec2_t poscompare2[2] = {}; @@ -69,22 +73,16 @@ struct SectionGeometryData class SectionGeometry { - TArray meshVerts; - TArray meshIndices; TArray data; - bool ValidateSection(Section2* section, int plane, const FVector2& offset); + bool ValidateSection(Section2* section, int plane); void MarkDirty(sectortype* sector); + bool CreateMesh(Section2* section); + void CreatePlaneMesh(Section2* section, int plane, const FVector2& offset); + public: - /* - SectionGeometryPlane* get(Section2* section, int plane, const FVector2& offset) - { - if (section->index >= data.Size()) return nullptr; - ValidateSector(section->index, plane, offset); - return &data[section->index].planes[plane]; - } - */ + SectionGeometryPlane* get(Section2* section, int plane, const FVector2& offset, TArray** pIndices); void SetSize(unsigned sectcount) {