Misc surface and lightmapper related cleanup and renaming

This commit is contained in:
Magnus Norddahl 2023-12-11 11:21:20 +01:00
commit 412be46e08
13 changed files with 200 additions and 185 deletions

View file

@ -32,8 +32,8 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl
}
hitSurface = hitmesh->GetSurface(hitmesh->Mesh.SurfaceIndexes[hit.triangle]);
auto portal = hitSurface->portalIndex;
int portal = hitSurface->PortalIndex;
if (!portal)
{
break;
@ -100,7 +100,7 @@ void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats)
for (int i = 0; i < count; ++i)
{
const auto* surface = GetSurface(i);
auto area = surface->Area();
auto area = surface->AtlasTile.Area();
stats.pixels.total += area;
@ -109,7 +109,7 @@ void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats)
stats.surfaces.dirty++;
stats.pixels.dirty += area;
}
if (surface->bSky)
if (surface->IsSky)
{
stats.surfaces.sky++;
stats.pixels.sky += area;
@ -133,12 +133,12 @@ void LevelSubmesh::BuildTileSurfaceLists()
for (size_t j = 0; j < SmoothingGroups.Size(); j++)
{
if (surface->sectorGroup == SmoothingGroups[j].sectorGroup)
if (surface->SectorGroup == SmoothingGroups[j].sectorGroup)
{
float direction = SmoothingGroups[j].plane.XYZ() | surface->plane.XYZ();
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 point = (surface->Plane.XYZ() * surface->Plane.W);
auto planeDistance = (SmoothingGroups[j].plane.XYZ() | point) - SmoothingGroups[j].plane.W;
float dist = std::abs(planeDistance);
@ -157,8 +157,8 @@ void LevelSubmesh::BuildTileSurfaceLists()
smoothingGroupIndex = SmoothingGroups.Size();
LevelMeshSmoothingGroup group;
group.plane = surface->plane;
group.sectorGroup = surface->sectorGroup;
group.plane = surface->Plane;
group.sectorGroup = surface->SectorGroup;
SmoothingGroups.Push(group);
}
@ -169,23 +169,23 @@ void LevelSubmesh::BuildTileSurfaceLists()
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
{
auto targetSurface = GetSurface(i);
targetSurface->tileSurfaces.Clear();
targetSurface->TileSurfaces.Clear();
for (LevelMeshSurface* surface : SmoothingGroups[SmoothingGroupIndexes[i]].surfaces)
{
FVector2 minUV = ToUV(surface->bounds.min, targetSurface);
FVector2 maxUV = ToUV(surface->bounds.max, targetSurface);
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);
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);
FVector3 localPos = vert - targetSurface->TileTransform.TranslateWorldToLocal;
float u = (1.0f + (localPos | targetSurface->TileTransform.ProjLocalToU)) / (targetSurface->AtlasTile.Width + 2);
float v = (1.0f + (localPos | targetSurface->TileTransform.ProjLocalToV)) / (targetSurface->AtlasTile.Height + 2);
return FVector2(u, v);
}

View file

@ -38,12 +38,15 @@ struct LevelMeshSurface
{
LevelSubmesh* Submesh = nullptr;
int numVerts = 0;
unsigned int startVertIndex = 0;
unsigned int startElementIndex = 0;
unsigned int numElements = 0;
FVector4 plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
bool bSky = false;
struct
{
unsigned int StartVertIndex = 0;
int NumVerts = 0;
unsigned int StartElementIndex = 0;
unsigned int NumElements = 0;
} MeshLocation;
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
// Surface location in lightmap texture
struct
@ -53,30 +56,33 @@ struct LevelMeshSurface
int Width = 0;
int Height = 0;
int ArrayIndex = 0;
uint32_t Area() const { return Width * Height; }
} AtlasTile;
// True if the surface needs to be rendered into the lightmap texture before it can be used
bool NeedsUpdate = true;
bool AlwaysUpdate = false;
FGameTexture* texture = nullptr;
float alpha = 1.0;
FGameTexture* Texture = nullptr;
float Alpha = 1.0;
int portalIndex = 0;
int sectorGroup = 0;
bool IsSky = false;
int PortalIndex = 0;
int SectorGroup = 0;
BBox bounds;
uint16_t sampleDimension = 0;
BBox Bounds;
uint16_t SampleDimension = 0;
// Calculate world coordinates to UV coordinates
FVector3 translateWorldToLocal = { 0.f, 0.f, 0.f };
FVector3 projLocalToU = { 0.f, 0.f, 0.f };
FVector3 projLocalToV = { 0.f, 0.f, 0.f };
struct
{
FVector3 TranslateWorldToLocal = { 0.0f, 0.0f, 0.0f };
FVector3 ProjLocalToU = { 0.0f, 0.0f, 0.0f };
FVector3 ProjLocalToV = { 0.0f, 0.0f, 0.0f };
} TileTransform;
// Surfaces that are visible within the lightmap tile
TArray<LevelMeshSurface*> tileSurfaces;
uint32_t Area() const { return AtlasTile.Width * AtlasTile.Height; }
TArray<LevelMeshSurface*> TileSurfaces;
// Light list location in the lightmapper GPU buffers
struct

View file

@ -638,14 +638,14 @@ void VkLevelMeshUploader::UploadSurfaces()
LevelMeshSurface* surface = submesh->GetSurface(j);
SurfaceInfo info;
info.Normal = FVector3(surface->plane.X, surface->plane.Z, surface->plane.Y);
info.PortalIndex = surface->portalIndex;
info.SamplingDistance = (float)surface->sampleDimension;
info.Sky = surface->bSky;
info.Alpha = surface->alpha;
if (surface->texture)
info.Normal = FVector3(surface->Plane.X, surface->Plane.Z, surface->Plane.Y);
info.PortalIndex = surface->PortalIndex;
info.SamplingDistance = (float)surface->SampleDimension;
info.Sky = surface->IsSky;
info.Alpha = surface->Alpha;
if (surface->Texture)
{
auto mat = FMaterial::ValidateTexture(surface->texture, 0);
auto mat = FMaterial::ValidateTexture(surface->Texture, 0);
info.TextureIndex = Mesh->fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0);
}
else

View file

@ -200,14 +200,14 @@ void VkLightmapper::Render()
pc.TextureSize = (float)bakeImageSize;
pc.TileWidth = (float)targetSurface->AtlasTile.Width;
pc.TileHeight = (float)targetSurface->AtlasTile.Height;
pc.WorldToLocal = SwapYZ(targetSurface->translateWorldToLocal);
pc.ProjLocalToU = SwapYZ(targetSurface->projLocalToU);
pc.ProjLocalToV = SwapYZ(targetSurface->projLocalToV);
pc.WorldToLocal = SwapYZ(targetSurface->TileTransform.TranslateWorldToLocal);
pc.ProjLocalToU = SwapYZ(targetSurface->TileTransform.ProjLocalToU);
pc.ProjLocalToV = SwapYZ(targetSurface->TileTransform.ProjLocalToV);
bool buffersFull = false;
// Paint all surfaces visible in the tile
for (LevelMeshSurface* surface : targetSurface->tileSurfaces)
for (LevelMeshSurface* surface : targetSurface->TileSurfaces)
{
if (surface->LightList.ResetCounter != lights.ResetCounter)
{
@ -247,9 +247,9 @@ void VkLightmapper::Render()
#ifdef USE_DRAWINDIRECT
VkDrawIndexedIndirectCommand cmd;
cmd.indexCount = surface->numElements;
cmd.indexCount = surface->MeshLocation.NumElements;
cmd.instanceCount = 1;
cmd.firstIndex = firstIndexOffset + surface->startElementIndex;
cmd.firstIndex = firstIndexOffset + surface->MeshLocation.StartElementIndex;
cmd.vertexOffset = 0;
cmd.firstInstance = drawindexed.Pos;
drawindexed.Constants[drawindexed.Pos] = pc;
@ -419,7 +419,7 @@ void VkLightmapper::CopyResult()
}
copylists[pageIndex].Push(&selected);
pixels += selected.Surface->Area();
pixels += selected.Surface->AtlasTile.Area();
lastSurfaceCount++;
}
}

View file

@ -3321,7 +3321,7 @@ bool MapLoader::LoadLightmap(MapData* map)
dstX, dstY,
dstX + realSurface.AtlasTile.Width, dstY + realSurface.AtlasTile.Height,
dstPage,
realSurface.Area() * 3);
realSurface.AtlasTile.Area() * 3);
}
// copy pixels
@ -3351,7 +3351,7 @@ bool MapLoader::LoadLightmap(MapData* map)
{
auto& realSurface = *surface.targetSurface;
auto* vertices = &submesh->Mesh.Vertices[realSurface.startVertIndex];
auto* vertices = &submesh->Mesh.Vertices[realSurface.MeshLocation.StartVertIndex];
auto* newUVs = &zdrayUvs[surface.uvOffset];
for (uint32_t i = 0; i < surface.uvCount; ++i)

View file

@ -80,17 +80,17 @@ void PrintSurfaceInfo(const DoomLevelMeshSurface* surface)
{
if (!RequireLevelMesh()) return;
auto gameTexture = surface->texture;
auto gameTexture = surface->Texture;
Printf("Surface %d (%p)\n Type: %d, TypeIndex: %d, ControlSector: %d\n", surface->Submesh->GetSurfaceIndex(surface), surface, surface->Type, surface->TypeIndex, surface->ControlSector ? surface->ControlSector->Index() : -1);
Printf(" Atlas page: %d, x:%d, y:%d\n", surface->AtlasTile.ArrayIndex, surface->AtlasTile.X, surface->AtlasTile.Y);
Printf(" Pixels: %dx%d (area: %d)\n", surface->AtlasTile.Width, surface->AtlasTile.Height, surface->Area());
Printf(" Sample dimension: %d\n", surface->sampleDimension);
Printf(" Pixels: %dx%d (area: %d)\n", surface->AtlasTile.Width, surface->AtlasTile.Height, surface->AtlasTile.Area());
Printf(" Sample dimension: %d\n", surface->SampleDimension);
Printf(" Needs update?: %d\n", surface->NeedsUpdate);
Printf(" Always update?: %d\n", surface->AlwaysUpdate);
Printf(" Sector group: %d\n", surface->sectorGroup);
Printf(" Sector group: %d\n", surface->SectorGroup);
Printf(" Texture: '%s'\n", gameTexture ? gameTexture->GetName().GetChars() : "<nullptr>");
Printf(" Alpha: %f\n", surface->alpha);
Printf(" Alpha: %f\n", surface->Alpha);
}
FVector3 RayDir(FAngle angle, FAngle pitch)
@ -144,23 +144,20 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
BuildSectorGroups(doomMap);
CreatePortals(doomMap);
StaticMesh = std::make_unique<DoomLevelSubmesh>(this);
DynamicMesh = std::make_unique<DoomLevelSubmesh>(this);
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->CreateStatic(doomMap);
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->CreateDynamic(doomMap);
StaticMesh = std::make_unique<DoomLevelSubmesh>(this, doomMap, true);
DynamicMesh = std::make_unique<DoomLevelSubmesh>(this, doomMap, false);
}
void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
{
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->UpdateDynamic(doomMap, static_cast<DoomLevelSubmesh*>(StaticMesh.get())->LMTextureCount);
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->Update(doomMap, static_cast<DoomLevelSubmesh*>(StaticMesh.get())->LMTextureCount);
}
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;
return surface && surface->IsSky;
}
void DoomLevelMesh::PackLightmapAtlas()
@ -170,31 +167,7 @@ void DoomLevelMesh::PackLightmapAtlas()
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)
{
bool isPolyLine = !!(doomsurf->Side->Flags & WALLF_POLYOBJ);
if (isPolyLine)
{
subsector_t* subsector = level.PointInRenderSubsector((doomsurf->Side->V1()->fPos() + doomsurf->Side->V2()->fPos()) * 0.5);
node = subsector->section->lighthead;
}
else if (!doomsurf->ControlSector)
{
node = doomsurf->Side->lighthead;
}
else // 3d floor needs light from the sidedef on the other side
{
int otherside = doomsurf->Side->linedef->sidedef[0] == doomsurf->Side ? 1 : 0;
node = doomsurf->Side->linedef->sidedef[otherside]->lighthead;
}
}
FLightNode* node = GetSurfaceLightNode(static_cast<const DoomLevelMeshSurface*>(surface));
if (!node)
return 0;
@ -247,6 +220,34 @@ int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLi
return listpos;
}
FLightNode* DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf)
{
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)
{
bool isPolyLine = !!(doomsurf->Side->Flags & WALLF_POLYOBJ);
if (isPolyLine)
{
subsector_t* subsector = level.PointInRenderSubsector((doomsurf->Side->V1()->fPos() + doomsurf->Side->V2()->fPos()) * 0.5);
node = subsector->section->lighthead;
}
else if (!doomsurf->ControlSector)
{
node = doomsurf->Side->lighthead;
}
else // 3d floor needs light from the sidedef on the other side
{
int otherside = doomsurf->Side->linedef->sidedef[0] == doomsurf->Side ? 1 : 0;
node = doomsurf->Side->linedef->sidedef[otherside]->lighthead;
}
}
return node;
}
void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const
{
DoomLevelSubmesh* submesh = static_cast<DoomLevelSubmesh*>(StaticMesh.get());
@ -315,7 +316,7 @@ void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilen
else
{
const auto& surface = submesh->Surfaces[index];
fprintf(f, "o Surface[%d] %s %d%s\n", index, name(surface.Type), surface.TypeIndex, surface.bSky ? " sky" : "");
fprintf(f, "o Surface[%d] %s %d%s\n", index, name(surface.Type), surface.TypeIndex, surface.IsSky ? " sky" : "");
fprintf(f, "usemtl lightmap%d\n", surface.AtlasTile.ArrayIndex);
if (surface.AtlasTile.ArrayIndex > highestUsedAtlasPage)

View file

@ -22,4 +22,7 @@ public:
TArray<int> sectorGroup; // index is sector, value is sectorGroup
TArray<int> sectorPortals[2]; // index is sector+plane, value is index into the portal list
TArray<int> linePortals; // index is linedef, value is index into the portal list
private:
FLightNode* GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf);
};

View file

@ -21,41 +21,40 @@ void GetTexCoordInfo(FGameTexture* tex, FTexCoordInfo* tci, side_t* side, int te
EXTERN_CVAR(Bool, gl_texture)
EXTERN_CVAR(Float, lm_scale);
void DoomLevelSubmesh::CreateStatic(FLevelLocals& doomMap)
{
LightmapSampleDistance = doomMap.LightmapSampleDistance;
Reset();
CreateStaticSurfaces(doomMap);
LinkSurfaces(doomMap);
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
}
void DoomLevelSubmesh::CreateDynamic(FLevelLocals& doomMap)
DoomLevelSubmesh::DoomLevelSubmesh(DoomLevelMesh* mesh, FLevelLocals& doomMap, bool staticMesh) : LevelMesh(mesh), StaticMesh(staticMesh)
{
LightmapSampleDistance = doomMap.LightmapSampleDistance;
Reset();
if (StaticMesh)
{
CreateStaticSurfaces(doomMap);
LinkSurfaces(doomMap);
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
}
}
void DoomLevelSubmesh::UpdateDynamic(FLevelLocals& doomMap, int lightmapStartIndex)
void DoomLevelSubmesh::Update(FLevelLocals& doomMap, int lightmapStartIndex)
{
Reset();
if (!StaticMesh)
{
Reset();
CreateDynamicSurfaces(doomMap);
LinkSurfaces(doomMap);
CreateDynamicSurfaces(doomMap);
LinkSurfaces(doomMap);
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
CreateIndexes();
SetupLightmapUvs(doomMap);
BuildTileSurfaceLists();
UpdateCollision();
if (doomMap.lightmaps)
PackLightmapAtlas(lightmapStartIndex);
if (doomMap.lightmaps)
PackLightmapAtlas(lightmapStartIndex);
}
}
void DoomLevelSubmesh::Reset()
@ -169,14 +168,14 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
surf.TypeIndex = side->Index();
surf.Side = side;
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
surf.sectorGroup = LevelMesh->sectorGroup[front->Index()];
surf.alpha = float(side->linedef->alpha);
surf.startVertIndex = startVertIndex;
surf.numVerts = Mesh.Vertices.Size() - startVertIndex;
surf.plane = ToPlane(Mesh.Vertices[startVertIndex].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 3].fPos());
surf.texture = wallpart.texture;
surf.SectorGroup = LevelMesh->sectorGroup[front->Index()];
surf.Alpha = float(side->linedef->alpha);
surf.MeshLocation.StartVertIndex = startVertIndex;
surf.MeshLocation.NumVerts = Mesh.Vertices.Size() - startVertIndex;
surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 3].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos());
surf.Texture = wallpart.texture;
surf.PipelineID = pipelineID;
surf.portalIndex = (surf.Type == ST_MIDDLESIDE) ? LevelMesh->linePortals[side->linedef->Index()] : 0;
surf.PortalIndex = (surf.Type == ST_MIDDLESIDE) ? LevelMesh->linePortals[side->linedef->Index()] : 0;
Surfaces.Push(surf);
}
@ -242,19 +241,21 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
if (!foundDraw)
continue;
auto plane = sector->GetSecPlane(flatpart.ceiling);
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.Type = flatpart.ceiling ? ST_CEILING : ST_FLOOR;
surf.ControlSector = flatpart.controlsector ? flatpart.controlsector->model : nullptr;
surf.AlwaysUpdate = !!(sector->Flags & SECF_LM_DYNAMIC);
surf.sectorGroup = LevelMesh->sectorGroup[sector->Index()];
surf.alpha = flatpart.alpha;
surf.texture = flatpart.texture;
surf.SectorGroup = LevelMesh->sectorGroup[sector->Index()];
surf.Alpha = flatpart.alpha;
surf.Texture = flatpart.texture;
surf.PipelineID = pipelineID;
surf.plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D);
surf.portalIndex = LevelMesh->sectorPortals[flatpart.ceiling][i];
surf.PortalIndex = LevelMesh->sectorPortals[flatpart.ceiling][i];
auto plane = sector->GetSecPlane(flatpart.ceiling);
surf.Plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D);
//if (flatpart.ceiling)
// surf.Plane = -surf.Plane;
for (subsector_t* sub : section.subsectors)
{
@ -280,8 +281,11 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
surf.TypeIndex = sub->Index();
surf.Subsector = sub;
surf.startVertIndex = startVertIndex;
surf.numVerts = sub->numlines;
surf.MeshLocation.StartVertIndex = startVertIndex;
surf.MeshLocation.NumVerts = sub->numlines;
//surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos());
Surfaces.Push(surf);
}
}
@ -321,7 +325,7 @@ void DoomLevelSubmesh::CreateIndexes()
for (size_t i = 0; i < Surfaces.Size(); i++)
{
DoomLevelMeshSurface* s = &Surfaces[i];
pipelineSurfaces[(int64_t(s->PipelineID) << 32) | int64_t(s->bSky)].Push(i);
pipelineSurfaces[(int64_t(s->PipelineID) << 32) | int64_t(s->IsSky)].Push(i);
}
for (const auto& it : pipelineSurfaces)
@ -332,13 +336,12 @@ void DoomLevelSubmesh::CreateIndexes()
for (unsigned int i : it.second)
{
DoomLevelMeshSurface& s = Surfaces[i];
int numVerts = s.numVerts;
unsigned int pos = s.startVertIndex;
int numVerts = s.MeshLocation.NumVerts;
unsigned int pos = s.MeshLocation.StartVertIndex;
FFlatVertex* verts = &Mesh.Vertices[pos];
s.Vertices = verts;
s.startElementIndex = Mesh.Indexes.Size();
s.numElements = 0;
s.MeshLocation.StartElementIndex = Mesh.Indexes.Size();
s.MeshLocation.NumElements = 0;
if (s.Type == ST_CEILING)
{
@ -350,7 +353,7 @@ void DoomLevelSubmesh::CreateIndexes()
Mesh.Indexes.Push(pos + j - 1);
Mesh.Indexes.Push(pos + j);
Mesh.SurfaceIndexes.Push((int)i);
s.numElements += 3;
s.MeshLocation.NumElements += 3;
}
}
}
@ -364,7 +367,7 @@ void DoomLevelSubmesh::CreateIndexes()
Mesh.Indexes.Push(pos + j - 1);
Mesh.Indexes.Push(pos);
Mesh.SurfaceIndexes.Push((int)i);
s.numElements += 3;
s.MeshLocation.NumElements += 3;
}
}
}
@ -376,7 +379,7 @@ void DoomLevelSubmesh::CreateIndexes()
Mesh.Indexes.Push(pos + 1);
Mesh.Indexes.Push(pos + 2);
Mesh.SurfaceIndexes.Push((int)i);
s.numElements += 3;
s.MeshLocation.NumElements += 3;
}
if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[3].fPos()))
{
@ -384,7 +387,7 @@ void DoomLevelSubmesh::CreateIndexes()
Mesh.Indexes.Push(pos + 2);
Mesh.Indexes.Push(pos + 3);
Mesh.SurfaceIndexes.Push((int)i);
s.numElements += 3;
s.MeshLocation.NumElements += 3;
}
}
}
@ -489,7 +492,7 @@ void DoomLevelSubmesh::SetupLightmapUvs(FLevelLocals& doomMap)
for (auto& surface : Surfaces)
{
BuildSurfaceParams(LMTextureSize, LMTextureSize, surface);
SetupTileTransform(LMTextureSize, LMTextureSize, surface);
}
}
@ -520,9 +523,9 @@ void DoomLevelSubmesh::PackLightmapAtlas(int lightmapStartIndex)
surf->AtlasTile.ArrayIndex = lightmapStartIndex + (int)result.pageIndex;
// calculate final texture coordinates
for (int i = 0; i < (int)surf->numVerts; i++)
for (int i = 0; i < (int)surf->MeshLocation.NumVerts; i++)
{
auto& vertex = Mesh.Vertices[surf->startVertIndex + i];
auto& vertex = Mesh.Vertices[surf->MeshLocation.StartVertIndex + i];
vertex.lu = (vertex.lu + x) / (float)LMTextureSize;
vertex.lv = (vertex.lv + y) / (float)LMTextureSize;
vertex.lindex = (float)surf->AtlasTile.ArrayIndex;
@ -539,7 +542,7 @@ BBox DoomLevelSubmesh::GetBoundsFromSurface(const LevelMeshSurface& surface) con
FVector3 low(M_INFINITY, M_INFINITY, M_INFINITY);
FVector3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
for (int i = int(surface.startVertIndex); i < int(surface.startVertIndex) + surface.numVerts; i++)
for (int i = int(surface.MeshLocation.StartVertIndex); i < int(surface.MeshLocation.StartVertIndex) + surface.MeshLocation.NumVerts; i++)
{
for (int j = 0; j < 3; j++)
{
@ -580,41 +583,41 @@ DoomLevelSubmesh::PlaneAxis DoomLevelSubmesh::BestAxis(const FVector4& p)
return AXIS_XY;
}
void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface)
void DoomLevelSubmesh::SetupTileTransform(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface)
{
BBox bounds = GetBoundsFromSurface(surface);
surface.bounds = bounds;
surface.Bounds = bounds;
if (surface.sampleDimension <= 0)
if (surface.SampleDimension <= 0)
{
surface.sampleDimension = LightmapSampleDistance;
surface.SampleDimension = LightmapSampleDistance;
}
surface.sampleDimension = uint16_t(max(int(roundf(float(surface.sampleDimension) / max(1.0f / 4, float(lm_scale)))), 1));
surface.SampleDimension = uint16_t(max(int(roundf(float(surface.SampleDimension) / max(1.0f / 4, float(lm_scale)))), 1));
{
// Round to nearest power of two
uint32_t n = uint16_t(surface.sampleDimension);
uint32_t n = uint16_t(surface.SampleDimension);
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n = (n + 1) >> 1;
surface.sampleDimension = uint16_t(n) ? uint16_t(n) : uint16_t(0xFFFF);
surface.SampleDimension = uint16_t(n) ? uint16_t(n) : uint16_t(0xFFFF);
}
// round off dimensions
FVector3 roundedSize;
for (int i = 0; i < 3; i++)
{
bounds.min[i] = surface.sampleDimension * (floor(bounds.min[i] / surface.sampleDimension) - 1);
bounds.max[i] = surface.sampleDimension * (ceil(bounds.max[i] / surface.sampleDimension) + 1);
roundedSize[i] = (bounds.max[i] - bounds.min[i]) / surface.sampleDimension;
bounds.min[i] = surface.SampleDimension * (floor(bounds.min[i] / surface.SampleDimension) - 1);
bounds.max[i] = surface.SampleDimension * (ceil(bounds.max[i] / surface.SampleDimension) + 1);
roundedSize[i] = (bounds.max[i] - bounds.min[i]) / surface.SampleDimension;
}
FVector3 tCoords[2] = { FVector3(0.0f, 0.0f, 0.0f), FVector3(0.0f, 0.0f, 0.0f) };
PlaneAxis axis = BestAxis(surface.plane);
PlaneAxis axis = BestAxis(surface.Plane);
int width;
int height;
@ -624,22 +627,22 @@ void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMap
case AXIS_YZ:
width = (int)roundedSize.Y;
height = (int)roundedSize.Z;
tCoords[0].Y = 1.0f / surface.sampleDimension;
tCoords[1].Z = 1.0f / surface.sampleDimension;
tCoords[0].Y = 1.0f / surface.SampleDimension;
tCoords[1].Z = 1.0f / surface.SampleDimension;
break;
case AXIS_XZ:
width = (int)roundedSize.X;
height = (int)roundedSize.Z;
tCoords[0].X = 1.0f / surface.sampleDimension;
tCoords[1].Z = 1.0f / surface.sampleDimension;
tCoords[0].X = 1.0f / surface.SampleDimension;
tCoords[1].Z = 1.0f / surface.SampleDimension;
break;
case AXIS_XY:
width = (int)roundedSize.X;
height = (int)roundedSize.Y;
tCoords[0].X = 1.0f / surface.sampleDimension;
tCoords[1].Y = 1.0f / surface.sampleDimension;
tCoords[0].X = 1.0f / surface.SampleDimension;
tCoords[1].Y = 1.0f / surface.SampleDimension;
break;
}
@ -657,18 +660,19 @@ void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMap
height = (lightMapTextureHeight - 2);
}
surface.translateWorldToLocal = bounds.min;
surface.projLocalToU = tCoords[0];
surface.projLocalToV = tCoords[1];
surface.TileTransform.TranslateWorldToLocal = bounds.min;
surface.TileTransform.ProjLocalToU = tCoords[0];
surface.TileTransform.ProjLocalToV = tCoords[1];
for (int i = 0; i < surface.numVerts; i++)
for (int i = 0; i < surface.MeshLocation.NumVerts; i++)
{
FVector3 tDelta = Mesh.Vertices[surface.startVertIndex + i].fPos() - surface.translateWorldToLocal;
FVector3 tDelta = Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].fPos() - surface.TileTransform.TranslateWorldToLocal;
Mesh.Vertices[surface.startVertIndex + i].lu = (tDelta | surface.projLocalToU);
Mesh.Vertices[surface.startVertIndex + i].lv = (tDelta | surface.projLocalToV);
Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].lu = (tDelta | surface.TileTransform.ProjLocalToU);
Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].lv = (tDelta | surface.TileTransform.ProjLocalToV);
}
#if 0
// project tCoords so they lie on the plane
const FVector4& plane = surface.plane;
float d = ((bounds.min | FVector3(plane.X, plane.Y, plane.Z)) - plane.W) / plane[axis]; //d = (plane->PointToDist(bounds.min)) / plane->Normal()[axis];
@ -678,6 +682,7 @@ void DoomLevelSubmesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMap
d = (tCoords[i] | FVector3(plane.X, plane.Y, plane.Z)) / plane[axis]; //d = dot(tCoords[i], plane->Normal()) / plane->Normal()[axis];
tCoords[i][axis] -= d;
}
#endif
surface.AtlasTile.Width = width;
surface.AtlasTile.Height = height;

View file

@ -25,18 +25,15 @@ struct DoomLevelMeshSurface : public LevelMeshSurface
side_t* Side = nullptr;
sector_t* ControlSector = nullptr;
FFlatVertex* Vertices = nullptr;
int PipelineID = 0;
};
class DoomLevelSubmesh : public LevelSubmesh
{
public:
DoomLevelSubmesh(DoomLevelMesh* mesh) : LevelMesh(mesh) { }
DoomLevelSubmesh(DoomLevelMesh* mesh, FLevelLocals& doomMap, bool staticMesh);
void CreateStatic(FLevelLocals& doomMap);
void CreateDynamic(FLevelLocals& doomMap);
void UpdateDynamic(FLevelLocals& doomMap, int lightmapStartIndex);
void Update(FLevelLocals& doomMap, int lightmapStartIndex);
LevelMeshSurface* GetSurface(int index) override { return &Surfaces[index]; }
unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const override { return (unsigned int)(ptrdiff_t)(static_cast<const DoomLevelMeshSurface*>(surface) - Surfaces.Data()); }
@ -98,7 +95,7 @@ private:
static PlaneAxis BestAxis(const FVector4& p);
BBox GetBoundsFromSurface(const LevelMeshSurface& surface) const;
void BuildSurfaceParams(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface);
void SetupTileTransform(int lightMapTextureWidth, int lightMapTextureHeight, LevelMeshSurface& surface);
static bool IsDegenerate(const FVector3& v0, const FVector3& v1, const FVector3& v2);
@ -107,6 +104,7 @@ private:
static FVector4 ToFVector4(const DVector4& v) { return FVector4((float)v.X, (float)v.Y, (float)v.Z, (float)v.W); }
DoomLevelMesh* LevelMesh = nullptr;
bool StaticMesh = true;
};
static_assert(alignof(FVector2) == alignof(float[2]) && sizeof(FVector2) == sizeof(float) * 2);

View file

@ -246,7 +246,7 @@ static int CreateIndexedSectorVerticesLM(FRenderState& renderstate, sector_t* se
DoomLevelMeshSurface* lightmap = sub->surface[h].Size() > lightmapIndex ? sub->surface[h][lightmapIndex] : nullptr;
if (lightmap && lightmap->Type != ST_NONE) // surface may be missing if the subsector is degenerate triangle
{
FFlatVertex* luvs = lightmap->Vertices;
FFlatVertex* luvs = &lightmap->Submesh->Mesh.Vertices[lightmap->MeshLocation.StartVertIndex];
for (unsigned int j = 0; j < sub->numlines; j++)
{
SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline[j].v1, plane, luvs[j].lu, luvs[j].lv, luvs[j].lindex);

View file

@ -541,7 +541,7 @@ void HWDrawInfo::UpdateLightmaps()
{
for (auto& e : static_cast<DoomLevelSubmesh*>(level.levelMesh->StaticMesh.get())->Surfaces)
{
if (e.NeedsUpdate && !e.bSky && !e.portalIndex)
if (e.NeedsUpdate && !e.IsSky && !e.PortalIndex)
{
VisibleSurfaces.Push(&e);

View file

@ -241,7 +241,7 @@ public:
return;
}
if (surface->NeedsUpdate && !surface->portalIndex && !surface->bSky)
if (surface->NeedsUpdate && !surface->PortalIndex && !surface->IsSky)
{
VisibleSurfaces.Push(surface);
}

View file

@ -910,13 +910,14 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
}
texcoord srclightuv[4];
if (surface && surface->Type != ST_NONE && surface->numVerts != 0)
if (surface && surface->Type != ST_NONE && surface->MeshLocation.NumVerts >= 4)
{
srclightuv[0] = { surface->Vertices[0].lu, surface->Vertices[0].lv };
srclightuv[1] = { surface->Vertices[1].lu, surface->Vertices[1].lv };
srclightuv[2] = { surface->Vertices[2].lu, surface->Vertices[2].lv };
srclightuv[3] = { surface->Vertices[3].lu, surface->Vertices[3].lv };
lindex = surface->Vertices[0].lindex;
FFlatVertex* vertices = &surface->Submesh->Mesh.Vertices[surface->MeshLocation.StartVertIndex];
srclightuv[0] = { vertices[0].lu, vertices[0].lv };
srclightuv[1] = { vertices[1].lu, vertices[1].lv };
srclightuv[2] = { vertices[2].lu, vertices[2].lv };
srclightuv[3] = { vertices[3].lu, vertices[3].lv };
lindex = vertices[0].lindex;
}
else
{
@ -1674,11 +1675,12 @@ void HWWall::BuildFFBlock(HWWallDispatcher *di, FRenderState& state, seg_t * seg
texcoord srclightuv[4];
if (surface && surface->Type != ST_NONE)
{
srclightuv[0] = { surface->Vertices[0].lu, surface->Vertices[0].lv };
srclightuv[1] = { surface->Vertices[1].lu, surface->Vertices[1].lv };
srclightuv[2] = { surface->Vertices[2].lu, surface->Vertices[2].lv };
srclightuv[3] = { surface->Vertices[3].lu, surface->Vertices[3].lv };
lindex = surface->Vertices[0].lindex;
FFlatVertex* vertices = &surface->Submesh->Mesh.Vertices[surface->MeshLocation.StartVertIndex];
srclightuv[0] = { vertices[0].lu, vertices[0].lv };
srclightuv[1] = { vertices[1].lu, vertices[1].lv };
srclightuv[2] = { vertices[2].lu, vertices[2].lv };
srclightuv[3] = { vertices[3].lu, vertices[3].lv };
lindex = vertices[0].lindex;
}
else
{