More code cleanup

This commit is contained in:
Magnus Norddahl 2023-09-30 22:24:24 +02:00
commit e2e0a78a2b
5 changed files with 348 additions and 335 deletions

View file

@ -1115,6 +1115,7 @@ set (PCH_SOURCES
common/rendering/hwrenderer/data/hw_shadowmap.cpp
common/rendering/hwrenderer/data/hw_shaderpatcher.cpp
common/rendering/hwrenderer/data/hw_collision.cpp
common/rendering/hwrenderer/data/hw_levelmesh.cpp
common/rendering/hwrenderer/data/hw_meshbuilder.cpp
common/rendering/hwrenderer/data/hw_mesh.cpp
common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp

View file

@ -0,0 +1,190 @@
#include "hw_levelmesh.h"
LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, float maxDist)
{
maxDist = std::max(maxDist - 10.0f, 0.0f);
FVector3 origin = start;
LevelMeshSurface* hitSurface = nullptr;
while (true)
{
FVector3 end = origin + direction * maxDist;
TraceHit hit0 = TriangleMeshShape::find_first_hit(StaticMesh->Collision.get(), origin, end);
TraceHit hit1 = TriangleMeshShape::find_first_hit(DynamicMesh->Collision.get(), origin, end);
LevelSubmesh* hitmesh = hit0.fraction < hit1.fraction ? StaticMesh.get() : DynamicMesh.get();
TraceHit hit = hit0.fraction < hit1.fraction ? hit0 : hit1;
if (hit.triangle < 0)
{
return nullptr;
}
hitSurface = hitmesh->GetSurface(hitmesh->MeshSurfaceIndexes[hit.triangle]);
auto portal = hitSurface->portalIndex;
if (!portal)
{
break;
}
auto& transformation = hitmesh->Portals[portal];
auto travelDist = hit.fraction * maxDist + 2.0f;
if (travelDist >= maxDist)
{
break;
}
origin = transformation.TransformPosition(origin + direction * travelDist);
direction = transformation.TransformRotation(direction);
maxDist -= travelDist;
}
return hitSurface; // I hit something
}
LevelMeshSurfaceStats LevelMesh::GatherSurfacePixelStats()
{
LevelMeshSurfaceStats stats;
StaticMesh->GatherSurfacePixelStats(stats);
DynamicMesh->GatherSurfacePixelStats(stats);
return stats;
}
/////////////////////////////////////////////////////////////////////////////
LevelSubmesh::LevelSubmesh()
{
// Default portal
LevelMeshPortal portal;
Portals.Push(portal);
// Default empty mesh (we can't make it completely empty since vulkan doesn't like that)
float minval = -100001.0f;
float maxval = -100000.0f;
MeshVertices.Push({ minval, minval, minval });
MeshVertices.Push({ maxval, minval, minval });
MeshVertices.Push({ maxval, maxval, minval });
MeshVertices.Push({ minval, minval, minval });
MeshVertices.Push({ minval, maxval, minval });
MeshVertices.Push({ maxval, maxval, minval });
MeshVertices.Push({ minval, minval, maxval });
MeshVertices.Push({ maxval, minval, maxval });
MeshVertices.Push({ maxval, maxval, maxval });
MeshVertices.Push({ minval, minval, maxval });
MeshVertices.Push({ minval, maxval, maxval });
MeshVertices.Push({ maxval, maxval, maxval });
MeshVertexUVs.Resize(MeshVertices.Size());
for (int i = 0; i < 3 * 4; i++)
MeshElements.Push(i);
UpdateCollision();
}
void LevelSubmesh::UpdateCollision()
{
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
}
void LevelSubmesh::GatherSurfacePixelStats(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;
}
void LevelSubmesh::BuildTileSurfaceLists()
{
// Smoothing group surface is to be rendered with
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
TArray<int> SmoothingGroupIndexes(GetSurfaceCount());
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
{
auto surface = GetSurface(i);
// Is this surface in the same plane as an existing smoothing group?
int smoothingGroupIndex = -1;
for (size_t j = 0; j < SmoothingGroups.Size(); j++)
{
if (surface->sectorGroup == SmoothingGroups[j].sectorGroup)
{
float direction = SmoothingGroups[j].plane.XYZ() | surface->plane.XYZ();
if (direction >= 0.9999f && direction <= 1.001f)
{
auto point = (surface->plane.XYZ() * surface->plane.W);
auto planeDistance = (SmoothingGroups[j].plane.XYZ() | point) - SmoothingGroups[j].plane.W;
float dist = std::abs(planeDistance);
if (dist <= 0.01f)
{
smoothingGroupIndex = (int)j;
break;
}
}
}
}
// Surface is in a new plane. Create a smoothing group for it
if (smoothingGroupIndex == -1)
{
smoothingGroupIndex = SmoothingGroups.Size();
LevelMeshSmoothingGroup group;
group.plane = surface->plane;
group.sectorGroup = surface->sectorGroup;
SmoothingGroups.Push(group);
}
SmoothingGroups[smoothingGroupIndex].surfaces.push_back(surface);
SmoothingGroupIndexes.Push(smoothingGroupIndex);
}
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
{
auto targetSurface = GetSurface(i);
targetSurface->tileSurfaces.Clear();
for (LevelMeshSurface* surface : SmoothingGroups[SmoothingGroupIndexes[i]].surfaces)
{
FVector2 minUV = ToUV(surface->bounds.min, targetSurface);
FVector2 maxUV = ToUV(surface->bounds.max, targetSurface);
if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f))
continue; // Bounding box not visible
targetSurface->tileSurfaces.Push(surface);
}
}
}
FVector2 LevelSubmesh::ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface)
{
FVector3 localPos = vert - targetSurface->translateWorldToLocal;
float u = (1.0f + (localPos | targetSurface->projLocalToU)) / (targetSurface->AtlasTile.Width + 2);
float v = (1.0f + (localPos | targetSurface->projLocalToV)) / (targetSurface->AtlasTile.Height + 2);
return FVector2(u, v);
}

View file

@ -31,13 +31,13 @@ public:
struct LevelMeshSurface
{
int numVerts;
unsigned int startVertIndex;
unsigned int startUvIndex;
unsigned int startElementIndex;
unsigned int numElements;
FVector4 plane;
bool bSky;
int numVerts = 0;
unsigned int startVertIndex = 0;
unsigned int startUvIndex = 0;
unsigned int startElementIndex = 0;
unsigned int numElements = 0;
FVector4 plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
bool bSky = false;
// Surface location in lightmap texture
struct
@ -52,10 +52,6 @@ struct LevelMeshSurface
// True if the surface needs to be rendered into the lightmap texture before it can be used
bool needsUpdate = true;
//
// Required for internal lightmapper:
//
FTextureID texture = FNullTextureID();
float alpha = 1.0;
@ -70,15 +66,9 @@ struct LevelMeshSurface
FVector3 projLocalToU = { 0.f, 0.f, 0.f };
FVector3 projLocalToV = { 0.f, 0.f, 0.f };
// Smoothing group surface is to be rendered with
int smoothingGroupIndex = -1;
// Surfaces that are visible within the lightmap tile
TArray<LevelMeshSurface*> tileSurfaces;
//
// Utility/Info
//
uint32_t Area() const { return AtlasTile.Width * AtlasTile.Height; }
// Light list location in the lightmapper GPU buffers
@ -181,35 +171,7 @@ struct LevelMeshSurfaceStats
class LevelSubmesh
{
public:
LevelSubmesh()
{
// Default portal
LevelMeshPortal portal;
Portals.Push(portal);
// Default empty mesh (we can't make it completely empty since vulkan doesn't like that)
float minval = -100001.0f;
float maxval = -100000.0f;
MeshVertices.Push({ minval, minval, minval });
MeshVertices.Push({ maxval, minval, minval });
MeshVertices.Push({ maxval, maxval, minval });
MeshVertices.Push({ minval, minval, minval });
MeshVertices.Push({ minval, maxval, minval });
MeshVertices.Push({ maxval, maxval, minval });
MeshVertices.Push({ minval, minval, maxval });
MeshVertices.Push({ maxval, minval, maxval });
MeshVertices.Push({ maxval, maxval, maxval });
MeshVertices.Push({ minval, minval, maxval });
MeshVertices.Push({ minval, maxval, maxval });
MeshVertices.Push({ maxval, maxval, maxval });
MeshVertexUVs.Resize(MeshVertices.Size());
for (int i = 0; i < 3 * 4; i++)
MeshElements.Push(i);
UpdateCollision();
}
LevelSubmesh();
virtual ~LevelSubmesh() = default;
@ -236,105 +198,12 @@ public:
uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
void UpdateCollision()
{
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
}
void GatherSurfacePixelStats(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;
}
void BuildSmoothingGroups()
{
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
{
auto surface = GetSurface(i);
// Is this surface in the same plane as an existing smoothing group?
int smoothingGroupIndex = -1;
for (size_t j = 0; j < SmoothingGroups.Size(); j++)
{
if (surface->sectorGroup == SmoothingGroups[j].sectorGroup)
{
float direction = SmoothingGroups[j].plane.XYZ() | surface->plane.XYZ();
if (direction >= 0.9999f && direction <= 1.001f)
{
auto point = (surface->plane.XYZ() * surface->plane.W);
auto planeDistance = (SmoothingGroups[j].plane.XYZ() | point) - SmoothingGroups[j].plane.W;
float dist = std::abs(planeDistance);
if (dist <= 0.01f)
{
smoothingGroupIndex = (int)j;
break;
}
}
}
}
// Surface is in a new plane. Create a smoothing group for it
if (smoothingGroupIndex == -1)
{
smoothingGroupIndex = SmoothingGroups.Size();
LevelMeshSmoothingGroup group;
group.plane = surface->plane;
group.sectorGroup = surface->sectorGroup;
SmoothingGroups.Push(group);
}
SmoothingGroups[smoothingGroupIndex].surfaces.push_back(surface);
surface->smoothingGroupIndex = smoothingGroupIndex;
}
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
{
auto targetSurface = GetSurface(i);
targetSurface->tileSurfaces.Clear();
for (LevelMeshSurface* surface : SmoothingGroups[targetSurface->smoothingGroupIndex].surfaces)
{
FVector2 minUV = ToUV(surface->bounds.min, targetSurface);
FVector2 maxUV = ToUV(surface->bounds.max, targetSurface);
if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f))
continue; // Bounding box not visible
targetSurface->tileSurfaces.Push(surface);
}
}
}
void UpdateCollision();
void GatherSurfacePixelStats(LevelMeshSurfaceStats& stats);
void BuildTileSurfaceLists();
private:
FVector2 ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface)
{
FVector3 localPos = vert - targetSurface->translateWorldToLocal;
float u = (1.0f + (localPos | targetSurface->projLocalToU)) / (targetSurface->AtlasTile.Width + 2);
float v = (1.0f + (localPos | targetSurface->projLocalToV)) / (targetSurface->AtlasTile.Height + 2);
return FVector2(u, v);
}
FVector2 ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface);
};
class LevelMesh
@ -347,62 +216,11 @@ public:
virtual int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { return 0; }
LevelMeshSurfaceStats GatherSurfacePixelStats()
{
LevelMeshSurfaceStats stats;
StaticMesh->GatherSurfacePixelStats(stats);
DynamicMesh->GatherSurfacePixelStats(stats);
return stats;
}
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
LevelMeshSurfaceStats GatherSurfacePixelStats();
// Map defaults
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist)
{
maxDist = std::max(maxDist - 10.0f, 0.0f);
FVector3 origin = start;
LevelMeshSurface* hitSurface = nullptr;
while (true)
{
FVector3 end = origin + direction * maxDist;
TraceHit hit0 = TriangleMeshShape::find_first_hit(StaticMesh->Collision.get(), origin, end);
TraceHit hit1 = TriangleMeshShape::find_first_hit(DynamicMesh->Collision.get(), origin, end);
LevelSubmesh* hitmesh = hit0.fraction < hit1.fraction ? StaticMesh.get() : DynamicMesh.get();
TraceHit hit = hit0.fraction < hit1.fraction ? hit0 : hit1;
if (hit.triangle < 0)
{
return nullptr;
}
hitSurface = hitmesh->GetSurface(hitmesh->MeshSurfaceIndexes[hit.triangle]);
auto portal = hitSurface->portalIndex;
if (!portal)
{
break;
}
auto& transformation = hitmesh->Portals[portal];
auto travelDist = hit.fraction * maxDist + 2.0f;
if (travelDist >= maxDist)
{
break;
}
origin = transformation.TransformPosition(origin + direction * travelDist);
direction = transformation.TransformRotation(direction);
maxDist -= travelDist;
}
return hitSurface; // I hit something
}
};

View file

@ -10,6 +10,9 @@
#include "common/rendering/vulkan/accelstructs/vk_lightmap.h"
#include <vulkan/accelstructs/halffloat.h>
VSMatrix GetPlaneTextureRotationMatrix(FGameTexture* gltexture, const sector_t* sector, int plane);
void GetTexCoordInfo(FGameTexture* tex, FTexCoordInfo* tci, side_t* side, int texpos);
static bool RequireLevelMesh()
{
if (level.levelMesh)
@ -88,7 +91,6 @@ void PrintSurfaceInfo(const DoomLevelMeshSurface* surface)
Printf(" Sample dimension: %d\n", surface->sampleDimension);
Printf(" Needs update?: %d\n", surface->needsUpdate);
Printf(" Sector group: %d\n", surface->sectorGroup);
Printf(" Smoothing group: %d\n", surface->smoothingGroupIndex);
Printf(" Texture: '%s' (id=%d)\n", gameTexture ? gameTexture->GetName().GetChars() : "<nullptr>", surface->texture.GetIndex());
Printf(" Alpha: %f\n", surface->alpha);
}
@ -134,6 +136,135 @@ CCMD(surfaceinfo)
EXTERN_CVAR(Float, lm_scale);
/////////////////////////////////////////////////////////////////////////////
DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
{
SunColor = doomMap.SunColor; // TODO keep only one copy?
SunDirection = doomMap.SunDirection;
StaticMesh = std::make_unique<DoomLevelSubmesh>();
DynamicMesh = std::make_unique<DoomLevelSubmesh>();
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->CreateStatic(doomMap);
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->CreateDynamic(doomMap);
}
void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
{
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->UpdateDynamic(doomMap);
}
bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float dist)
{
FVector3 end = start + direction * dist;
auto surface = Trace(start, direction, dist);
return surface && surface->bSky;
}
void DoomLevelMesh::PackLightmapAtlas()
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->PackLightmapAtlas();
}
void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->BindLightmapSurfacesToGeometry(doomMap);
// Runtime helper
for (auto& surface : static_cast<DoomLevelSubmesh*>(StaticMesh.get())->Surfaces)
{
if (surface.ControlSector)
{
if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING)
{
XFloorToSurface[surface.Subsector->sector].Push(&surface);
}
else if (surface.Type == ST_MIDDLESIDE)
{
XFloorToSurfaceSides[surface.ControlSector].Push(&surface);
}
}
}
}
void DoomLevelMesh::DisableLightmaps()
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->DisableLightmaps();
}
void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->DumpMesh(objFilename, mtlFilename);
}
int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize)
{
const DoomLevelMeshSurface* doomsurf = static_cast<const DoomLevelMeshSurface*>(surface);
FLightNode* node = nullptr;
if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING)
{
node = doomsurf->Subsector->section->lighthead;
}
else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE)
{
node = doomsurf->Side->lighthead;
}
if (!node)
return 0;
int listpos = 0;
while (node && listpos < listMaxSize)
{
FDynamicLight* light = node->lightsource;
if (light && light->Trace())
{
DVector3 pos = light->Pos; //light->PosRelative(portalgroup);
LevelMeshLight& meshlight = list[listpos++];
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
meshlight.RelativeOrigin = meshlight.Origin;
meshlight.Radius = (float)light->GetRadius();
meshlight.Intensity = (float)light->target->Alpha;
if (light->IsSpot())
{
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xzLen = negPitch.Cos();
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
meshlight.SpotDir.Y = float(-Angle.Sin() * xzLen);
meshlight.SpotDir.Z = float(-negPitch.Sin());
}
else
{
meshlight.InnerAngleCos = -1.0f;
meshlight.OuterAngleCos = -1.0f;
meshlight.SpotDir.X = 0.0f;
meshlight.SpotDir.Y = 0.0f;
meshlight.SpotDir.Z = 0.0f;
}
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
if (light->Sector)
meshlight.SectorGroup = static_cast<DoomLevelSubmesh*>(StaticMesh.get())->sectorGroup[light->Sector->Index()];
else
meshlight.SectorGroup = 0;
}
node = node->nextLight;
}
return listpos;
}
/////////////////////////////////////////////////////////////////////////////
void DoomLevelSubmesh::CreateStatic(FLevelLocals& doomMap)
{
MeshVertices.Clear();
@ -155,6 +286,7 @@ void DoomLevelSubmesh::CreateStatic(FLevelLocals& doomMap)
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
}
@ -236,26 +368,10 @@ void DoomLevelSubmesh::UpdateDynamic(FLevelLocals& doomMap)
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
}
DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
{
SunColor = doomMap.SunColor; // TODO keep only one copy?
SunDirection = doomMap.SunDirection;
StaticMesh = std::make_unique<DoomLevelSubmesh>();
DynamicMesh = std::make_unique<DoomLevelSubmesh>();
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->CreateStatic(doomMap);
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->CreateDynamic(doomMap);
}
void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
{
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->UpdateDynamic(doomMap);
}
void DoomLevelSubmesh::BuildSectorGroups(const FLevelLocals& doomMap)
{
int groupIndex = 0;
@ -415,71 +531,6 @@ void DoomLevelSubmesh::CreatePortals()
}
}
int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize)
{
const DoomLevelMeshSurface* doomsurf = static_cast<const DoomLevelMeshSurface*>(surface);
FLightNode* node = nullptr;
if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING)
{
node = doomsurf->Subsector->section->lighthead;
}
else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE)
{
node = doomsurf->Side->lighthead;
}
if (!node)
return 0;
int listpos = 0;
while (node && listpos < listMaxSize)
{
FDynamicLight* light = node->lightsource;
if (light && light->Trace())
{
DVector3 pos = light->Pos; //light->PosRelative(portalgroup);
LevelMeshLight& meshlight = list[listpos++];
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
meshlight.RelativeOrigin = meshlight.Origin;
meshlight.Radius = (float)light->GetRadius();
meshlight.Intensity = (float)light->target->Alpha;
if (light->IsSpot())
{
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xzLen = negPitch.Cos();
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
meshlight.SpotDir.Y = float(-Angle.Sin() * xzLen);
meshlight.SpotDir.Z = float(-negPitch.Sin());
}
else
{
meshlight.InnerAngleCos = -1.0f;
meshlight.OuterAngleCos = -1.0f;
meshlight.SpotDir.X = 0.0f;
meshlight.SpotDir.Y = 0.0f;
meshlight.SpotDir.Z = 0.0f;
}
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
if (light->Sector)
meshlight.SectorGroup = static_cast<DoomLevelSubmesh*>(StaticMesh.get())->sectorGroup[light->Sector->Index()];
else
meshlight.SectorGroup = 0;
}
node = node->nextLight;
}
return listpos;
}
void DoomLevelSubmesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
{
// You have no idea how long this took me to figure out...
@ -1262,8 +1313,6 @@ void DoomLevelSubmesh::SetupLightmapUvs(FLevelLocals& doomMap)
BuildSurfaceParams(LMTextureSize, LMTextureSize, surface);
}
BuildSmoothingGroups();
CreateSurfaceTextureUVs(doomMap);
}
@ -1469,12 +1518,6 @@ void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMap
surface.AtlasTile.Height = height;
}
// hw_flats.cpp
VSMatrix GetPlaneTextureRotationMatrix(FGameTexture* gltexture, const sector_t* sector, int plane);
// hw_walls.cpp
void GetTexCoordInfo(FGameTexture* tex, FTexCoordInfo* tci, side_t* side, int texpos);
void DoomLevelSubmesh::CreateSurfaceTextureUVs(FLevelLocals& doomMap)
{
auto toUv = [](const DoomLevelMeshSurface* targetSurface, FVector3 vert) {

View file

@ -7,7 +7,6 @@
#include "r_defs.h"
#include "bounds.h"
#include <dp_rect_pack.h>
#include <set>
typedef dp::rect_pack::RectPacker<int> RectPacker;
@ -27,12 +26,12 @@ enum DoomLevelMeshSurfaceType
struct DoomLevelMeshSurface : public LevelMeshSurface
{
DoomLevelMeshSurfaceType Type = ST_UNKNOWN;
int TypeIndex;
int TypeIndex = 0;
subsector_t* Subsector = nullptr;
side_t* Side = nullptr;
sector_t* ControlSector = nullptr;
float* TexCoords;
float* TexCoords = nullptr;
};
class DoomLevelSubmesh : public LevelSubmesh
@ -133,52 +132,14 @@ class DoomLevelMesh : public LevelMesh
public:
DoomLevelMesh(FLevelLocals &doomMap);
void BeginFrame(FLevelLocals& doomMap);
bool TraceSky(const FVector3& start, FVector3 direction, float dist)
{
FVector3 end = start + direction * dist;
auto surface = Trace(start, direction, dist);
return surface && surface->bSky;
}
int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override;
void PackLightmapAtlas()
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->PackLightmapAtlas();
}
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->BindLightmapSurfacesToGeometry(doomMap);
// Runtime helper
for (auto& surface : static_cast<DoomLevelSubmesh*>(StaticMesh.get())->Surfaces)
{
if (surface.ControlSector)
{
if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING)
{
XFloorToSurface[surface.Subsector->sector].Push(&surface);
}
else if (surface.Type == ST_MIDDLESIDE)
{
XFloorToSurfaceSides[surface.ControlSector].Push(&surface);
}
}
}
}
void DisableLightmaps()
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->DisableLightmaps();
}
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const
{
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->DumpMesh(objFilename, mtlFilename);
}
void BeginFrame(FLevelLocals& doomMap);
bool TraceSky(const FVector3& start, FVector3 direction, float dist);
void PackLightmapAtlas();
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap);
void DisableLightmaps();
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
// To do: remove these. Use ffloors on flats and sides to find the 3d surfaces as that is both faster and culls better
TMap<const sector_t*, TArray<DoomLevelMeshSurface*>> XFloorToSurface;