diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 4268880b17..7ebd5dd387 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -2984,7 +2984,11 @@ void MapLoader::InitLevelMesh(MapData* map) if (Level->lightmaps) { - LoadLightmap(map); + if (!LoadLightmap(map)) + { + Level->levelMesh->PackLightmapAtlas(); + } + Level->levelMesh->BindLightmapSurfacesToGeometry(*Level); } else @@ -2993,30 +2997,30 @@ void MapLoader::InitLevelMesh(MapData* map) } } -void MapLoader::LoadLightmap(MapData* map) +bool MapLoader::LoadLightmap(MapData* map) { if (!map->Size(ML_LIGHTMAP)) - return; + return false; FileReader fr; if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB, false, true)) - return; + return false; int version = fr.ReadInt32(); if (version == 0) { Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported alpha version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n"); - return; + return false; } if (version == 1) { Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n"); - return; + return false; } if (version != 2) { Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n"); - return; + return false; } uint32_t numSurfaces = fr.ReadUInt32(); @@ -3029,7 +3033,7 @@ void MapLoader::LoadLightmap(MapData* map) } if (numSurfaces == 0 || numTexCoords == 0 || numTexPixels == 0) - return; + return false; bool errors = false; @@ -3073,7 +3077,8 @@ void MapLoader::LoadLightmap(MapData* map) }; TMap detectedSurfaces; - TArray zdraySurfaces; // TODO reserve ahead of time 'numSurfaces' + TArray zdraySurfaces; + zdraySurfaces.Reserve(numSurfaces); for (auto& surface : Level->levelMesh->Surfaces) { @@ -3092,6 +3097,7 @@ void MapLoader::LoadLightmap(MapData* map) } } + uint32_t usedSurfaceIndex = 0; for (uint32_t i = 0; i < numSurfaces; i++) { SurfaceEntry surface; @@ -3160,12 +3166,19 @@ void MapLoader::LoadLightmap(MapData* map) } else { + levelSurface->texWidth = surface.width; + levelSurface->texHeight = surface.height; + surface.targetSurface = levelSurface; detectedSurfaces.Insert(levelSurface, 1); - zdraySurfaces.Push(surface); + zdraySurfaces[usedSurfaceIndex++] = surface; } } + Level->levelMesh->PackLightmapAtlas(); + + zdraySurfaces.Resize(usedSurfaceIndex); + if (developer >= 1) { Printf("Lightmap contains %d surfaces out of which %d were successfully matched.\n", numSurfaces, zdraySurfaces.Size()); @@ -3310,7 +3323,7 @@ void MapLoader::LoadLightmap(MapData* map) // Use UVs from the lightmap for (auto& surface : zdraySurfaces) { - auto& realSurface = Level->levelMesh->Surfaces[findSurfaceIndex(surface.type, surface.typeIndex, getControlSector(surface.controlSector))]; + auto& realSurface = *surface.targetSurface; auto* UVs = &Level->levelMesh->LightmapUvs[realSurface.startUvIndex]; auto* newUVs = &zdrayUvs[surface.uvOffset]; diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index 3dcbddc182..90cccf87a2 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -305,7 +305,7 @@ public: void CopySlopes(); void InitLevelMesh(MapData* map); - void LoadLightmap(MapData* map); + bool LoadLightmap(MapData* map); void LoadLevel(MapData *map, const char *lumpname, int position); diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 800bbbe4ae..74a8204ad8 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -1070,17 +1070,24 @@ void DoomLevelMesh::SetupLightmapUvs() { LMTextureSize = 1024; // TODO cvar + for (auto& surface : Surfaces) + { + BuildSurfaceParams(LMTextureSize, LMTextureSize, surface); + } + + BuildSmoothingGroups(); +} + +void DoomLevelMesh::PackLightmapAtlas() +{ std::vector sortedSurfaces; sortedSurfaces.reserve(Surfaces.Size()); for (auto& surface : Surfaces) { - BuildSurfaceParams(LMTextureSize, LMTextureSize, surface); sortedSurfaces.push_back(&surface); } - BuildSmoothingGroups(); - std::sort(sortedSurfaces.begin(), sortedSurfaces.end(), [](LevelMeshSurface* a, LevelMeshSurface* b) { return a->texHeight != b->texHeight ? a->texHeight > b->texHeight : a->texWidth > b->texWidth; }); RectPacker packer(LMTextureSize, LMTextureSize, RectPacker::Spacing(0)); diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index aa9c4d8831..43360ff78a 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -30,6 +30,7 @@ public: void CreatePortals(); void DumpMesh(const FString& objFilename, const FString& mtlFilename) const; void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap); + void PackLightmapAtlas(); bool TraceSky(const FVector3& start, FVector3 direction, float dist) { diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 34b2b968e5..f67c9bb8da 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -214,7 +214,7 @@ struct HWDrawInfo { surface->needsUpdate = true; } - else if (VisibleSurfaces.Size() >= lm_max_updates) + else if (VisibleSurfaces.Size() >= unsigned(lm_max_updates)) { return; }