From 45206f2184e2640aec2a027133a318bf1d537f9e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 1 Sep 2023 00:13:22 +0200 Subject: [PATCH] Move surface linking into DoomLevelMesh --- src/maploader/maploader.cpp | 292 +------------------- src/maploader/maploader.h | 11 - src/rendering/hwrenderer/doom_levelmesh.cpp | 120 ++++++++ src/rendering/hwrenderer/doom_levelmesh.h | 4 + 4 files changed, 129 insertions(+), 298 deletions(-) diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index c22550987f..aad91c5e4d 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -3204,15 +3204,12 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) SpawnThings(position); - // Load and link lightmaps - must be done after P_Spawn3DFloors (and SpawnThings? Potentially for baking static model actors?) -#if 0 - if (!ForceNodeBuild) - { - LoadLightmap(map); - } -#endif + // TODO read from ZDRayInfoThing + Level->SunColor = FVector3(1.f, 1.f, 1.f); + Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f); + Level->levelMesh = new DoomLevelMesh(*Level); - InitLightmap(map); + Level->lightmaps = true; for (int i = 0; i < MAXPLAYERS; ++i) { @@ -3266,282 +3263,3 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) Level->aabbTree = new DoomLevelAABBTree(Level); } - -//========================================================================== -// -// -// -//========================================================================== - - -void MapLoader::SetSubsectorLightmap(const LightmapSurface &surface) -{ - if (!surface.ControlSector) - { - int index = surface.Type == hwrenderer::ST_CEILING ? 1 : 0; - surface.Subsector->lightmap[index][0] = surface; - } - else - { - int index = surface.Type == hwrenderer::ST_CEILING ? 0 : 1; - const auto &ffloors = surface.Subsector->sector->e->XFloor.ffloors; - for (unsigned int i = 0; i < ffloors.Size(); i++) - { - if (ffloors[i]->model == surface.ControlSector) - { - surface.Subsector->lightmap[index][i + 1] = surface; - } - } - } -} - -void MapLoader::SetSideLightmap(const LightmapSurface &surface) -{ - if (!surface.ControlSector) - { - if (surface.Type == hwrenderer::ST_UPPERSIDE) - { - surface.Side->lightmap[0] = surface; - } - else if (surface.Type == hwrenderer::ST_MIDDLESIDE) - { - surface.Side->lightmap[1] = surface; - surface.Side->lightmap[2] = surface; - } - else if (surface.Type == hwrenderer::ST_LOWERSIDE) - { - surface.Side->lightmap[3] = surface; - } - } - else - { - const auto &ffloors = surface.Side->sector->e->XFloor.ffloors; - for (unsigned int i = 0; i < ffloors.Size(); i++) - { - if (ffloors[i]->model == surface.ControlSector) - { - surface.Side->lightmap[4 + i] = surface; - } - } - } -} - -void MapLoader::BindLightmapSurfacesToGeometry() -{ - // Allocate room for all surfaces - - unsigned int allSurfaces = 0; - - for (unsigned int i = 0; i < Level->sides.Size(); i++) - allSurfaces += 4 + Level->sides[i].sector->e->XFloor.ffloors.Size(); - - for (unsigned int i = 0; i < Level->subsectors.Size(); i++) - allSurfaces += 2 + Level->subsectors[i].sector->e->XFloor.ffloors.Size() * 2; - - Level->LMSurfaces.Resize(allSurfaces); - memset(&Level->LMSurfaces[0], 0, sizeof(LightmapSurface) * allSurfaces); - - // Link the surfaces to sectors, sides and their 3D floors - - unsigned int offset = 0; - for (unsigned int i = 0; i < Level->sides.Size(); i++) - { - auto& side = Level->sides[i]; - side.lightmap = &Level->LMSurfaces[offset]; - offset += 4 + side.sector->e->XFloor.ffloors.Size(); - } - for (unsigned int i = 0; i < Level->subsectors.Size(); i++) - { - auto& subsector = Level->subsectors[i]; - unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size(); - subsector.lightmap[0] = &Level->LMSurfaces[offset]; - subsector.lightmap[1] = &Level->LMSurfaces[offset + count]; - offset += count * 2; - } - - // Copy and build properties - size_t index = 0; - for (auto& surface : Level->levelMesh->Surfaces) - { - LightmapSurface l; - memset(&l, 0, sizeof(LightmapSurface)); - - l.ControlSector = (sector_t*)surface.controlSector; - l.Type = surface.type; - l.LightmapNum = 0; - - l.TexCoords = (float*) & Level->levelMesh->LightmapUvs[surface.startUvIndex]; - - l.LightmapNum = surface.atlasPageIndex; - - if (surface.type == hwrenderer::ST_FLOOR || surface.type == hwrenderer::ST_CEILING) - { - l.Subsector = &Level->subsectors[surface.typeIndex]; - if (l.Subsector->firstline && l.Subsector->firstline->sidedef) - l.Subsector->firstline->sidedef->sector->HasLightmaps = true; - SetSubsectorLightmap(l); - } - else - { - l.Side = &Level->sides[surface.typeIndex]; - SetSideLightmap(l); - } - } - -} - -void MapLoader::InitLightmap(MapData* map) -{ - // We have to reset everything as FLevelLocals is recycled between maps - Level->LMSurfaces.Reset(); - - // TODO read from ZDRayInfoThing - Level->SunColor = FVector3(1.f, 1.f, 1.f); - Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f); - - Level->levelMesh->SunColor = Level->SunColor; // TODO keep only one copy? - Level->levelMesh->SunDirection = Level->SunDirection; - - Level->lightmaps = true; - - BindLightmapSurfacesToGeometry(); -} - -#if 0 -void MapLoader::LoadLightmap(MapData *map) -{ - Level->LMTexCoords.Reset(); - Level->LMSurfaces.Reset(); - Level->LMTextureData.Reset(); - Level->LMTextureCount = 0; - Level->LMTextureSize = 0; - - // We have to reset everything as FLevelLocals is recycled between maps - - //if (!Args->CheckParm("-enablelightmaps")) - // return; // this feature is still too early WIP to allow general access - - if (!map->Size(ML_LIGHTMAP)) - return; - - FileReader fr; - if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB, false, false)) - return; - - - 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; - } - if (version != 1) - { - Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n"); - return; - } - - uint16_t textureSize = fr.ReadUInt16(); - uint16_t numTextures = fr.ReadUInt16(); - uint32_t numSurfaces = fr.ReadUInt32(); - uint32_t numTexCoords = fr.ReadUInt32(); - uint32_t numSubsectors = fr.ReadUInt32(); - uint32_t numTexBytes = numTextures * textureSize * textureSize * 3 * 2; - if (numSurfaces == 0 || numTexCoords == 0 || numTexBytes == 0) - return; - - float sunDir[3], sunColor[3]; - fr.Read(sunDir, sizeof(float) * 3); - fr.Read(sunColor, sizeof(float) * 3); - Level->SunDirection = FVector3(sunDir); - Level->SunColor = FVector3(sunColor); - - /*if (numSubsectors != Level->subsectors.Size()) - { - Printf(PRINT_HIGH, "LoadLightmap: subsector count for level doesn't match (%d in wad vs %d in engine)\n", (int)numSubsectors, (int)Level->subsectors.Size()); - }*/ - - Level->LMTexCoords.Resize(numTexCoords * 2); - - // Allocate room for all surfaces - - unsigned int allSurfaces = 0; - - for (unsigned int i = 0; i < Level->sides.Size(); i++) - allSurfaces += 4 + Level->sides[i].sector->e->XFloor.ffloors.Size(); - - for (unsigned int i = 0; i < Level->subsectors.Size(); i++) - allSurfaces += 2 + Level->subsectors[i].sector->e->XFloor.ffloors.Size() * 2; - - Level->LMSurfaces.Resize(allSurfaces); - memset(&Level->LMSurfaces[0], 0, sizeof(LightmapSurface) * allSurfaces); - - // Link the surfaces to sectors, sides and their 3D floors - - unsigned int offset = 0; - for (unsigned int i = 0; i < Level->sides.Size(); i++) - { - auto& side = Level->sides[i]; - side.lightmap = &Level->LMSurfaces[offset]; - offset += 4 + side.sector->e->XFloor.ffloors.Size(); - } - for (unsigned int i = 0; i < Level->subsectors.Size(); i++) - { - auto& subsector = Level->subsectors[i]; - unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size(); - subsector.lightmap[0] = &Level->LMSurfaces[offset]; - subsector.lightmap[1] = &Level->LMSurfaces[offset + count]; - offset += count * 2; - } - - // Load the surfaces we have lightmap data for - - for (uint32_t i = 0; i < numSurfaces; i++) - { - LightmapSurface surface; - memset(&surface, 0, sizeof(LightmapSurface)); - - SurfaceType type = (SurfaceType)fr.ReadUInt32(); - uint32_t typeIndex = fr.ReadUInt32(); - uint32_t controlSector = fr.ReadUInt32(); - uint32_t lightmapNum = fr.ReadUInt32(); - uint32_t firstTexCoord = fr.ReadUInt32(); - - if (controlSector != 0xffffffff) - surface.ControlSector = &Level->sectors[controlSector]; - - surface.Type = type; - surface.LightmapNum = lightmapNum; - surface.TexCoords = &Level->LMTexCoords[firstTexCoord * 2]; - - if (type == ST_CEILING || type == ST_FLOOR) - { - surface.Subsector = &Level->subsectors[typeIndex]; - surface.Subsector->firstline->sidedef->sector->HasLightmaps = true; - SetSubsectorLightmap(surface); - } - else if (type != ST_NULL) - { - surface.Side = &Level->sides[typeIndex]; - SetSideLightmap(surface); - } - } - - // Load texture coordinates - - fr.Read(&Level->LMTexCoords[0], numTexCoords * 2 * sizeof(float)); - - // Load lightmap textures - - Level->LMTextureCount = numTextures; - Level->LMTextureSize = textureSize; - Level->LMTextureData.Resize((numTexBytes + 1) / 2); - uint8_t* data = (uint8_t*)&Level->LMTextureData[0]; - fr.Read(data, numTexBytes); -#if 0 - // Apply compression predictor - for (uint32_t i = 1; i < numTexBytes; i++) - data[i] += data[i - 1]; -#endif -} -#endif \ No newline at end of file diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index a39e2c69de..79beb6aeea 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -304,17 +304,6 @@ public: void SetSlopes(); void CopySlopes(); - void SetSubsectorLightmap(const LightmapSurface &surface); - void SetSideLightmap(const LightmapSurface &surface); - - // Lightmap -#if 0 - void LoadLightmap(MapData *map); -#endif - void InitLightmap(MapData* map); - void BindLightmapSurfacesToGeometry(); - - void LoadLevel(MapData *map, const char *lumpname, int position); MapLoader(FLevelLocals *lev) diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 213e5670ed..2cc960ac42 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -30,6 +30,9 @@ CCMD(dumplevelmesh) DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap) { + SunColor = doomMap.SunColor; // TODO keep only one copy? + SunDirection = doomMap.SunDirection; + for (unsigned int i = 0; i < doomMap.sides.Size(); i++) { CreateSideSurfaces(doomMap, &doomMap.sides[i]); @@ -81,9 +84,126 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap) } } + BindLightmapSurfacesToGeometry(doomMap); + Collision = std::make_unique(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size()); } +void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap) +{ + // Allocate room for all surfaces + + unsigned int allSurfaces = 0; + + for (unsigned int i = 0; i < doomMap.sides.Size(); i++) + allSurfaces += 4 + doomMap.sides[i].sector->e->XFloor.ffloors.Size(); + + for (unsigned int i = 0; i < doomMap.subsectors.Size(); i++) + allSurfaces += 2 + doomMap.subsectors[i].sector->e->XFloor.ffloors.Size() * 2; + + doomMap.LMSurfaces.Resize(allSurfaces); + memset(&doomMap.LMSurfaces[0], 0, sizeof(LightmapSurface) * allSurfaces); + + // Link the surfaces to sectors, sides and their 3D floors + + unsigned int offset = 0; + for (unsigned int i = 0; i < doomMap.sides.Size(); i++) + { + auto& side = doomMap.sides[i]; + side.lightmap = &doomMap.LMSurfaces[offset]; + offset += 4 + side.sector->e->XFloor.ffloors.Size(); + } + for (unsigned int i = 0; i < doomMap.subsectors.Size(); i++) + { + auto& subsector = doomMap.subsectors[i]; + unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size(); + subsector.lightmap[0] = &doomMap.LMSurfaces[offset]; + subsector.lightmap[1] = &doomMap.LMSurfaces[offset + count]; + offset += count * 2; + } + + // Copy and build properties + size_t index = 0; + for (auto& surface : doomMap.levelMesh->Surfaces) + { + LightmapSurface l; + memset(&l, 0, sizeof(LightmapSurface)); + + l.ControlSector = (sector_t*)surface.controlSector; + l.Type = surface.type; + l.LightmapNum = 0; + + l.TexCoords = (float*)&doomMap.levelMesh->LightmapUvs[surface.startUvIndex]; + + l.LightmapNum = surface.atlasPageIndex; + + if (surface.type == hwrenderer::ST_FLOOR || surface.type == hwrenderer::ST_CEILING) + { + l.Subsector = &doomMap.subsectors[surface.typeIndex]; + if (l.Subsector->firstline && l.Subsector->firstline->sidedef) + l.Subsector->firstline->sidedef->sector->HasLightmaps = true; + SetSubsectorLightmap(l); + } + else + { + l.Side = &doomMap.sides[surface.typeIndex]; + SetSideLightmap(l); + } + } +} + +void DoomLevelMesh::SetSubsectorLightmap(const LightmapSurface& surface) +{ + if (!surface.ControlSector) + { + int index = surface.Type == hwrenderer::ST_CEILING ? 1 : 0; + surface.Subsector->lightmap[index][0] = surface; + } + else + { + int index = surface.Type == hwrenderer::ST_CEILING ? 0 : 1; + const auto& ffloors = surface.Subsector->sector->e->XFloor.ffloors; + for (unsigned int i = 0; i < ffloors.Size(); i++) + { + if (ffloors[i]->model == surface.ControlSector) + { + surface.Subsector->lightmap[index][i + 1] = surface; + } + } + } +} + +void DoomLevelMesh::SetSideLightmap(const LightmapSurface& surface) +{ + if (!surface.ControlSector) + { + if (surface.Type == hwrenderer::ST_UPPERSIDE) + { + surface.Side->lightmap[0] = surface; + } + else if (surface.Type == hwrenderer::ST_MIDDLESIDE) + { + surface.Side->lightmap[1] = surface; + surface.Side->lightmap[2] = surface; + } + else if (surface.Type == hwrenderer::ST_LOWERSIDE) + { + surface.Side->lightmap[3] = surface; + } + } + else + { + const auto& ffloors = surface.Side->sector->e->XFloor.ffloors; + for (unsigned int i = 0; i < ffloors.Size(); i++) + { + if (ffloors[i]->model == surface.ControlSector) + { + surface.Side->lightmap[4 + i] = surface; + } + } + } +} + void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side) { sector_t *front; diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 7cd88ab2e0..f9f0f8b66e 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -42,6 +42,10 @@ private: void CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor); void CreateSideSurfaces(FLevelLocals &doomMap, side_t *side); + void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap); + void SetSubsectorLightmap(const LightmapSurface& surface); + void SetSideLightmap(const LightmapSurface& surface); + static bool IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side); static bool IsTopSideVisible(side_t* side); static bool IsBottomSideVisible(side_t* side);