Refactor CCMDs in doom_levelmesh.cpp

This commit is contained in:
RaveYard 2023-09-14 17:02:46 +02:00 committed by Christoph Oelckers
parent 2036f9a973
commit 3cdf28eb23
3 changed files with 97 additions and 98 deletions

View file

@ -78,6 +78,11 @@ struct LevelMeshSurface
// Smoothing group surface is to be rendered with
int smoothingGroupIndex = -1;
//
// Utility/Info
//
inline uint32_t Area() const { return texWidth * texHeight; }
//
// VkLightmap extra stuff that I dislike:
//
@ -171,6 +176,15 @@ struct IdenticalPortalComparator
}
};
struct LevelMeshSurfaceStats
{
struct Stats
{
uint32_t total = 0, dirty = 0, sky = 0;
};
Stats surfaces, pixels;
};
class LevelMesh
{
@ -200,10 +214,41 @@ public:
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
TArray<LevelMeshPortal> Portals;
// Lightmap atlas
int LMTextureCount = 0;
int LMTextureSize = 0;
TArray<uint16_t> LMTextureData; // TODO better place for this?
inline uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
inline LevelMeshSurfaceStats GatherSurfacePixelStats() //const
{
LevelMeshSurfaceStats stats;
int count = GetSurfaceCount();
for (int i = 0; i < count; ++i)
{
const auto* surface = GetSurface(i);
auto area = surface->Area();
stats.pixels.total += area;
if (surface->needsUpdate)
{
stats.surfaces.dirty++;
stats.pixels.dirty += area;
}
if (surface->bSky)
{
stats.surfaces.sky++;
stats.pixels.sky += area;
}
}
stats.surfaces.total = count;
return stats;
}
// Map defaults
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
uint16_t LightmapSampleDistance = 16;

View file

@ -78,7 +78,7 @@ void VkLightmap::Raytrace(const TArray<LevelMeshSurface*>& surfaces)
for (auto& surface : surfaces)
{
surface->needsUpdate = false; // it may have been set to false already, but lightmapper ultimately decides so
pixels += surface->texHeight * surface->texWidth;
pixels += surface->Area();
}
UploadUniforms();

View file

@ -10,122 +10,86 @@
#include "common/rendering/vulkan/accelstructs/vk_lightmap.h"
#include <vulkan/accelstructs/halffloat.h>
void PrintMissingLevelMesh()
{
Printf("No level mesh. Perhaps your level has no lightmap loaded?\n");
}
void PrintMissingLevelMesh() { Printf("No level mesh. Perhaps your level has no lightmap loaded?\n"); }
void PrintNoLightmap() { Printf("Lightmap is not enabled in this level.\n"); }
void PrintNoLightmaps()
{
Printf("Lightmap is not enabled in this level.\n");
}
#define GET_LEVELMESH() auto* levelMesh = level.levelMesh
#define REQUIRE_LEVELMESH(returnValue) GET_LEVELMESH(); do { if(!levelMesh) { PrintMissingLevelMesh(); return returnValue ; } } while(false)
#define REQUIRE_LIGHTMAP(returnValue) REQUIRE_LEVELMESH(returnValue); do { if(!level.lightmaps) { PrintNoLightmap(); return returnValue ; } } while(false)
ADD_STAT(lightmap)
{
FString out;
if (level.levelMesh && level.lightmaps)
{
auto* mesh = level.levelMesh;
GET_LEVELMESH();
uint32_t usedPixels = 0;
uint32_t updatesNeeded = 0;
uint32_t skies = 0;
uint32_t pixelsTbd = 0;
for (auto& surface : mesh->Surfaces)
if (!levelMesh || !level.lightmaps)
{
uint32_t area = surface.texWidth * surface.texHeight;
if (surface.needsUpdate)
{
pixelsTbd += area;
updatesNeeded++;
out.Format("No lightmap");
return out;
}
if (surface.bSky)
{
skies++;
}
usedPixels += area;
}
uint32_t atlasPixelCount = level.levelMesh->LMTextureSize * level.levelMesh->LMTextureSize * level.levelMesh->LMTextureCount;
uint32_t atlasPixelCount = levelMesh->AtlasPixelCount();
auto stats = levelMesh->GatherSurfacePixelStats();
out.Format("Surfaces: %u (sky: %u, awaiting updates: %u)\nSurface pixel area to update: %u\nSurface pixel area: %u\nAtlas pixel area: %u\nAtlas efficiency: %.4f%%",
mesh->Surfaces.Size(), skies, updatesNeeded,
pixelsTbd,
usedPixels,
stats.surfaces.total, stats.surfaces.sky, stats.surfaces.dirty,
stats.pixels.dirty,
stats.pixels.total,
atlasPixelCount,
float(usedPixels) / float(atlasPixelCount) * 100.0f );
}
else
{
out.Format("No level mesh.");
}
float(stats.pixels.total) / float(atlasPixelCount) * 100.0f );
return out;
}
CCMD(dumplevelmesh)
{
if (level.levelMesh)
{
level.levelMesh->DumpMesh(FString("levelmesh.obj"), FString("levelmesh.mtl"));
REQUIRE_LEVELMESH();
levelMesh->DumpMesh(FString("levelmesh.obj"), FString("levelmesh.mtl"));
Printf("Level mesh exported.\n");
}
else
{
PrintMissingLevelMesh();
}
}
CCMD(invalidatelightmap)
{
if (!level.levelMesh)
{
PrintMissingLevelMesh();
return;
}
if (!level.lightmaps)
{
PrintNoLightmaps();
return;
}
REQUIRE_LIGHTMAP();
int count = 0;
for (auto& surface : level.levelMesh->Surfaces)
for (auto& surface : levelMesh->Surfaces)
{
if (!surface.needsUpdate)
++count;
surface.needsUpdate = true;
}
Printf("Marked %d out of %d surfaces for update.\n", count, level.levelMesh->Surfaces.Size());
Printf("Marked %d out of %d surfaces for update.\n", count, levelMesh->Surfaces.Size());
}
CCMD(lightmapinfo)
void PrintSurfaceInfo(const DoomLevelMeshSurface* surface)
{
if (!level.levelMesh)
{
PrintMissingLevelMesh();
return;
REQUIRE_LEVELMESH();
Printf("Surface %d (%p)\n Type: %d, TypeIndex: %d, ControlSector: %d\n", levelMesh->GetSurfaceIndex(surface), surface, surface->Type, surface->typeIndex, surface->ControlSector ? surface->ControlSector->Index() : -1);
Printf(" Atlas page: %d, x:%d, y:%d\n", surface->atlasPageIndex, surface->atlasX, surface->atlasY);
Printf(" Pixels: %dx%d (area: %d)\n", surface->texWidth, surface->texHeight, surface->Area());
Printf(" Sample dimension: %d\n", surface->sampleDimension);
Printf(" Needs update?: %d\n", surface->needsUpdate);
}
if (!level.lightmaps)
FVector3 RayDir(FAngle angle, FAngle pitch)
{
PrintNoLightmaps();
return;
auto pc = float(pitch.Cos());
return FVector3{ pc * float(angle.Cos()), pc * float(angle.Sin()), -float(pitch.Sin()) };
}
DVector3 RayDir(DAngle angle, DAngle pitch)
{
auto pc = pitch.Cos();
return DVector3{ pc * (angle.Cos()), pc * (angle.Sin()), -(pitch.Sin()) };
}
CCMD(surfaceinfo)
{
auto* mesh = level.levelMesh;
if (!mesh)
{
PrintMissingLevelMesh();
return;
}
REQUIRE_LEVELMESH();
auto pov = players[consoleplayer].mo;
if (!pov)
{
Printf("players[consoleplayer].mo is null.\n");
@ -134,27 +98,17 @@ CCMD(surfaceinfo)
auto posXYZ = FVector3(pov->Pos());
posXYZ.Z = players[consoleplayer].viewz;
auto angle = pov->Angles.Yaw;
auto pitch = pov->Angles.Pitch;
auto pc = float(pitch.Cos());
auto dir = FVector3{ pc * float(angle.Cos()), pc * float(angle.Sin()), -float(pitch.Sin()) }; // No seriously, is there a dedication function for this?
const auto surface = (DoomLevelMeshSurface*)mesh->Trace(posXYZ, dir, 32000.0f);
const auto surface = (DoomLevelMeshSurface*)levelMesh->Trace(posXYZ, FVector3(RayDir(angle, pitch)), 32000.0f);
if (surface)
{
Printf("Surface %d (%p)\n Type: %d, TypeIndex: %d, ControlSector: %d\n", mesh->GetSurfaceIndex(surface), surface, surface->Type, surface->typeIndex, surface->ControlSector ? surface->ControlSector->Index() : -1);
Printf(" Atlas page: %d, x:%d, y:%d\n", surface->atlasPageIndex, surface->atlasX, surface->atlasY);
Printf(" Pixels: %dx%d (area: %d)\n", surface->texWidth, surface->texHeight, surface->texWidth * surface->texHeight);
Printf(" Sample dimension: %d\n", surface->sampleDimension);
Printf(" Needs update?: %d\n", surface->needsUpdate);
PrintSurfaceInfo(surface);
}
else
{
Printf("No surface was hit.\n");
return;
}
}