Change how visible surfaces for a tile are collected by the light mapper
This commit is contained in:
parent
5a1c8131c5
commit
d2958d8366
7 changed files with 66 additions and 84 deletions
|
|
@ -148,75 +148,6 @@ struct LevelMeshPlaneGroup
|
|||
std::vector<LevelMeshSurface*> surfaces;
|
||||
};
|
||||
|
||||
void LevelMesh::BuildTileSurfaceLists()
|
||||
{
|
||||
// Plane group surface is to be rendered with
|
||||
TArray<LevelMeshPlaneGroup> PlaneGroups;
|
||||
TArray<int> PlaneGroupIndexes(Mesh.Surfaces.Size());
|
||||
|
||||
for (int i = 0, count = Mesh.Surfaces.Size(); i < count; i++)
|
||||
{
|
||||
auto surface = &Mesh.Surfaces[i];
|
||||
|
||||
// Is this surface in the same plane as an existing plane group?
|
||||
int planeGroupIndex = -1;
|
||||
|
||||
for (size_t j = 0; j < PlaneGroups.Size(); j++)
|
||||
{
|
||||
if (surface->SectorGroup == PlaneGroups[j].sectorGroup)
|
||||
{
|
||||
float direction = PlaneGroups[j].plane.XYZ() | surface->Plane.XYZ();
|
||||
if (direction >= 0.999f && direction <= 1.01f)
|
||||
{
|
||||
auto point = (surface->Plane.XYZ() * surface->Plane.W);
|
||||
auto planeDistance = (PlaneGroups[j].plane.XYZ() | point) - PlaneGroups[j].plane.W;
|
||||
|
||||
float dist = std::abs(planeDistance);
|
||||
if (dist <= 0.1f)
|
||||
{
|
||||
planeGroupIndex = (int)j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Surface is in a new plane. Create a plane group for it
|
||||
if (planeGroupIndex == -1)
|
||||
{
|
||||
planeGroupIndex = PlaneGroups.Size();
|
||||
|
||||
LevelMeshPlaneGroup group;
|
||||
group.plane = surface->Plane;
|
||||
group.sectorGroup = surface->SectorGroup;
|
||||
PlaneGroups.Push(group);
|
||||
}
|
||||
|
||||
PlaneGroups[planeGroupIndex].surfaces.push_back(surface);
|
||||
PlaneGroupIndexes.Push(planeGroupIndex);
|
||||
}
|
||||
|
||||
for (auto& tile : LightmapTiles)
|
||||
tile.Surfaces.Clear();
|
||||
|
||||
for (int i = 0, count = Mesh.Surfaces.Size(); i < count; i++)
|
||||
{
|
||||
LevelMeshSurface* targetSurface = &Mesh.Surfaces[i];
|
||||
if (targetSurface->LightmapTileIndex < 0)
|
||||
continue;
|
||||
LightmapTile* tile = &LightmapTiles[targetSurface->LightmapTileIndex];
|
||||
for (LevelMeshSurface* surface : PlaneGroups[PlaneGroupIndexes[i]].surfaces)
|
||||
{
|
||||
FVector2 minUV = tile->ToUV(surface->Bounds.min);
|
||||
FVector2 maxUV = tile->ToUV(surface->Bounds.max);
|
||||
if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f))
|
||||
continue; // Bounding box not visible
|
||||
|
||||
tile->Surfaces.Push((unsigned int)(ptrdiff_t)(surface - Mesh.Surfaces.Data()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LevelMesh::SetupTileTransforms()
|
||||
{
|
||||
for (auto& tile : LightmapTiles)
|
||||
|
|
@ -227,6 +158,8 @@ void LevelMesh::SetupTileTransforms()
|
|||
|
||||
void LevelMesh::PackLightmapAtlas(int lightmapStartIndex)
|
||||
{
|
||||
LMAtlasPacked = true;
|
||||
|
||||
std::vector<LightmapTile*> sortedTiles;
|
||||
sortedTiles.reserve(LightmapTiles.Size());
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ public:
|
|||
// Sets the sizes of all the GPU buffers and empties the mesh
|
||||
virtual void Reset(const LevelMeshLimits& limits);
|
||||
|
||||
virtual void GetVisibleSurfaces(LightmapTile* tile, TArray<int>& outSurfaces) { }
|
||||
|
||||
// Data placed in GPU buffers
|
||||
struct
|
||||
{
|
||||
|
|
@ -171,6 +173,7 @@ public:
|
|||
uint16_t LightmapSampleDistance = 16;
|
||||
|
||||
TArray<LightmapTile> LightmapTiles;
|
||||
bool LMAtlasPacked = false; // Tile sizes can't be changed anymore
|
||||
|
||||
uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
|
||||
|
||||
|
|
|
|||
|
|
@ -44,9 +44,6 @@ struct LightmapTile
|
|||
|
||||
LightmapTileBinding Binding;
|
||||
|
||||
// Surfaces that are visible within the lightmap tile
|
||||
TArray<int> Surfaces;
|
||||
|
||||
BBox Bounds;
|
||||
uint16_t SampleDimension = 0;
|
||||
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
||||
|
|
|
|||
|
|
@ -194,7 +194,10 @@ void VkLightmapper::Render()
|
|||
bool buffersFull = false;
|
||||
|
||||
// Paint all surfaces visible in the tile
|
||||
for (int surfaceIndex : targetTile->Surfaces)
|
||||
|
||||
visibleSurfaces.Clear();
|
||||
mesh->GetVisibleSurfaces(targetTile, visibleSurfaces);
|
||||
for (int surfaceIndex : visibleSurfaces)
|
||||
{
|
||||
LevelMeshSurface* surface = &mesh->Mesh.Surfaces[surfaceIndex];
|
||||
pc.SurfaceIndex = surfaceIndex;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,8 @@ private:
|
|||
TArray<SelectedTile> selectedTiles;
|
||||
TArray<TArray<SelectedTile*>> copylists;
|
||||
|
||||
TArray<int> visibleSurfaces;
|
||||
|
||||
struct
|
||||
{
|
||||
std::unique_ptr<VulkanBuffer> Buffer;
|
||||
|
|
|
|||
|
|
@ -171,8 +171,6 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
|
|||
CreatePortals(doomMap);
|
||||
CreateSurfaces(doomMap);
|
||||
|
||||
BuildTileSurfaceLists();
|
||||
|
||||
UpdateCollision();
|
||||
Mesh.MaxNodes = std::max(Collision->get_nodes().size() * 2, (size_t)10000);
|
||||
|
||||
|
|
@ -921,19 +919,25 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomSurfaceInfo& info, const LevelMesh
|
|||
{
|
||||
int index = it->second;
|
||||
|
||||
LightmapTile& tile = LightmapTiles[index];
|
||||
tile.Bounds.min.X = std::min(tile.Bounds.min.X, surf.Bounds.min.X);
|
||||
tile.Bounds.min.Y = std::min(tile.Bounds.min.Y, surf.Bounds.min.Y);
|
||||
tile.Bounds.min.Z = std::min(tile.Bounds.min.Z, surf.Bounds.min.Z);
|
||||
tile.Bounds.max.X = std::max(tile.Bounds.max.X, surf.Bounds.max.X);
|
||||
tile.Bounds.max.Y = std::max(tile.Bounds.max.Y, surf.Bounds.max.Y);
|
||||
tile.Bounds.max.Z = std::max(tile.Bounds.max.Z, surf.Bounds.max.Z);
|
||||
tile.AlwaysUpdate = tile.AlwaysUpdate || alwaysUpdate;
|
||||
if (!LMAtlasPacked)
|
||||
{
|
||||
LightmapTile& tile = LightmapTiles[index];
|
||||
tile.Bounds.min.X = std::min(tile.Bounds.min.X, surf.Bounds.min.X);
|
||||
tile.Bounds.min.Y = std::min(tile.Bounds.min.Y, surf.Bounds.min.Y);
|
||||
tile.Bounds.min.Z = std::min(tile.Bounds.min.Z, surf.Bounds.min.Z);
|
||||
tile.Bounds.max.X = std::max(tile.Bounds.max.X, surf.Bounds.max.X);
|
||||
tile.Bounds.max.Y = std::max(tile.Bounds.max.Y, surf.Bounds.max.Y);
|
||||
tile.Bounds.max.Z = std::max(tile.Bounds.max.Z, surf.Bounds.max.Z);
|
||||
tile.AlwaysUpdate = tile.AlwaysUpdate || alwaysUpdate;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LMAtlasPacked)
|
||||
return -1;
|
||||
|
||||
int index = LightmapTiles.Size();
|
||||
|
||||
LightmapTile tile;
|
||||
|
|
@ -1237,6 +1241,45 @@ BBox DoomLevelMesh::GetBoundsFromSurface(const LevelMeshSurface& surface) const
|
|||
return bounds;
|
||||
}
|
||||
|
||||
void DoomLevelMesh::GetVisibleSurfaces(LightmapTile* tile, TArray<int>& outSurfaces)
|
||||
{
|
||||
if (tile->Binding.Type == ST_MIDDLESIDE || tile->Binding.Type == ST_UPPERSIDE || tile->Binding.Type == ST_LOWERSIDE)
|
||||
{
|
||||
int sideIndex = tile->Binding.TypeIndex;
|
||||
int surf = Sides[sideIndex].FirstSurface;
|
||||
while (surf != -1)
|
||||
{
|
||||
const auto& sinfo = DoomSurfaceInfos[surf];
|
||||
if (sinfo.Type == tile->Binding.Type)
|
||||
{
|
||||
outSurfaces.Push(surf);
|
||||
}
|
||||
surf = sinfo.NextSurface;
|
||||
}
|
||||
}
|
||||
else if (tile->Binding.Type == ST_CEILING || tile->Binding.Type == ST_FLOOR)
|
||||
{
|
||||
int subsectorIndex = tile->Binding.TypeIndex;
|
||||
int sectorIndex = level.subsectors[subsectorIndex].sector->Index();
|
||||
int surf = Flats[sectorIndex].FirstSurface;
|
||||
while (surf != -1)
|
||||
{
|
||||
const auto& sinfo = DoomSurfaceInfos[surf];
|
||||
int controlSector = sinfo.ControlSector ? sinfo.ControlSector->Index() : (int)0xffffffffUL;
|
||||
if (sinfo.Type == tile->Binding.Type && controlSector == tile->Binding.ControlSector)
|
||||
{
|
||||
FVector2 minUV = tile->ToUV(Mesh.Surfaces[surf].Bounds.min);
|
||||
FVector2 maxUV = tile->ToUV(Mesh.Surfaces[surf].Bounds.max);
|
||||
if (!(maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f))
|
||||
{
|
||||
outSurfaces.Push(surf);
|
||||
}
|
||||
}
|
||||
surf = sinfo.NextSurface;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const
|
||||
{
|
||||
auto f = fopen(objFilename.GetChars(), "w");
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ public:
|
|||
DoomSurfaceInfos.Resize(limits.MaxSurfaces);
|
||||
}
|
||||
|
||||
void GetVisibleSurfaces(LightmapTile* tile, TArray<int>& outSurfaces) override;
|
||||
|
||||
struct Stats
|
||||
{
|
||||
int FlatsUpdated = 0;
|
||||
|
|
@ -159,7 +161,6 @@ private:
|
|||
void SortDrawLists();
|
||||
|
||||
TArray<DoomSurfaceInfo> DoomSurfaceInfos;
|
||||
TArray<std::unique_ptr<DoomSurfaceInfo* []>> PolyDoomSurfaceInfos;
|
||||
|
||||
TArray<SideSurfaceBlock> Sides;
|
||||
TArray<FlatSurfaceBlock> Flats;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue