More code cleanup
This commit is contained in:
parent
b5095a4790
commit
e2e0a78a2b
5 changed files with 348 additions and 335 deletions
|
|
@ -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
|
||||
|
|
|
|||
190
src/common/rendering/hwrenderer/data/hw_levelmesh.cpp
Normal file
190
src/common/rendering/hwrenderer/data/hw_levelmesh.cpp
Normal 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);
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue