mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 12:11:25 +00:00
Refactor CCMDs in doom_levelmesh.cpp
This commit is contained in:
parent
2036f9a973
commit
3cdf28eb23
3 changed files with 97 additions and 98 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue