Fix misc bugs related to the dynamic lightmap and polybsp lines in the lightmapper

This commit is contained in:
Magnus Norddahl 2023-10-02 02:40:40 +02:00
commit bcea260f33
7 changed files with 143 additions and 88 deletions

View file

@ -12,9 +12,10 @@
#include <dp_rect_pack.h>
typedef dp::rect_pack::RectPacker<int> RectPacker;
class LevelSubmesh;
class LevelMeshLight
{
public:
@ -31,6 +32,8 @@ public:
struct LevelMeshSurface
{
LevelSubmesh* Submesh = nullptr;
int numVerts = 0;
unsigned int startVertIndex = 0;
unsigned int startUvIndex = 0;

View file

@ -167,10 +167,18 @@ void VkLightmap::Render()
auto& selectedSurface = selectedSurfaces[i];
LevelMeshSurface* targetSurface = selectedSurface.Surface;
int surfaceIndexOffset = 0;
int firstIndexOffset = 0;
if (targetSurface->Submesh != mesh->StaticMesh.get())
{
surfaceIndexOffset = mesh->StaticMesh->GetSurfaceCount();
firstIndexOffset = mesh->StaticMesh->MeshElements.Size();
}
LightmapRaytracePC pc;
pc.TileX = (float)selectedSurface.X;
pc.TileY = (float)selectedSurface.Y;
pc.SurfaceIndex = mesh->StaticMesh->GetSurfaceIndex(targetSurface);
pc.SurfaceIndex = surfaceIndexOffset + targetSurface->Submesh->GetSurfaceIndex(targetSurface);
pc.TextureSize = (float)bakeImageSize;
pc.TileWidth = (float)targetSurface->AtlasTile.Width;
pc.TileHeight = (float)targetSurface->AtlasTile.Height;
@ -223,7 +231,7 @@ void VkLightmap::Render()
VkDrawIndexedIndirectCommand cmd;
cmd.indexCount = surface->numElements;
cmd.instanceCount = 1;
cmd.firstIndex = surface->startElementIndex;
cmd.firstIndex = firstIndexOffset + surface->startElementIndex;
cmd.vertexOffset = 0;
cmd.firstInstance = drawindexed.Pos;
drawindexed.Constants[drawindexed.Pos] = pc;

View file

@ -205,7 +205,8 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
*(vertices++) = { { submesh->MeshVertices[j], 1.0f }, submesh->MeshVertexUVs[j], float(j), j + 10000.0f };
size_t copysize = submesh->MeshVertices.Size() * sizeof(SurfaceVertex);
cmdbuffer->copyBuffer(transferBuffer.get(), VertexBuffer.get(), datapos, cur.VertexOffset * sizeof(SurfaceVertex), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), VertexBuffer.get(), datapos, cur.VertexOffset * sizeof(SurfaceVertex), copysize);
datapos += copysize;
}
@ -220,7 +221,8 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
*(indexes++) = cur.VertexOffset + submesh->MeshElements[j];
size_t copysize = submesh->MeshElements.Size() * sizeof(uint32_t);
cmdbuffer->copyBuffer(transferBuffer.get(), IndexBuffer.get(), datapos, cur.IndexOffset * sizeof(uint32_t), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), IndexBuffer.get(), datapos, cur.IndexOffset * sizeof(uint32_t), copysize);
datapos += copysize;
}
@ -243,7 +245,8 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
}
size_t copysize = submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
cmdbuffer->copyBuffer(transferBuffer.get(), NodeBuffer.get(), datapos, +sizeof(CollisionNodeBufferHeader) + cur.NodeOffset * sizeof(CollisionNode), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), NodeBuffer.get(), datapos, +sizeof(CollisionNodeBufferHeader) + cur.NodeOffset * sizeof(CollisionNode), copysize);
datapos += copysize;
}
@ -258,7 +261,8 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
*(indexes++) = cur.SurfaceIndexOffset + submesh->MeshSurfaceIndexes[j];
size_t copysize = submesh->MeshSurfaceIndexes.Size() * sizeof(int);
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceIndexBuffer.get(), datapos, cur.SurfaceIndexOffset * sizeof(int), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceIndexBuffer.get(), datapos, cur.SurfaceIndexOffset * sizeof(int), copysize);
datapos += copysize;
}
@ -293,7 +297,8 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
}
size_t copysize = submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceBuffer.get(), datapos, cur.SurfaceOffset * sizeof(SurfaceInfo), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceBuffer.get(), datapos, cur.SurfaceOffset * sizeof(SurfaceInfo), copysize);
datapos += copysize;
}
@ -309,7 +314,8 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
}
size_t copysize = Mesh->StaticMesh->Portals.Size() * sizeof(PortalInfo);
cmdbuffer->copyBuffer(transferBuffer.get(), PortalBuffer.get(), datapos, 0, copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), PortalBuffer.get(), datapos, 0, copysize);
datapos += copysize;
}

View file

@ -190,11 +190,11 @@ void VkTextureManager::CreateLightmap()
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData)
{
if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount && newPixelData.Size() == 0)
if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount + 1 && newPixelData.Size() == 0)
return;
LMTextureSize = newLMTextureSize;
LMTextureCount = newLMTextureCount;
LMTextureCount = newLMTextureCount + 1; // the extra texture is for the dynamic lightmap
int w = newLMTextureSize;
int h = newLMTextureSize;
@ -204,7 +204,7 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
Lightmap.Reset(fb);
Lightmap.Image = ImageBuilder()
.Size(w, h, 1, count)
.Size(w, h, 1, LMTextureCount)
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.DebugName("VkRenderBuffers.Lightmap")
@ -243,7 +243,7 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
stagingBuffer->Unmap();
VkImageTransition()
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, count)
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, LMTextureCount)
.Execute(cmdbuffer);
VkBufferImageCopy region = {};
@ -260,6 +260,6 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
}
VkImageTransition()
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, count)
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, LMTextureCount)
.Execute(cmdbuffer);
}

View file

@ -2994,6 +2994,35 @@ void MapLoader::InitLevelMesh(MapData* map)
Level->levelMesh->PackLightmapAtlas();
}
// Allocate room for lightmap arrays on sectors, sides and their 3D floors
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.Data(), 0, sizeof(DoomLevelMeshSurface*) * allSurfaces);
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;
}
Level->levelMesh->BindLightmapSurfacesToGeometry(*Level);
}
else

View file

@ -85,7 +85,7 @@ void PrintSurfaceInfo(const DoomLevelMeshSurface* surface)
auto gameTexture = TexMan.GameByIndex(surface->texture.GetIndex());
Printf("Surface %d (%p)\n Type: %d, TypeIndex: %d, ControlSector: %d\n", level.levelMesh->StaticMesh->GetSurfaceIndex(surface), surface, surface->Type, surface->TypeIndex, surface->ControlSector ? surface->ControlSector->Index() : -1);
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);
@ -152,7 +152,7 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
{
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->UpdateDynamic(doomMap);
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->UpdateDynamic(doomMap, static_cast<DoomLevelSubmesh*>(StaticMesh.get())->LMTextureCount);
}
bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float dist)
@ -164,7 +164,7 @@ bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float di
void DoomLevelMesh::PackLightmapAtlas()
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->PackLightmapAtlas();
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->PackLightmapAtlas(0);
}
void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
@ -193,7 +193,13 @@ int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLi
}
else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE)
{
if (!doomsurf->ControlSector)
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;
}
@ -282,6 +288,50 @@ void DoomLevelSubmesh::CreateStatic(FLevelLocals& doomMap)
UpdateCollision();
}
void DoomLevelSubmesh::CreateDynamic(FLevelLocals& doomMap)
{
LightmapSampleDistance = doomMap.LightmapSampleDistance;
BuildSectorGroups(doomMap);
}
void DoomLevelSubmesh::UpdateDynamic(FLevelLocals& doomMap, int lightmapStartIndex)
{
Surfaces.Clear();
MeshVertices.Clear();
MeshVertexUVs.Clear();
MeshElements.Clear();
MeshSurfaceIndexes.Clear();
LightmapUvs.Clear();
// Look for polyobjects
for (unsigned int i = 0; i < doomMap.lines.Size(); i++)
{
side_t* side = doomMap.lines[i].sidedef[0];
bool isPolyLine = !!(side->Flags & WALLF_POLYOBJ);
if (isPolyLine)
{
// Make sure we have a lightmap array on the polyobj sidedef
if (!side->lightmap)
{
auto array = std::make_unique<DoomLevelMeshSurface*[]>(4);
memset(array.get(), 0, sizeof(DoomLevelMeshSurface*));
side->lightmap = array.get();
PolyLMSurfaces.Push(std::move(array));
}
CreateSideSurfaces(doomMap, side);
}
}
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
PackLightmapAtlas(lightmapStartIndex);
BindLightmapSurfacesToGeometry(doomMap);
}
void DoomLevelSubmesh::CreateIndexes()
{
for (size_t i = 0; i < Surfaces.Size(); i++)
@ -330,34 +380,6 @@ void DoomLevelSubmesh::CreateIndexes()
}
}
void DoomLevelSubmesh::CreateDynamic(FLevelLocals& doomMap)
{
LightmapSampleDistance = doomMap.LightmapSampleDistance;
BuildSectorGroups(doomMap);
}
void DoomLevelSubmesh::UpdateDynamic(FLevelLocals& doomMap)
{
Surfaces.Clear();
MeshVertices.Clear();
MeshVertexUVs.Clear();
MeshElements.Clear();
MeshSurfaceIndexes.Clear();
LightmapUvs.Clear();
for (unsigned int i = 0; i < doomMap.lines.Size(); i++)
{
bool isPolyLine = doomMap.lines[i].sidedef[0] && (doomMap.lines[i].sidedef[0]->Flags & WALLF_POLYOBJ);
if (isPolyLine)
CreateSideSurfaces(doomMap, doomMap.lines[i].sidedef[0]);
}
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
}
void DoomLevelSubmesh::BuildSectorGroups(const FLevelLocals& doomMap)
{
int groupIndex = 0;
@ -539,44 +561,13 @@ void DoomLevelSubmesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
std::swap(LightmapUvs[surface.startUvIndex + 1], LightmapUvs[surface.startUvIndex + 2]);
std::swap(LightmapUvs[surface.startUvIndex + 2], LightmapUvs[surface.startUvIndex + 3]);
}
surface.TexCoords = (float*)&LightmapUvs[surface.startUvIndex];
}
// 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(DoomLevelMeshSurface*) * 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
// Link surfaces
for (auto& surface : Surfaces)
{
surface.TexCoords = (float*)&LightmapUvs[surface.startUvIndex];
if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING)
{
surface.Subsector = &doomMap.subsectors[surface.TypeIndex];
@ -667,6 +658,7 @@ void DoomLevelSubmesh::CreateLinePortalSurface(FLevelLocals& doomMap, side_t* si
verts[3].Z = v2Top;
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.Type = ST_MIDDLESIDE;
surf.TypeIndex = side->Index();
surf.bSky = front->GetTexture(sector_t::floor) == skyflatnum || front->GetTexture(sector_t::ceiling) == skyflatnum;
@ -751,6 +743,7 @@ void DoomLevelSubmesh::CreateLineHorizonSurface(FLevelLocals& doomMap, side_t* s
float v2Bottom = (float)front->floorplane.ZatPoint(v2);
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.Type = ST_MIDDLESIDE;
surf.TypeIndex = side->Index();
surf.bSky = front->GetTexture(sector_t::floor) == skyflatnum || front->GetTexture(sector_t::ceiling) == skyflatnum;
@ -784,7 +777,14 @@ void DoomLevelSubmesh::CreateLineHorizonSurface(FLevelLocals& doomMap, side_t* s
void DoomLevelSubmesh::CreateFrontWallSurface(FLevelLocals& doomMap, side_t* side)
{
sector_t* front = side->sector;
/*
bool isPolyLine = !!(side->Flags & WALLF_POLYOBJ);
if (isPolyLine)
{
subsector_t* subsector = level.PointInRenderSubsector((side->V1()->fPos() + side->V2()->fPos()) * 0.5);
front = subsector->sector;
}
*/
FVector2 v1 = ToFVector2(side->V1()->fPos());
FVector2 v2 = ToFVector2(side->V2()->fPos());
@ -804,6 +804,7 @@ void DoomLevelSubmesh::CreateFrontWallSurface(FLevelLocals& doomMap, side_t* sid
verts[3].Z = v2Top;
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.bSky = false;
surf.startVertIndex = MeshVertices.Size();
surf.numVerts = 4;
@ -883,6 +884,7 @@ void DoomLevelSubmesh::CreateMidWallSurface(FLevelLocals& doomMap, side_t* side)
// mid texture
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.bSky = false;
surf.startVertIndex = MeshVertices.Size();
surf.numVerts = 4;
@ -946,6 +948,7 @@ void DoomLevelSubmesh::Create3DFloorWallSurfaces(FLevelLocals& doomMap, side_t*
continue;
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.Type = ST_MIDDLESIDE;
surf.TypeIndex = side->Index();
surf.ControlSector = xfloor->model;
@ -1001,8 +1004,6 @@ void DoomLevelSubmesh::CreateTopWallSurface(FLevelLocals& doomMap, side_t* side)
if (!bSky && !IsTopSideVisible(side))
return;
DoomLevelMeshSurface surf;
FVector3 verts[4];
verts[0].X = verts[2].X = v1.X;
verts[0].Y = verts[2].Y = v1.Y;
@ -1013,6 +1014,8 @@ void DoomLevelSubmesh::CreateTopWallSurface(FLevelLocals& doomMap, side_t* side)
verts[2].Z = v1Top;
verts[3].Z = v2Top;
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.startVertIndex = MeshVertices.Size();
surf.numVerts = 4;
MeshVertices.Push(verts[0]);
@ -1050,8 +1053,6 @@ void DoomLevelSubmesh::CreateBottomWallSurface(FLevelLocals& doomMap, side_t* si
float v1BottomBack = (float)back->floorplane.ZatPoint(v1);
float v2BottomBack = (float)back->floorplane.ZatPoint(v2);
DoomLevelMeshSurface surf;
FVector3 verts[4];
verts[0].X = verts[2].X = v1.X;
verts[0].Y = verts[2].Y = v1.Y;
@ -1062,6 +1063,8 @@ void DoomLevelSubmesh::CreateBottomWallSurface(FLevelLocals& doomMap, side_t* si
verts[2].Z = v1BottomBack;
verts[3].Z = v2BottomBack;
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.startVertIndex = MeshVertices.Size();
surf.numVerts = 4;
MeshVertices.Push(verts[0]);
@ -1124,6 +1127,7 @@ void DoomLevelSubmesh::SetSideTextureUVs(DoomLevelMeshSurface& surface, side_t*
void DoomLevelSubmesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, sector_t *controlSector, int typeIndex)
{
DoomLevelMeshSurface surf;
surf.Submesh = this;
secplane_t plane;
if (!controlSector)
@ -1178,6 +1182,7 @@ void DoomLevelSubmesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *su
void DoomLevelSubmesh::CreateCeilingSurface(FLevelLocals& doomMap, subsector_t* sub, sector_t* sector, sector_t* controlSector, int typeIndex)
{
DoomLevelMeshSurface surf;
surf.Submesh = this;
secplane_t plane;
if (!controlSector)
@ -1415,7 +1420,7 @@ void DoomLevelSubmesh::SetupLightmapUvs(FLevelLocals& doomMap)
}
}
void DoomLevelSubmesh::PackLightmapAtlas()
void DoomLevelSubmesh::PackLightmapAtlas(int lightmapStartIndex)
{
std::vector<LevelMeshSurface*> sortedSurfaces;
sortedSurfaces.reserve(Surfaces.Size());
@ -1439,7 +1444,7 @@ void DoomLevelSubmesh::PackLightmapAtlas()
surf->AtlasTile.X = x;
surf->AtlasTile.Y = y;
surf->AtlasTile.ArrayIndex = (int)result.pageIndex;
surf->AtlasTile.ArrayIndex = lightmapStartIndex + (int)result.pageIndex;
// calculate final texture coordinates
for (int i = 0; i < (int)surf->numVerts; i++)

View file

@ -12,6 +12,7 @@
typedef dp::rect_pack::RectPacker<int> RectPacker;
struct FLevelLocals;
struct FPolyObj;
enum DoomLevelMeshSurfaceType
{
@ -31,6 +32,7 @@ struct DoomLevelMeshSurface : public LevelMeshSurface
subsector_t* Subsector = nullptr;
side_t* Side = nullptr;
sector_t* ControlSector = nullptr;
float* TexCoords = nullptr;
};
@ -39,7 +41,7 @@ class DoomLevelSubmesh : public LevelSubmesh
public:
void CreateStatic(FLevelLocals& doomMap);
void CreateDynamic(FLevelLocals& doomMap);
void UpdateDynamic(FLevelLocals& doomMap);
void UpdateDynamic(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<const DoomLevelMeshSurface*>(surface) - Surfaces.Data()); }
@ -49,7 +51,7 @@ public:
// Used by Maploader
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap);
void PackLightmapAtlas();
void PackLightmapAtlas(int lightmapStartIndex);
void CreatePortals();
void DisableLightmaps() { Surfaces.Clear(); } // Temp hack that disables lightmapping
@ -57,6 +59,8 @@ public:
TArray<FVector2> LightmapUvs;
TArray<int> sectorGroup; // index is sector, value is sectorGroup
TArray<std::unique_ptr<DoomLevelMeshSurface*[]>> PolyLMSurfaces;
private:
void BuildSectorGroups(const FLevelLocals& doomMap);