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 // Smoothing group surface is to be rendered with
int smoothingGroupIndex = -1; int smoothingGroupIndex = -1;
//
// Utility/Info
//
inline uint32_t Area() const { return texWidth * texHeight; }
// //
// VkLightmap extra stuff that I dislike: // 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 class LevelMesh
{ {
@ -200,10 +214,41 @@ public:
TArray<LevelMeshSmoothingGroup> SmoothingGroups; TArray<LevelMeshSmoothingGroup> SmoothingGroups;
TArray<LevelMeshPortal> Portals; TArray<LevelMeshPortal> Portals;
// Lightmap atlas
int LMTextureCount = 0; int LMTextureCount = 0;
int LMTextureSize = 0; int LMTextureSize = 0;
TArray<uint16_t> LMTextureData; // TODO better place for this? 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 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f); FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
uint16_t LightmapSampleDistance = 16; uint16_t LightmapSampleDistance = 16;

View file

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

View file

@ -10,122 +10,86 @@
#include "common/rendering/vulkan/accelstructs/vk_lightmap.h" #include "common/rendering/vulkan/accelstructs/vk_lightmap.h"
#include <vulkan/accelstructs/halffloat.h> #include <vulkan/accelstructs/halffloat.h>
void PrintMissingLevelMesh() 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"); }
Printf("No level mesh. Perhaps your level has no lightmap loaded?\n");
}
void PrintNoLightmaps() #define GET_LEVELMESH() auto* levelMesh = level.levelMesh
{ #define REQUIRE_LEVELMESH(returnValue) GET_LEVELMESH(); do { if(!levelMesh) { PrintMissingLevelMesh(); return returnValue ; } } while(false)
Printf("Lightmap is not enabled in this level.\n"); #define REQUIRE_LIGHTMAP(returnValue) REQUIRE_LEVELMESH(returnValue); do { if(!level.lightmaps) { PrintNoLightmap(); return returnValue ; } } while(false)
}
ADD_STAT(lightmap) ADD_STAT(lightmap)
{ {
FString out; FString out;
if (level.levelMesh && level.lightmaps) GET_LEVELMESH();
if (!levelMesh || !level.lightmaps)
{ {
auto* mesh = level.levelMesh; out.Format("No lightmap");
return out;
uint32_t usedPixels = 0;
uint32_t updatesNeeded = 0;
uint32_t skies = 0;
uint32_t pixelsTbd = 0;
for (auto& surface : mesh->Surfaces)
{
uint32_t area = surface.texWidth * surface.texHeight;
if (surface.needsUpdate)
{
pixelsTbd += area;
updatesNeeded++;
}
if (surface.bSky)
{
skies++;
}
usedPixels += area;
}
uint32_t atlasPixelCount = level.levelMesh->LMTextureSize * level.levelMesh->LMTextureSize * level.levelMesh->LMTextureCount;
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,
atlasPixelCount,
float(usedPixels) / float(atlasPixelCount) * 100.0f );
}
else
{
out.Format("No level mesh.");
} }
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%%",
stats.surfaces.total, stats.surfaces.sky, stats.surfaces.dirty,
stats.pixels.dirty,
stats.pixels.total,
atlasPixelCount,
float(stats.pixels.total) / float(atlasPixelCount) * 100.0f );
return out; return out;
} }
CCMD(dumplevelmesh) CCMD(dumplevelmesh)
{ {
if (level.levelMesh) REQUIRE_LEVELMESH();
{ levelMesh->DumpMesh(FString("levelmesh.obj"), FString("levelmesh.mtl"));
level.levelMesh->DumpMesh(FString("levelmesh.obj"), FString("levelmesh.mtl")); Printf("Level mesh exported.\n");
Printf("Level mesh exported.\n");
}
else
{
PrintMissingLevelMesh();
}
} }
CCMD(invalidatelightmap) CCMD(invalidatelightmap)
{ {
if (!level.levelMesh) REQUIRE_LIGHTMAP();
{
PrintMissingLevelMesh();
return;
}
if (!level.lightmaps)
{
PrintNoLightmaps();
return;
}
int count = 0; int count = 0;
for (auto& surface : level.levelMesh->Surfaces) for (auto& surface : levelMesh->Surfaces)
{ {
if (!surface.needsUpdate) if (!surface.needsUpdate)
++count; ++count;
surface.needsUpdate = true; 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) REQUIRE_LEVELMESH();
{
PrintMissingLevelMesh(); 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);
return; 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());
if (!level.lightmaps) Printf(" Sample dimension: %d\n", surface->sampleDimension);
{ Printf(" Needs update?: %d\n", surface->needsUpdate);
PrintNoLightmaps(); }
return;
} FVector3 RayDir(FAngle angle, FAngle pitch)
{
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) CCMD(surfaceinfo)
{ {
auto* mesh = level.levelMesh; REQUIRE_LEVELMESH();
if (!mesh)
{
PrintMissingLevelMesh();
return;
}
auto pov = players[consoleplayer].mo;
auto pov = players[consoleplayer].mo;
if (!pov) if (!pov)
{ {
Printf("players[consoleplayer].mo is null.\n"); Printf("players[consoleplayer].mo is null.\n");
@ -134,27 +98,17 @@ CCMD(surfaceinfo)
auto posXYZ = FVector3(pov->Pos()); auto posXYZ = FVector3(pov->Pos());
posXYZ.Z = players[consoleplayer].viewz; posXYZ.Z = players[consoleplayer].viewz;
auto angle = pov->Angles.Yaw; auto angle = pov->Angles.Yaw;
auto pitch = pov->Angles.Pitch; auto pitch = pov->Angles.Pitch;
auto pc = float(pitch.Cos()); const auto surface = (DoomLevelMeshSurface*)levelMesh->Trace(posXYZ, FVector3(RayDir(angle, pitch)), 32000.0f);
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);
if (surface) 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); PrintSurfaceInfo(surface);
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);
} }
else else
{ {
Printf("No surface was hit.\n"); Printf("No surface was hit.\n");
return;
} }
} }