From 412be46e088c86a421c154c3d8f999bceb5629fa Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 11 Dec 2023 11:21:20 +0100 Subject: [PATCH] Misc surface and lightmapper related cleanup and renaming --- .../hwrenderer/data/hw_levelmesh.cpp | 30 ++-- .../rendering/hwrenderer/data/hw_levelmesh.h | 42 +++-- src/common/rendering/vulkan/vk_levelmesh.cpp | 14 +- .../rendering/vulkan/vk_lightmapper.cpp | 14 +- src/maploader/maploader.cpp | 4 +- src/rendering/hwrenderer/doom_levelmesh.cpp | 77 ++++---- src/rendering/hwrenderer/doom_levelmesh.h | 3 + .../hwrenderer/doom_levelsubmesh.cpp | 165 +++++++++--------- src/rendering/hwrenderer/doom_levelsubmesh.h | 10 +- src/rendering/hwrenderer/hw_vertexbuilder.cpp | 2 +- .../hwrenderer/scene/hw_drawinfo.cpp | 2 +- src/rendering/hwrenderer/scene/hw_drawinfo.h | 2 +- src/rendering/hwrenderer/scene/hw_walls.cpp | 24 +-- 13 files changed, 202 insertions(+), 187 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp index 97263d922..25ae6928d 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp @@ -32,8 +32,8 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl } hitSurface = hitmesh->GetSurface(hitmesh->Mesh.SurfaceIndexes[hit.triangle]); - auto portal = hitSurface->portalIndex; + int portal = hitSurface->PortalIndex; if (!portal) { break; @@ -100,7 +100,7 @@ void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats) for (int i = 0; i < count; ++i) { const auto* surface = GetSurface(i); - auto area = surface->Area(); + auto area = surface->AtlasTile.Area(); stats.pixels.total += area; @@ -109,7 +109,7 @@ void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats) stats.surfaces.dirty++; stats.pixels.dirty += area; } - if (surface->bSky) + if (surface->IsSky) { stats.surfaces.sky++; stats.pixels.sky += area; @@ -133,12 +133,12 @@ void LevelSubmesh::BuildTileSurfaceLists() for (size_t j = 0; j < SmoothingGroups.Size(); j++) { - if (surface->sectorGroup == SmoothingGroups[j].sectorGroup) + if (surface->SectorGroup == SmoothingGroups[j].sectorGroup) { - float direction = SmoothingGroups[j].plane.XYZ() | surface->plane.XYZ(); + float direction = SmoothingGroups[j].plane.XYZ() | surface->Plane.XYZ(); if (direction >= 0.9999f && direction <= 1.001f) { - auto point = (surface->plane.XYZ() * surface->plane.W); + auto point = (surface->Plane.XYZ() * surface->Plane.W); auto planeDistance = (SmoothingGroups[j].plane.XYZ() | point) - SmoothingGroups[j].plane.W; float dist = std::abs(planeDistance); @@ -157,8 +157,8 @@ void LevelSubmesh::BuildTileSurfaceLists() smoothingGroupIndex = SmoothingGroups.Size(); LevelMeshSmoothingGroup group; - group.plane = surface->plane; - group.sectorGroup = surface->sectorGroup; + group.plane = surface->Plane; + group.sectorGroup = surface->SectorGroup; SmoothingGroups.Push(group); } @@ -169,23 +169,23 @@ void LevelSubmesh::BuildTileSurfaceLists() for (int i = 0, count = GetSurfaceCount(); i < count; i++) { auto targetSurface = GetSurface(i); - targetSurface->tileSurfaces.Clear(); + targetSurface->TileSurfaces.Clear(); for (LevelMeshSurface* surface : SmoothingGroups[SmoothingGroupIndexes[i]].surfaces) { - FVector2 minUV = ToUV(surface->bounds.min, targetSurface); - FVector2 maxUV = ToUV(surface->bounds.max, targetSurface); + FVector2 minUV = ToUV(surface->Bounds.min, targetSurface); + FVector2 maxUV = ToUV(surface->Bounds.max, targetSurface); if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f)) continue; // Bounding box not visible - targetSurface->tileSurfaces.Push(surface); + targetSurface->TileSurfaces.Push(surface); } } } FVector2 LevelSubmesh::ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface) { - FVector3 localPos = vert - targetSurface->translateWorldToLocal; - float u = (1.0f + (localPos | targetSurface->projLocalToU)) / (targetSurface->AtlasTile.Width + 2); - float v = (1.0f + (localPos | targetSurface->projLocalToV)) / (targetSurface->AtlasTile.Height + 2); + FVector3 localPos = vert - targetSurface->TileTransform.TranslateWorldToLocal; + float u = (1.0f + (localPos | targetSurface->TileTransform.ProjLocalToU)) / (targetSurface->AtlasTile.Width + 2); + float v = (1.0f + (localPos | targetSurface->TileTransform.ProjLocalToV)) / (targetSurface->AtlasTile.Height + 2); return FVector2(u, v); } diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 1f1043faa..45dbe8c02 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -38,12 +38,15 @@ struct LevelMeshSurface { LevelSubmesh* Submesh = nullptr; - int numVerts = 0; - unsigned int startVertIndex = 0; - unsigned int startElementIndex = 0; - unsigned int numElements = 0; - FVector4 plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f); - bool bSky = false; + struct + { + unsigned int StartVertIndex = 0; + int NumVerts = 0; + unsigned int StartElementIndex = 0; + unsigned int NumElements = 0; + } MeshLocation; + + FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f); // Surface location in lightmap texture struct @@ -53,30 +56,33 @@ struct LevelMeshSurface int Width = 0; int Height = 0; int ArrayIndex = 0; + uint32_t Area() const { return Width * Height; } } AtlasTile; // True if the surface needs to be rendered into the lightmap texture before it can be used bool NeedsUpdate = true; bool AlwaysUpdate = false; - FGameTexture* texture = nullptr; - float alpha = 1.0; + FGameTexture* Texture = nullptr; + float Alpha = 1.0; - int portalIndex = 0; - int sectorGroup = 0; + bool IsSky = false; + int PortalIndex = 0; + int SectorGroup = 0; - BBox bounds; - uint16_t sampleDimension = 0; + BBox Bounds; + uint16_t SampleDimension = 0; // Calculate world coordinates to UV coordinates - FVector3 translateWorldToLocal = { 0.f, 0.f, 0.f }; - FVector3 projLocalToU = { 0.f, 0.f, 0.f }; - FVector3 projLocalToV = { 0.f, 0.f, 0.f }; + struct + { + FVector3 TranslateWorldToLocal = { 0.0f, 0.0f, 0.0f }; + FVector3 ProjLocalToU = { 0.0f, 0.0f, 0.0f }; + FVector3 ProjLocalToV = { 0.0f, 0.0f, 0.0f }; + } TileTransform; // Surfaces that are visible within the lightmap tile - TArray tileSurfaces; - - uint32_t Area() const { return AtlasTile.Width * AtlasTile.Height; } + TArray TileSurfaces; // Light list location in the lightmapper GPU buffers struct diff --git a/src/common/rendering/vulkan/vk_levelmesh.cpp b/src/common/rendering/vulkan/vk_levelmesh.cpp index 00ee5e196..9fe848273 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.cpp +++ b/src/common/rendering/vulkan/vk_levelmesh.cpp @@ -638,14 +638,14 @@ void VkLevelMeshUploader::UploadSurfaces() LevelMeshSurface* surface = submesh->GetSurface(j); SurfaceInfo info; - info.Normal = FVector3(surface->plane.X, surface->plane.Z, surface->plane.Y); - info.PortalIndex = surface->portalIndex; - info.SamplingDistance = (float)surface->sampleDimension; - info.Sky = surface->bSky; - info.Alpha = surface->alpha; - if (surface->texture) + info.Normal = FVector3(surface->Plane.X, surface->Plane.Z, surface->Plane.Y); + info.PortalIndex = surface->PortalIndex; + info.SamplingDistance = (float)surface->SampleDimension; + info.Sky = surface->IsSky; + info.Alpha = surface->Alpha; + if (surface->Texture) { - auto mat = FMaterial::ValidateTexture(surface->texture, 0); + auto mat = FMaterial::ValidateTexture(surface->Texture, 0); info.TextureIndex = Mesh->fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0); } else diff --git a/src/common/rendering/vulkan/vk_lightmapper.cpp b/src/common/rendering/vulkan/vk_lightmapper.cpp index 5c84685dd..4a7a5126a 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.cpp +++ b/src/common/rendering/vulkan/vk_lightmapper.cpp @@ -200,14 +200,14 @@ void VkLightmapper::Render() pc.TextureSize = (float)bakeImageSize; pc.TileWidth = (float)targetSurface->AtlasTile.Width; pc.TileHeight = (float)targetSurface->AtlasTile.Height; - pc.WorldToLocal = SwapYZ(targetSurface->translateWorldToLocal); - pc.ProjLocalToU = SwapYZ(targetSurface->projLocalToU); - pc.ProjLocalToV = SwapYZ(targetSurface->projLocalToV); + pc.WorldToLocal = SwapYZ(targetSurface->TileTransform.TranslateWorldToLocal); + pc.ProjLocalToU = SwapYZ(targetSurface->TileTransform.ProjLocalToU); + pc.ProjLocalToV = SwapYZ(targetSurface->TileTransform.ProjLocalToV); bool buffersFull = false; // Paint all surfaces visible in the tile - for (LevelMeshSurface* surface : targetSurface->tileSurfaces) + for (LevelMeshSurface* surface : targetSurface->TileSurfaces) { if (surface->LightList.ResetCounter != lights.ResetCounter) { @@ -247,9 +247,9 @@ void VkLightmapper::Render() #ifdef USE_DRAWINDIRECT VkDrawIndexedIndirectCommand cmd; - cmd.indexCount = surface->numElements; + cmd.indexCount = surface->MeshLocation.NumElements; cmd.instanceCount = 1; - cmd.firstIndex = firstIndexOffset + surface->startElementIndex; + cmd.firstIndex = firstIndexOffset + surface->MeshLocation.StartElementIndex; cmd.vertexOffset = 0; cmd.firstInstance = drawindexed.Pos; drawindexed.Constants[drawindexed.Pos] = pc; @@ -419,7 +419,7 @@ void VkLightmapper::CopyResult() } copylists[pageIndex].Push(&selected); - pixels += selected.Surface->Area(); + pixels += selected.Surface->AtlasTile.Area(); lastSurfaceCount++; } } diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 42e54ca99..4d83e9704 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -3321,7 +3321,7 @@ bool MapLoader::LoadLightmap(MapData* map) dstX, dstY, dstX + realSurface.AtlasTile.Width, dstY + realSurface.AtlasTile.Height, dstPage, - realSurface.Area() * 3); + realSurface.AtlasTile.Area() * 3); } // copy pixels @@ -3351,7 +3351,7 @@ bool MapLoader::LoadLightmap(MapData* map) { auto& realSurface = *surface.targetSurface; - auto* vertices = &submesh->Mesh.Vertices[realSurface.startVertIndex]; + auto* vertices = &submesh->Mesh.Vertices[realSurface.MeshLocation.StartVertIndex]; auto* newUVs = &zdrayUvs[surface.uvOffset]; for (uint32_t i = 0; i < surface.uvCount; ++i) diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index a5e8ae90a..4241c93a2 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -80,17 +80,17 @@ void PrintSurfaceInfo(const DoomLevelMeshSurface* surface) { if (!RequireLevelMesh()) return; - auto gameTexture = surface->texture; + auto gameTexture = surface->Texture; Printf("Surface %d (%p)\n Type: %d, TypeIndex: %d, ControlSector: %d\n", surface->Submesh->GetSurfaceIndex(surface), surface, surface->Type, surface->TypeIndex, surface->ControlSector ? surface->ControlSector->Index() : -1); Printf(" Atlas page: %d, x:%d, y:%d\n", surface->AtlasTile.ArrayIndex, surface->AtlasTile.X, surface->AtlasTile.Y); - Printf(" Pixels: %dx%d (area: %d)\n", surface->AtlasTile.Width, surface->AtlasTile.Height, surface->Area()); - Printf(" Sample dimension: %d\n", surface->sampleDimension); + Printf(" Pixels: %dx%d (area: %d)\n", surface->AtlasTile.Width, surface->AtlasTile.Height, surface->AtlasTile.Area()); + Printf(" Sample dimension: %d\n", surface->SampleDimension); Printf(" Needs update?: %d\n", surface->NeedsUpdate); Printf(" Always update?: %d\n", surface->AlwaysUpdate); - Printf(" Sector group: %d\n", surface->sectorGroup); + Printf(" Sector group: %d\n", surface->SectorGroup); Printf(" Texture: '%s'\n", gameTexture ? gameTexture->GetName().GetChars() : ""); - Printf(" Alpha: %f\n", surface->alpha); + Printf(" Alpha: %f\n", surface->Alpha); } FVector3 RayDir(FAngle angle, FAngle pitch) @@ -144,23 +144,20 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap) BuildSectorGroups(doomMap); CreatePortals(doomMap); - StaticMesh = std::make_unique(this); - DynamicMesh = std::make_unique(this); - - static_cast(StaticMesh.get())->CreateStatic(doomMap); - static_cast(DynamicMesh.get())->CreateDynamic(doomMap); + StaticMesh = std::make_unique(this, doomMap, true); + DynamicMesh = std::make_unique(this, doomMap, false); } void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap) { - static_cast(DynamicMesh.get())->UpdateDynamic(doomMap, static_cast(StaticMesh.get())->LMTextureCount); + static_cast(DynamicMesh.get())->Update(doomMap, static_cast(StaticMesh.get())->LMTextureCount); } bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float dist) { FVector3 end = start + direction * dist; auto surface = Trace(start, direction, dist); - return surface && surface->bSky; + return surface && surface->IsSky; } void DoomLevelMesh::PackLightmapAtlas() @@ -170,31 +167,7 @@ void DoomLevelMesh::PackLightmapAtlas() int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { - const DoomLevelMeshSurface* doomsurf = static_cast(surface); - - FLightNode* node = nullptr; - if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING) - { - node = doomsurf->Subsector->section->lighthead; - } - else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE) - { - bool isPolyLine = !!(doomsurf->Side->Flags & WALLF_POLYOBJ); - if (isPolyLine) - { - subsector_t* subsector = level.PointInRenderSubsector((doomsurf->Side->V1()->fPos() + doomsurf->Side->V2()->fPos()) * 0.5); - node = subsector->section->lighthead; - } - else if (!doomsurf->ControlSector) - { - node = doomsurf->Side->lighthead; - } - else // 3d floor needs light from the sidedef on the other side - { - int otherside = doomsurf->Side->linedef->sidedef[0] == doomsurf->Side ? 1 : 0; - node = doomsurf->Side->linedef->sidedef[otherside]->lighthead; - } - } + FLightNode* node = GetSurfaceLightNode(static_cast(surface)); if (!node) return 0; @@ -247,6 +220,34 @@ int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLi return listpos; } +FLightNode* DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf) +{ + FLightNode* node = nullptr; + if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING) + { + node = doomsurf->Subsector->section->lighthead; + } + else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE) + { + bool isPolyLine = !!(doomsurf->Side->Flags & WALLF_POLYOBJ); + if (isPolyLine) + { + subsector_t* subsector = level.PointInRenderSubsector((doomsurf->Side->V1()->fPos() + doomsurf->Side->V2()->fPos()) * 0.5); + node = subsector->section->lighthead; + } + else if (!doomsurf->ControlSector) + { + node = doomsurf->Side->lighthead; + } + else // 3d floor needs light from the sidedef on the other side + { + int otherside = doomsurf->Side->linedef->sidedef[0] == doomsurf->Side ? 1 : 0; + node = doomsurf->Side->linedef->sidedef[otherside]->lighthead; + } + } + return node; +} + void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const { DoomLevelSubmesh* submesh = static_cast(StaticMesh.get()); @@ -315,7 +316,7 @@ void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilen else { const auto& surface = submesh->Surfaces[index]; - fprintf(f, "o Surface[%d] %s %d%s\n", index, name(surface.Type), surface.TypeIndex, surface.bSky ? " sky" : ""); + fprintf(f, "o Surface[%d] %s %d%s\n", index, name(surface.Type), surface.TypeIndex, surface.IsSky ? " sky" : ""); fprintf(f, "usemtl lightmap%d\n", surface.AtlasTile.ArrayIndex); if (surface.AtlasTile.ArrayIndex > highestUsedAtlasPage) diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 352f15779..4368ebf32 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -22,4 +22,7 @@ public: TArray sectorGroup; // index is sector, value is sectorGroup TArray sectorPortals[2]; // index is sector+plane, value is index into the portal list TArray linePortals; // index is linedef, value is index into the portal list + +private: + FLightNode* GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf); }; diff --git a/src/rendering/hwrenderer/doom_levelsubmesh.cpp b/src/rendering/hwrenderer/doom_levelsubmesh.cpp index b362399c7..f61742e1a 100644 --- a/src/rendering/hwrenderer/doom_levelsubmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelsubmesh.cpp @@ -21,41 +21,40 @@ void GetTexCoordInfo(FGameTexture* tex, FTexCoordInfo* tci, side_t* side, int te EXTERN_CVAR(Bool, gl_texture) EXTERN_CVAR(Float, lm_scale); -void DoomLevelSubmesh::CreateStatic(FLevelLocals& doomMap) -{ - LightmapSampleDistance = doomMap.LightmapSampleDistance; - - Reset(); - - CreateStaticSurfaces(doomMap); - LinkSurfaces(doomMap); - - CreateIndexes(); - SetupLightmapUvs(doomMap); - BuildTileSurfaceLists(); - UpdateCollision(); -} - -void DoomLevelSubmesh::CreateDynamic(FLevelLocals& doomMap) +DoomLevelSubmesh::DoomLevelSubmesh(DoomLevelMesh* mesh, FLevelLocals& doomMap, bool staticMesh) : LevelMesh(mesh), StaticMesh(staticMesh) { LightmapSampleDistance = doomMap.LightmapSampleDistance; Reset(); + + if (StaticMesh) + { + CreateStaticSurfaces(doomMap); + LinkSurfaces(doomMap); + + CreateIndexes(); + SetupLightmapUvs(doomMap); + BuildTileSurfaceLists(); + UpdateCollision(); + } } -void DoomLevelSubmesh::UpdateDynamic(FLevelLocals& doomMap, int lightmapStartIndex) +void DoomLevelSubmesh::Update(FLevelLocals& doomMap, int lightmapStartIndex) { - Reset(); + if (!StaticMesh) + { + Reset(); - CreateDynamicSurfaces(doomMap); - LinkSurfaces(doomMap); + CreateDynamicSurfaces(doomMap); + LinkSurfaces(doomMap); - CreateIndexes(); - SetupLightmapUvs(doomMap); - BuildTileSurfaceLists(); - UpdateCollision(); + CreateIndexes(); + SetupLightmapUvs(doomMap); + BuildTileSurfaceLists(); + UpdateCollision(); - if (doomMap.lightmaps) - PackLightmapAtlas(lightmapStartIndex); + if (doomMap.lightmaps) + PackLightmapAtlas(lightmapStartIndex); + } } void DoomLevelSubmesh::Reset() @@ -169,14 +168,14 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap) surf.TypeIndex = side->Index(); surf.Side = side; surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); - surf.sectorGroup = LevelMesh->sectorGroup[front->Index()]; - surf.alpha = float(side->linedef->alpha); - surf.startVertIndex = startVertIndex; - surf.numVerts = Mesh.Vertices.Size() - startVertIndex; - surf.plane = ToPlane(Mesh.Vertices[startVertIndex].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 3].fPos()); - surf.texture = wallpart.texture; + surf.SectorGroup = LevelMesh->sectorGroup[front->Index()]; + surf.Alpha = float(side->linedef->alpha); + surf.MeshLocation.StartVertIndex = startVertIndex; + surf.MeshLocation.NumVerts = Mesh.Vertices.Size() - startVertIndex; + surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 3].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos()); + surf.Texture = wallpart.texture; surf.PipelineID = pipelineID; - surf.portalIndex = (surf.Type == ST_MIDDLESIDE) ? LevelMesh->linePortals[side->linedef->Index()] : 0; + surf.PortalIndex = (surf.Type == ST_MIDDLESIDE) ? LevelMesh->linePortals[side->linedef->Index()] : 0; Surfaces.Push(surf); } @@ -242,19 +241,21 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap) if (!foundDraw) continue; - auto plane = sector->GetSecPlane(flatpart.ceiling); - DoomLevelMeshSurface surf; surf.Submesh = this; surf.Type = flatpart.ceiling ? ST_CEILING : ST_FLOOR; surf.ControlSector = flatpart.controlsector ? flatpart.controlsector->model : nullptr; surf.AlwaysUpdate = !!(sector->Flags & SECF_LM_DYNAMIC); - surf.sectorGroup = LevelMesh->sectorGroup[sector->Index()]; - surf.alpha = flatpart.alpha; - surf.texture = flatpart.texture; + surf.SectorGroup = LevelMesh->sectorGroup[sector->Index()]; + surf.Alpha = flatpart.alpha; + surf.Texture = flatpart.texture; surf.PipelineID = pipelineID; - surf.plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D); - surf.portalIndex = LevelMesh->sectorPortals[flatpart.ceiling][i]; + surf.PortalIndex = LevelMesh->sectorPortals[flatpart.ceiling][i]; + + auto plane = sector->GetSecPlane(flatpart.ceiling); + surf.Plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D); + //if (flatpart.ceiling) + // surf.Plane = -surf.Plane; for (subsector_t* sub : section.subsectors) { @@ -280,8 +281,11 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap) surf.TypeIndex = sub->Index(); surf.Subsector = sub; - surf.startVertIndex = startVertIndex; - surf.numVerts = sub->numlines; + surf.MeshLocation.StartVertIndex = startVertIndex; + surf.MeshLocation.NumVerts = sub->numlines; + + //surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos()); + Surfaces.Push(surf); } } @@ -321,7 +325,7 @@ void DoomLevelSubmesh::CreateIndexes() for (size_t i = 0; i < Surfaces.Size(); i++) { DoomLevelMeshSurface* s = &Surfaces[i]; - pipelineSurfaces[(int64_t(s->PipelineID) << 32) | int64_t(s->bSky)].Push(i); + pipelineSurfaces[(int64_t(s->PipelineID) << 32) | int64_t(s->IsSky)].Push(i); } for (const auto& it : pipelineSurfaces) @@ -332,13 +336,12 @@ void DoomLevelSubmesh::CreateIndexes() for (unsigned int i : it.second) { DoomLevelMeshSurface& s = Surfaces[i]; - int numVerts = s.numVerts; - unsigned int pos = s.startVertIndex; + int numVerts = s.MeshLocation.NumVerts; + unsigned int pos = s.MeshLocation.StartVertIndex; FFlatVertex* verts = &Mesh.Vertices[pos]; - s.Vertices = verts; - s.startElementIndex = Mesh.Indexes.Size(); - s.numElements = 0; + s.MeshLocation.StartElementIndex = Mesh.Indexes.Size(); + s.MeshLocation.NumElements = 0; if (s.Type == ST_CEILING) { @@ -350,7 +353,7 @@ void DoomLevelSubmesh::CreateIndexes() Mesh.Indexes.Push(pos + j - 1); Mesh.Indexes.Push(pos + j); Mesh.SurfaceIndexes.Push((int)i); - s.numElements += 3; + s.MeshLocation.NumElements += 3; } } } @@ -364,7 +367,7 @@ void DoomLevelSubmesh::CreateIndexes() Mesh.Indexes.Push(pos + j - 1); Mesh.Indexes.Push(pos); Mesh.SurfaceIndexes.Push((int)i); - s.numElements += 3; + s.MeshLocation.NumElements += 3; } } } @@ -376,7 +379,7 @@ void DoomLevelSubmesh::CreateIndexes() Mesh.Indexes.Push(pos + 1); Mesh.Indexes.Push(pos + 2); Mesh.SurfaceIndexes.Push((int)i); - s.numElements += 3; + s.MeshLocation.NumElements += 3; } if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[3].fPos())) { @@ -384,7 +387,7 @@ void DoomLevelSubmesh::CreateIndexes() Mesh.Indexes.Push(pos + 2); Mesh.Indexes.Push(pos + 3); Mesh.SurfaceIndexes.Push((int)i); - s.numElements += 3; + s.MeshLocation.NumElements += 3; } } } @@ -489,7 +492,7 @@ void DoomLevelSubmesh::SetupLightmapUvs(FLevelLocals& doomMap) for (auto& surface : Surfaces) { - BuildSurfaceParams(LMTextureSize, LMTextureSize, surface); + SetupTileTransform(LMTextureSize, LMTextureSize, surface); } } @@ -520,9 +523,9 @@ void DoomLevelSubmesh::PackLightmapAtlas(int lightmapStartIndex) surf->AtlasTile.ArrayIndex = lightmapStartIndex + (int)result.pageIndex; // calculate final texture coordinates - for (int i = 0; i < (int)surf->numVerts; i++) + for (int i = 0; i < (int)surf->MeshLocation.NumVerts; i++) { - auto& vertex = Mesh.Vertices[surf->startVertIndex + i]; + auto& vertex = Mesh.Vertices[surf->MeshLocation.StartVertIndex + i]; vertex.lu = (vertex.lu + x) / (float)LMTextureSize; vertex.lv = (vertex.lv + y) / (float)LMTextureSize; vertex.lindex = (float)surf->AtlasTile.ArrayIndex; @@ -539,7 +542,7 @@ BBox DoomLevelSubmesh::GetBoundsFromSurface(const LevelMeshSurface& surface) con FVector3 low(M_INFINITY, M_INFINITY, M_INFINITY); FVector3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY); - for (int i = int(surface.startVertIndex); i < int(surface.startVertIndex) + surface.numVerts; i++) + for (int i = int(surface.MeshLocation.StartVertIndex); i < int(surface.MeshLocation.StartVertIndex) + surface.MeshLocation.NumVerts; i++) { for (int j = 0; j < 3; j++) { @@ -580,41 +583,41 @@ DoomLevelSubmesh::PlaneAxis DoomLevelSubmesh::BestAxis(const FVector4& p) return AXIS_XY; } -void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface) +void DoomLevelSubmesh::SetupTileTransform(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface) { BBox bounds = GetBoundsFromSurface(surface); - surface.bounds = bounds; + surface.Bounds = bounds; - if (surface.sampleDimension <= 0) + if (surface.SampleDimension <= 0) { - surface.sampleDimension = LightmapSampleDistance; + surface.SampleDimension = LightmapSampleDistance; } - surface.sampleDimension = uint16_t(max(int(roundf(float(surface.sampleDimension) / max(1.0f / 4, float(lm_scale)))), 1)); + surface.SampleDimension = uint16_t(max(int(roundf(float(surface.SampleDimension) / max(1.0f / 4, float(lm_scale)))), 1)); { // Round to nearest power of two - uint32_t n = uint16_t(surface.sampleDimension); + uint32_t n = uint16_t(surface.SampleDimension); n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8; n = (n + 1) >> 1; - surface.sampleDimension = uint16_t(n) ? uint16_t(n) : uint16_t(0xFFFF); + surface.SampleDimension = uint16_t(n) ? uint16_t(n) : uint16_t(0xFFFF); } // round off dimensions FVector3 roundedSize; for (int i = 0; i < 3; i++) { - bounds.min[i] = surface.sampleDimension * (floor(bounds.min[i] / surface.sampleDimension) - 1); - bounds.max[i] = surface.sampleDimension * (ceil(bounds.max[i] / surface.sampleDimension) + 1); - roundedSize[i] = (bounds.max[i] - bounds.min[i]) / surface.sampleDimension; + bounds.min[i] = surface.SampleDimension * (floor(bounds.min[i] / surface.SampleDimension) - 1); + bounds.max[i] = surface.SampleDimension * (ceil(bounds.max[i] / surface.SampleDimension) + 1); + roundedSize[i] = (bounds.max[i] - bounds.min[i]) / surface.SampleDimension; } FVector3 tCoords[2] = { FVector3(0.0f, 0.0f, 0.0f), FVector3(0.0f, 0.0f, 0.0f) }; - PlaneAxis axis = BestAxis(surface.plane); + PlaneAxis axis = BestAxis(surface.Plane); int width; int height; @@ -624,22 +627,22 @@ void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMap case AXIS_YZ: width = (int)roundedSize.Y; height = (int)roundedSize.Z; - tCoords[0].Y = 1.0f / surface.sampleDimension; - tCoords[1].Z = 1.0f / surface.sampleDimension; + tCoords[0].Y = 1.0f / surface.SampleDimension; + tCoords[1].Z = 1.0f / surface.SampleDimension; break; case AXIS_XZ: width = (int)roundedSize.X; height = (int)roundedSize.Z; - tCoords[0].X = 1.0f / surface.sampleDimension; - tCoords[1].Z = 1.0f / surface.sampleDimension; + tCoords[0].X = 1.0f / surface.SampleDimension; + tCoords[1].Z = 1.0f / surface.SampleDimension; break; case AXIS_XY: width = (int)roundedSize.X; height = (int)roundedSize.Y; - tCoords[0].X = 1.0f / surface.sampleDimension; - tCoords[1].Y = 1.0f / surface.sampleDimension; + tCoords[0].X = 1.0f / surface.SampleDimension; + tCoords[1].Y = 1.0f / surface.SampleDimension; break; } @@ -657,18 +660,19 @@ void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMap height = (lightMapTextureHeight - 2); } - surface.translateWorldToLocal = bounds.min; - surface.projLocalToU = tCoords[0]; - surface.projLocalToV = tCoords[1]; + surface.TileTransform.TranslateWorldToLocal = bounds.min; + surface.TileTransform.ProjLocalToU = tCoords[0]; + surface.TileTransform.ProjLocalToV = tCoords[1]; - for (int i = 0; i < surface.numVerts; i++) + for (int i = 0; i < surface.MeshLocation.NumVerts; i++) { - FVector3 tDelta = Mesh.Vertices[surface.startVertIndex + i].fPos() - surface.translateWorldToLocal; + FVector3 tDelta = Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].fPos() - surface.TileTransform.TranslateWorldToLocal; - Mesh.Vertices[surface.startVertIndex + i].lu = (tDelta | surface.projLocalToU); - Mesh.Vertices[surface.startVertIndex + i].lv = (tDelta | surface.projLocalToV); + Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].lu = (tDelta | surface.TileTransform.ProjLocalToU); + Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].lv = (tDelta | surface.TileTransform.ProjLocalToV); } +#if 0 // project tCoords so they lie on the plane const FVector4& plane = surface.plane; float d = ((bounds.min | FVector3(plane.X, plane.Y, plane.Z)) - plane.W) / plane[axis]; //d = (plane->PointToDist(bounds.min)) / plane->Normal()[axis]; @@ -678,6 +682,7 @@ void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMap d = (tCoords[i] | FVector3(plane.X, plane.Y, plane.Z)) / plane[axis]; //d = dot(tCoords[i], plane->Normal()) / plane->Normal()[axis]; tCoords[i][axis] -= d; } +#endif surface.AtlasTile.Width = width; surface.AtlasTile.Height = height; diff --git a/src/rendering/hwrenderer/doom_levelsubmesh.h b/src/rendering/hwrenderer/doom_levelsubmesh.h index 24ad76899..b15d96973 100644 --- a/src/rendering/hwrenderer/doom_levelsubmesh.h +++ b/src/rendering/hwrenderer/doom_levelsubmesh.h @@ -25,18 +25,15 @@ struct DoomLevelMeshSurface : public LevelMeshSurface side_t* Side = nullptr; sector_t* ControlSector = nullptr; - FFlatVertex* Vertices = nullptr; int PipelineID = 0; }; class DoomLevelSubmesh : public LevelSubmesh { public: - DoomLevelSubmesh(DoomLevelMesh* mesh) : LevelMesh(mesh) { } + DoomLevelSubmesh(DoomLevelMesh* mesh, FLevelLocals& doomMap, bool staticMesh); - void CreateStatic(FLevelLocals& doomMap); - void CreateDynamic(FLevelLocals& doomMap); - void UpdateDynamic(FLevelLocals& doomMap, int lightmapStartIndex); + void Update(FLevelLocals& doomMap, int lightmapStartIndex); LevelMeshSurface* GetSurface(int index) override { return &Surfaces[index]; } unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const override { return (unsigned int)(ptrdiff_t)(static_cast(surface) - Surfaces.Data()); } @@ -98,7 +95,7 @@ private: static PlaneAxis BestAxis(const FVector4& p); BBox GetBoundsFromSurface(const LevelMeshSurface& surface) const; - void BuildSurfaceParams(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface); + void SetupTileTransform(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface); static bool IsDegenerate(const FVector3& v0, const FVector3& v1, const FVector3& v2); @@ -107,6 +104,7 @@ private: static FVector4 ToFVector4(const DVector4& v) { return FVector4((float)v.X, (float)v.Y, (float)v.Z, (float)v.W); } DoomLevelMesh* LevelMesh = nullptr; + bool StaticMesh = true; }; static_assert(alignof(FVector2) == alignof(float[2]) && sizeof(FVector2) == sizeof(float) * 2); diff --git a/src/rendering/hwrenderer/hw_vertexbuilder.cpp b/src/rendering/hwrenderer/hw_vertexbuilder.cpp index c7f6ddbca..edca6e113 100644 --- a/src/rendering/hwrenderer/hw_vertexbuilder.cpp +++ b/src/rendering/hwrenderer/hw_vertexbuilder.cpp @@ -246,7 +246,7 @@ static int CreateIndexedSectorVerticesLM(FRenderState& renderstate, sector_t* se DoomLevelMeshSurface* lightmap = sub->surface[h].Size() > lightmapIndex ? sub->surface[h][lightmapIndex] : nullptr; if (lightmap && lightmap->Type != ST_NONE) // surface may be missing if the subsector is degenerate triangle { - FFlatVertex* luvs = lightmap->Vertices; + FFlatVertex* luvs = &lightmap->Submesh->Mesh.Vertices[lightmap->MeshLocation.StartVertIndex]; for (unsigned int j = 0; j < sub->numlines; j++) { SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline[j].v1, plane, luvs[j].lu, luvs[j].lv, luvs[j].lindex); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index ffdf56253..78e6557d9 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -541,7 +541,7 @@ void HWDrawInfo::UpdateLightmaps() { for (auto& e : static_cast(level.levelMesh->StaticMesh.get())->Surfaces) { - if (e.NeedsUpdate && !e.bSky && !e.portalIndex) + if (e.NeedsUpdate && !e.IsSky && !e.PortalIndex) { VisibleSurfaces.Push(&e); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 1bf0d70f8..ccd20b523 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -241,7 +241,7 @@ public: return; } - if (surface->NeedsUpdate && !surface->portalIndex && !surface->bSky) + if (surface->NeedsUpdate && !surface->PortalIndex && !surface->IsSky) { VisibleSurfaces.Push(surface); } diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 7189226fd..ca75e3da1 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -910,13 +910,14 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto } texcoord srclightuv[4]; - if (surface && surface->Type != ST_NONE && surface->numVerts != 0) + if (surface && surface->Type != ST_NONE && surface->MeshLocation.NumVerts >= 4) { - srclightuv[0] = { surface->Vertices[0].lu, surface->Vertices[0].lv }; - srclightuv[1] = { surface->Vertices[1].lu, surface->Vertices[1].lv }; - srclightuv[2] = { surface->Vertices[2].lu, surface->Vertices[2].lv }; - srclightuv[3] = { surface->Vertices[3].lu, surface->Vertices[3].lv }; - lindex = surface->Vertices[0].lindex; + FFlatVertex* vertices = &surface->Submesh->Mesh.Vertices[surface->MeshLocation.StartVertIndex]; + srclightuv[0] = { vertices[0].lu, vertices[0].lv }; + srclightuv[1] = { vertices[1].lu, vertices[1].lv }; + srclightuv[2] = { vertices[2].lu, vertices[2].lv }; + srclightuv[3] = { vertices[3].lu, vertices[3].lv }; + lindex = vertices[0].lindex; } else { @@ -1674,11 +1675,12 @@ void HWWall::BuildFFBlock(HWWallDispatcher *di, FRenderState& state, seg_t * seg texcoord srclightuv[4]; if (surface && surface->Type != ST_NONE) { - srclightuv[0] = { surface->Vertices[0].lu, surface->Vertices[0].lv }; - srclightuv[1] = { surface->Vertices[1].lu, surface->Vertices[1].lv }; - srclightuv[2] = { surface->Vertices[2].lu, surface->Vertices[2].lv }; - srclightuv[3] = { surface->Vertices[3].lu, surface->Vertices[3].lv }; - lindex = surface->Vertices[0].lindex; + FFlatVertex* vertices = &surface->Submesh->Mesh.Vertices[surface->MeshLocation.StartVertIndex]; + srclightuv[0] = { vertices[0].lu, vertices[0].lv }; + srclightuv[1] = { vertices[1].lu, vertices[1].lv }; + srclightuv[2] = { vertices[2].lu, vertices[2].lv }; + srclightuv[3] = { vertices[3].lu, vertices[3].lv }; + lindex = vertices[0].lindex; } else {