mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 20:21:26 +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
|
// 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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
{
|
|
||||||
auto* mesh = level.levelMesh;
|
|
||||||
|
|
||||||
uint32_t usedPixels = 0;
|
if (!levelMesh || !level.lightmaps)
|
||||||
uint32_t updatesNeeded = 0;
|
|
||||||
uint32_t skies = 0;
|
|
||||||
uint32_t pixelsTbd = 0;
|
|
||||||
for (auto& surface : mesh->Surfaces)
|
|
||||||
{
|
{
|
||||||
uint32_t area = surface.texWidth * surface.texHeight;
|
out.Format("No lightmap");
|
||||||
|
return out;
|
||||||
if (surface.needsUpdate)
|
|
||||||
{
|
|
||||||
pixelsTbd += area;
|
|
||||||
updatesNeeded++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface.bSky)
|
uint32_t atlasPixelCount = levelMesh->AtlasPixelCount();
|
||||||
{
|
auto stats = levelMesh->GatherSurfacePixelStats();
|
||||||
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%%",
|
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,
|
stats.surfaces.total, stats.surfaces.sky, stats.surfaces.dirty,
|
||||||
pixelsTbd,
|
stats.pixels.dirty,
|
||||||
usedPixels,
|
stats.pixels.total,
|
||||||
atlasPixelCount,
|
atlasPixelCount,
|
||||||
float(usedPixels) / float(atlasPixelCount) * 100.0f );
|
float(stats.pixels.total) / float(atlasPixelCount) * 100.0f );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out.Format("No level mesh.");
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue