mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-29 07:12:36 +00:00
Initial implementation for lightmap lump loading
This commit is contained in:
parent
2b4db4c601
commit
537cd7790d
10 changed files with 354 additions and 35 deletions
|
@ -192,11 +192,12 @@ public:
|
||||||
|
|
||||||
virtual void UpdateLightLists() { }
|
virtual void UpdateLightLists() { }
|
||||||
|
|
||||||
TArray<LevelMeshSmoothingGroup> SmoothingGroups; // TODO fill
|
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
|
||||||
TArray<LevelMeshPortal> Portals; // TODO fill
|
TArray<LevelMeshPortal> Portals;
|
||||||
|
|
||||||
int LMTextureCount = 0;
|
int LMTextureCount = 0;
|
||||||
int LMTextureSize = 0;
|
int LMTextureSize = 0;
|
||||||
|
TArray<uint16_t> LMTextureData; // TODO better place for this?
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -189,17 +189,17 @@ void VkTextureManager::CreateLightmap()
|
||||||
SetLightmap(1, 1, data);
|
SetLightmap(1, 1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount)
|
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData)
|
||||||
{
|
{
|
||||||
if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount)
|
if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LMTextureSize = newLMTextureSize;
|
LMTextureSize = newLMTextureSize;
|
||||||
LMTextureCount = newLMTextureCount;
|
LMTextureCount = newLMTextureCount;
|
||||||
|
|
||||||
int w = LMTextureSize;
|
int w = newLMTextureSize;
|
||||||
int h = LMTextureSize;
|
int h = newLMTextureSize;
|
||||||
int count = LMTextureCount;
|
int count = newLMTextureCount;
|
||||||
int pixelsize = 8;
|
int pixelsize = 8;
|
||||||
|
|
||||||
Lightmap.Reset(fb);
|
Lightmap.Reset(fb);
|
||||||
|
@ -219,6 +219,47 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
|
||||||
|
|
||||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||||
|
|
||||||
|
if (newPixelData.Size() >= w * h * count * 3)
|
||||||
|
{
|
||||||
|
assert(newPixelData.Size() == w * h * count * 3);
|
||||||
|
|
||||||
|
int totalSize = w * h * count * pixelsize;
|
||||||
|
|
||||||
|
auto stagingBuffer = BufferBuilder()
|
||||||
|
.Size(totalSize)
|
||||||
|
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||||
|
.DebugName("VkHardwareTexture.mStagingBuffer")
|
||||||
|
.Create(fb->GetDevice());
|
||||||
|
|
||||||
|
uint16_t one = 0x3c00; // half-float 1.0
|
||||||
|
const uint16_t* src = newPixelData.Data();
|
||||||
|
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
|
||||||
|
for (int i = w * h * count; i > 0; i--)
|
||||||
|
{
|
||||||
|
*(data++) = *(src++);
|
||||||
|
*(data++) = *(src++);
|
||||||
|
*(data++) = *(src++);
|
||||||
|
*(data++) = one;
|
||||||
|
}
|
||||||
|
stagingBuffer->Unmap();
|
||||||
|
|
||||||
|
VkImageTransition()
|
||||||
|
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, count)
|
||||||
|
.Execute(cmdbuffer);
|
||||||
|
|
||||||
|
VkBufferImageCopy region = {};
|
||||||
|
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
region.imageSubresource.layerCount = count;
|
||||||
|
region.imageExtent.depth = 1;
|
||||||
|
region.imageExtent.width = w;
|
||||||
|
region.imageExtent.height = h;
|
||||||
|
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||||
|
|
||||||
|
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||||
|
|
||||||
|
newPixelData.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
VkImageTransition()
|
VkImageTransition()
|
||||||
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count)
|
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count)
|
||||||
.Execute(cmdbuffer);
|
.Execute(cmdbuffer);
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
|
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
|
|
||||||
void CreateLightmap(int LMTextureSize, int LMTextureCount);
|
void CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData);
|
||||||
void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData);
|
void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData);
|
||||||
|
|
||||||
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
||||||
|
|
|
@ -474,7 +474,7 @@ void VulkanRenderDevice::BeginFrame()
|
||||||
if (levelMesh && levelMesh->GetSurfaceCount() > 0)
|
if (levelMesh && levelMesh->GetSurfaceCount() > 0)
|
||||||
{
|
{
|
||||||
levelMesh->UpdateLightLists();
|
levelMesh->UpdateLightLists();
|
||||||
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount);
|
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData));
|
||||||
GetLightmap()->SetLevelMesh(levelMesh);
|
GetLightmap()->SetLevelMesh(levelMesh);
|
||||||
|
|
||||||
#if 0 // full lightmap generation
|
#if 0 // full lightmap generation
|
||||||
|
|
|
@ -93,6 +93,7 @@ enum
|
||||||
|
|
||||||
CVAR (Bool, genblockmap, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG);
|
CVAR (Bool, genblockmap, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG);
|
||||||
CVAR (Bool, gennodes, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG);
|
CVAR (Bool, gennodes, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG);
|
||||||
|
CVAR (Bool, genlightmaps, true, CVAR_GLOBALCONFIG);
|
||||||
|
|
||||||
inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int *numthings)
|
inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int *numthings)
|
||||||
{
|
{
|
||||||
|
@ -2938,7 +2939,7 @@ void MapLoader::CalcIndices()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void MapLoader::InitLevelMesh()
|
void MapLoader::InitLevelMesh(MapData* map)
|
||||||
{
|
{
|
||||||
// Propagate sample distance where it isn't yet set
|
// Propagate sample distance where it isn't yet set
|
||||||
for (auto& line : Level->lines)
|
for (auto& line : Level->lines)
|
||||||
|
@ -2960,9 +2961,281 @@ void MapLoader::InitLevelMesh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last chance to make up our mind whether to use lightmaps or not
|
||||||
|
if (!Level->lightmaps)
|
||||||
|
{
|
||||||
|
if (map->Size(ML_LIGHTMAP))
|
||||||
|
{
|
||||||
|
Level->lightmaps = true;
|
||||||
|
Printf(PRINT_HIGH, "InitLevelMesh: The level contains LIGHTMAP, but no ZDRayInfo thing was detected in the level.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Level->lightmaps = *genlightmaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Levelmesh and lightmap binding/loading
|
||||||
Level->levelMesh = new DoomLevelMesh(*Level);
|
Level->levelMesh = new DoomLevelMesh(*Level);
|
||||||
Level->lightmaps = true;
|
|
||||||
|
if (Level->lightmaps)
|
||||||
|
{
|
||||||
|
LoadLightmap(map);
|
||||||
|
Level->levelMesh->BindLightmapSurfacesToGeometry(*Level);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Level->levelMesh->Surfaces.Clear(); // Temp hack that disables lightmapping
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapLoader::LoadLightmap(MapData* map)
|
||||||
|
{
|
||||||
|
if (!map->Size(ML_LIGHTMAP))
|
||||||
|
return;
|
||||||
|
|
||||||
|
FileReader fr;
|
||||||
|
if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB, false, true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int version = fr.ReadInt32();
|
||||||
|
if (version == 0)
|
||||||
|
{
|
||||||
|
Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported alpha version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (version != 1)
|
||||||
|
{
|
||||||
|
Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t textureSize = fr.ReadUInt16();
|
||||||
|
uint16_t numTextures = fr.ReadUInt16();
|
||||||
|
uint32_t numSurfaces = fr.ReadUInt32();
|
||||||
|
uint32_t numTexCoords = fr.ReadUInt32();
|
||||||
|
uint32_t numSubsectors = fr.ReadUInt32();
|
||||||
|
uint32_t numTexBytes = numTextures * textureSize * textureSize * 3 * 2;
|
||||||
|
if (numSurfaces == 0 || numTexCoords == 0 || numTexBytes == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float sunDir[3], sunColor[3];
|
||||||
|
fr.Read(sunDir, sizeof(float) * 3);
|
||||||
|
fr.Read(sunColor, sizeof(float) * 3);
|
||||||
|
Level->SunDirection = FVector3(sunDir);
|
||||||
|
Level->SunColor = FVector3(sunColor);
|
||||||
|
|
||||||
|
/*if (numSubsectors != Level->subsectors.Size())
|
||||||
|
{
|
||||||
|
Printf(PRINT_HIGH, "LoadLightmap: subsector count for level doesn't match (%d in wad vs %d in engine)\n", (int)numSubsectors, (int)Level->subsectors.Size());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//Level->LMTexCoords.Resize(numTexCoords * 2);
|
||||||
|
|
||||||
|
// Allocate room for all surfaces
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
unsigned int allSurfaces = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < Level->sides.Size(); i++)
|
||||||
|
allSurfaces += 4 + Level->sides[i].sector->e->XFloor.ffloors.Size();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < Level->subsectors.Size(); i++)
|
||||||
|
allSurfaces += 2 + Level->subsectors[i].sector->e->XFloor.ffloors.Size() * 2;
|
||||||
|
|
||||||
|
Level->LMSurfaces.Resize(allSurfaces);
|
||||||
|
memset(&Level->LMSurfaces[0], 0, sizeof(LightmapSurface) * allSurfaces);
|
||||||
|
|
||||||
|
// Link the surfaces to sectors, sides and their 3D floors
|
||||||
|
|
||||||
|
unsigned int offset = 0;
|
||||||
|
for (unsigned int i = 0; i < Level->sides.Size(); i++)
|
||||||
|
{
|
||||||
|
auto& side = Level->sides[i];
|
||||||
|
side.lightmap = &Level->LMSurfaces[offset];
|
||||||
|
offset += 4 + side.sector->e->XFloor.ffloors.Size();
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < Level->subsectors.Size(); i++)
|
||||||
|
{
|
||||||
|
auto& subsector = Level->subsectors[i];
|
||||||
|
unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size();
|
||||||
|
subsector.lightmap[0] = &Level->LMSurfaces[offset];
|
||||||
|
subsector.lightmap[1] = &Level->LMSurfaces[offset + count];
|
||||||
|
offset += count * 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool errors = false;
|
||||||
|
|
||||||
|
// Load the surfaces we have lightmap data for
|
||||||
|
|
||||||
|
// TODO more optimized way:
|
||||||
|
auto findSurfaceIndex = [&](int type, int index, const sector_t* sec) {
|
||||||
|
const auto& surfaces = Level->levelMesh->Surfaces;
|
||||||
|
for (unsigned i = 0, count = surfaces.Size(); i < count; ++i)
|
||||||
|
{
|
||||||
|
if (surfaces[i].Type == type && surfaces[i].typeIndex == index && sec == surfaces[i].ControlSector)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0xffffffff;
|
||||||
|
};
|
||||||
|
|
||||||
|
TArray<DoomLevelMeshSurface> zdraySurfaces;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numSurfaces; i++)
|
||||||
|
{
|
||||||
|
LevelMeshSurfaceType type = (LevelMeshSurfaceType)fr.ReadUInt32();
|
||||||
|
uint32_t typeIndex = fr.ReadUInt32();
|
||||||
|
uint32_t controlSectorIndex = fr.ReadUInt32();
|
||||||
|
uint32_t lightmapNum = fr.ReadUInt32();
|
||||||
|
uint32_t firstTexCoord = fr.ReadUInt32();
|
||||||
|
|
||||||
|
auto controlSector = controlSectorIndex < Level->sectors.Size() ? &Level->sectors[controlSectorIndex] : nullptr;
|
||||||
|
|
||||||
|
// Check against the internal levelmesh
|
||||||
|
|
||||||
|
if (i >= Level->levelMesh->Surfaces.Size())
|
||||||
|
{
|
||||||
|
errors = true;
|
||||||
|
if (*developer >= 1)
|
||||||
|
{
|
||||||
|
Printf(PRINT_HIGH, "Lightmap lump surface index %d is out of bounds\n", i);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto levelSurface = &Level->levelMesh->Surfaces[i];
|
||||||
|
|
||||||
|
if (levelSurface->Type != type || levelSurface->typeIndex != typeIndex || levelSurface->ControlSector != controlSector)
|
||||||
|
{
|
||||||
|
auto internalIndex = findSurfaceIndex(type, typeIndex, controlSector);
|
||||||
|
|
||||||
|
if (internalIndex < Level->levelMesh->Surfaces.Size())
|
||||||
|
{
|
||||||
|
levelSurface = &Level->levelMesh->Surfaces[internalIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errors = true;
|
||||||
|
if (*developer >= 1)
|
||||||
|
{
|
||||||
|
Printf(PRINT_HIGH, "Lightmap lump surface %d mismatch. Couldn't find surface type:%d, typeindex:%d, controlsector:%d\n", i, type, typeIndex, controlSectorIndex);
|
||||||
|
}
|
||||||
|
// TODO detailed printout
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoomLevelMeshSurface surface;
|
||||||
|
|
||||||
|
surface.startUvIndex = firstTexCoord;
|
||||||
|
surface.typeIndex = typeIndex;
|
||||||
|
surface.ControlSector = controlSector;
|
||||||
|
surface.Type = type;
|
||||||
|
surface.numVerts = levelSurface->numVerts;
|
||||||
|
surface.atlasPageIndex = lightmapNum;
|
||||||
|
|
||||||
|
|
||||||
|
zdraySurfaces.Push(surface);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (type == ST_CEILING || type == ST_FLOOR)
|
||||||
|
{
|
||||||
|
surface.Subsector = &Level->subsectors[typeIndex];
|
||||||
|
surface.Subsector->firstline->sidedef->sector->HasLightmaps = true;
|
||||||
|
SetSubsectorLightmap(surface);
|
||||||
|
}
|
||||||
|
else if (type != ST_NULL)
|
||||||
|
{
|
||||||
|
surface.Side = &Level->sides[typeIndex];
|
||||||
|
SetSideLightmap(surface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load texture coordinates
|
||||||
|
TArray<FVector2> zdrayUvs;
|
||||||
|
zdrayUvs.Resize(numTexCoords);
|
||||||
|
fr.Read(&zdrayUvs[0], numTexCoords * 2 * sizeof(float));
|
||||||
|
|
||||||
|
// Load lightmap textures
|
||||||
|
Level->levelMesh->LMTextureData.Resize(Level->levelMesh->LMTextureCount* Level->levelMesh->LMTextureSize * Level->levelMesh->LMTextureSize * 3);
|
||||||
|
|
||||||
|
TArray<uint16_t> textureData;
|
||||||
|
textureData.Resize((numTexBytes + 1) / 2);
|
||||||
|
uint8_t* data = (uint8_t*)&textureData[0];
|
||||||
|
fr.Read(data, numTexBytes);
|
||||||
|
|
||||||
|
// Remap the ZDRay atlas into internal lightmapper
|
||||||
|
for (auto& surface : zdraySurfaces)
|
||||||
|
{
|
||||||
|
auto& realSurface = Level->levelMesh->Surfaces[findSurfaceIndex(surface.Type, surface.typeIndex, surface.ControlSector)];
|
||||||
|
|
||||||
|
// what are the pixel boundaries in the atlas?
|
||||||
|
BBox bbox;
|
||||||
|
for (int i = 0; i < surface.numVerts; ++i)
|
||||||
|
{
|
||||||
|
auto& uv = zdrayUvs[surface.startUvIndex + i];
|
||||||
|
bbox.AddPoint(FVector3(uv.X, uv.Y, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate pixel positions
|
||||||
|
int srcMinX = (int)floorf(bbox.min.X * textureSize - 1.0f);
|
||||||
|
int srcMinY = (int)floorf(bbox.min.Y * textureSize - 1.0f);
|
||||||
|
int srcMaxX = (int)ceilf(bbox.max.X * textureSize + 1.0f);
|
||||||
|
int srcMaxY = (int)ceilf(bbox.max.Y * textureSize + 1.0f);
|
||||||
|
int srcPage = surface.atlasPageIndex;
|
||||||
|
int srcW = srcMaxX - srcMinX;
|
||||||
|
int srcH = srcMaxY - srcMinY;
|
||||||
|
|
||||||
|
// Now let's check
|
||||||
|
|
||||||
|
int dstX = realSurface.atlasX;
|
||||||
|
int dstY = realSurface.atlasY;
|
||||||
|
int dstPage = realSurface.atlasPageIndex;
|
||||||
|
|
||||||
|
// Sanity checks
|
||||||
|
if (srcMinX < 0 || srcMinY < 0 || dstX < 0 || dstY < 0 || srcMaxX >= textureSize || srcMaxY >= textureSize || dstX + srcW >= textureSize || dstY + srcH >= textureSize || srcPage >= numTextures || dstPage >= Level->levelMesh->LMTextureCount)
|
||||||
|
{
|
||||||
|
errors = true;
|
||||||
|
if (*developer >= 1)
|
||||||
|
{
|
||||||
|
Printf("Can't remap lightmap surface ((%d, %d), (%d, %d), %d) -> ((%d, %d), (%d, %d), %d)\n", srcMinX, srcMinY, srcMaxX, srcMaxY, srcPage, dstX, dstY, dstX + srcW, dstY + srcH, dstPage);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy pixels
|
||||||
|
uint16_t* src = &textureData[0];
|
||||||
|
uint16_t* dst = &Level->levelMesh->LMTextureData[0];
|
||||||
|
|
||||||
|
for (int y = srcMinY, y2 = dstY; y < srcMaxY; ++y, ++y2)
|
||||||
|
{
|
||||||
|
for (int x = srcMinX, x2 = dstX; x < srcMaxX; ++x, ++x2)
|
||||||
|
{
|
||||||
|
int index = (x + y * textureSize + srcPage * textureSize * textureSize) * 3;
|
||||||
|
int dstIndex = (x2 + y2 * textureSize + dstPage * textureSize * textureSize) * 3;
|
||||||
|
|
||||||
|
dst[dstIndex] = src[index];
|
||||||
|
dst[dstIndex + 1] = src[index + 1];
|
||||||
|
dst[dstIndex + 2] = src[index + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
realSurface.needsUpdate = false; // this surface is good
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors && developer <= 0)
|
||||||
|
{
|
||||||
|
Printf(PRINT_HIGH, "Pre-calculated LIGHTMAP surfaces do not match current level surfaces. Restart this level with 'developer 1' for further details.\nPerhaps you forget to rebuild lightmaps after modifying the map?");
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
// Apply compression predictor
|
||||||
|
for (uint32_t i = 1; i < numTexBytes; i++)
|
||||||
|
data[i] += data[i - 1];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2979,6 +3252,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
||||||
Level->SunColor = FVector3(1.f, 1.f, 1.f);
|
Level->SunColor = FVector3(1.f, 1.f, 1.f);
|
||||||
Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f);
|
Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f);
|
||||||
Level->LightmapSampleDistance = 16;
|
Level->LightmapSampleDistance = 16;
|
||||||
|
Level->lightmaps = false;
|
||||||
|
|
||||||
// note: most of this ordering is important
|
// note: most of this ordering is important
|
||||||
ForceNodeBuild = gennodes;
|
ForceNodeBuild = gennodes;
|
||||||
|
@ -3258,7 +3532,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
||||||
// set up world state
|
// set up world state
|
||||||
SpawnSpecials();
|
SpawnSpecials();
|
||||||
|
|
||||||
InitLevelMesh();
|
InitLevelMesh(map);
|
||||||
|
|
||||||
// disable reflective planes on sloped sectors.
|
// disable reflective planes on sloped sectors.
|
||||||
for (auto &sec : Level->sectors)
|
for (auto &sec : Level->sectors)
|
||||||
|
|
|
@ -304,7 +304,8 @@ public:
|
||||||
void SetSlopes();
|
void SetSlopes();
|
||||||
void CopySlopes();
|
void CopySlopes();
|
||||||
|
|
||||||
void InitLevelMesh();
|
void InitLevelMesh(MapData* map);
|
||||||
|
void LoadLightmap(MapData* map);
|
||||||
|
|
||||||
void LoadLevel(MapData *map, const char *lumpname, int position);
|
void LoadLevel(MapData *map, const char *lumpname, int position);
|
||||||
|
|
||||||
|
|
|
@ -835,6 +835,7 @@ public:
|
||||||
|
|
||||||
auto pc = pitch.Cos();
|
auto pc = pitch.Cos();
|
||||||
Level->SunDirection = -FVector3 { pc * angle.Cos(), pc * angle.Sin(), -pitch.Sin() }; // [RaveYard]: is there a dedicated function for this?
|
Level->SunDirection = -FVector3 { pc * angle.Cos(), pc * angle.Sin(), -pitch.Sin() }; // [RaveYard]: is there a dedicated function for this?
|
||||||
|
Level->lightmaps = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,18 +95,8 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupLightmapUvs();
|
SetupLightmapUvs();
|
||||||
BindLightmapSurfacesToGeometry(doomMap);
|
|
||||||
|
|
||||||
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
|
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
|
||||||
|
|
||||||
// Runtime stuff
|
|
||||||
for (auto& surface : Surfaces)
|
|
||||||
{
|
|
||||||
if ((surface.Type == ST_FLOOR || surface.Type == ST_CEILING) && surface.ControlSector)
|
|
||||||
{
|
|
||||||
XFloorToSurface[surface.Subsector->sector].Push(&surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoomLevelMesh::CreatePortals()
|
void DoomLevelMesh::CreatePortals()
|
||||||
|
@ -382,6 +372,15 @@ void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
|
||||||
SetSideLightmap(&surface);
|
SetSideLightmap(&surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Runtime helper
|
||||||
|
for (auto& surface : Surfaces)
|
||||||
|
{
|
||||||
|
if ((surface.Type == ST_FLOOR || surface.Type == ST_CEILING) && surface.ControlSector)
|
||||||
|
{
|
||||||
|
XFloorToSurface[surface.Subsector->sector].Push(&surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoomLevelMesh::SetSubsectorLightmap(DoomLevelMeshSurface* surface)
|
void DoomLevelMesh::SetSubsectorLightmap(DoomLevelMeshSurface* surface)
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
|
|
||||||
void CreatePortals();
|
void CreatePortals();
|
||||||
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
|
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
|
||||||
|
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap);
|
||||||
|
|
||||||
bool TraceSky(const FVector3& start, FVector3 direction, float dist)
|
bool TraceSky(const FVector3& start, FVector3 direction, float dist)
|
||||||
{
|
{
|
||||||
|
@ -58,7 +59,6 @@ private:
|
||||||
void CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor);
|
void CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor);
|
||||||
void CreateSideSurfaces(FLevelLocals &doomMap, side_t *side);
|
void CreateSideSurfaces(FLevelLocals &doomMap, side_t *side);
|
||||||
|
|
||||||
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap);
|
|
||||||
void SetSubsectorLightmap(DoomLevelMeshSurface* surface);
|
void SetSubsectorLightmap(DoomLevelMeshSurface* surface);
|
||||||
void SetSideLightmap(DoomLevelMeshSurface* surface);
|
void SetSideLightmap(DoomLevelMeshSurface* surface);
|
||||||
|
|
||||||
|
|
|
@ -504,25 +504,27 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front
|
||||||
//
|
//
|
||||||
// Lightmaps
|
// Lightmaps
|
||||||
//
|
//
|
||||||
|
if (level.lightmaps)
|
||||||
for (int i = 0, count = sector->subsectorcount; i < count; ++i)
|
|
||||||
{
|
{
|
||||||
for (int plane = 0; plane < 2; ++plane)
|
for (int i = 0, count = sector->subsectorcount; i < count; ++i)
|
||||||
{
|
{
|
||||||
if (auto lightmap = sector->subsectors[i]->lightmap[plane][0])
|
for (int plane = 0; plane < 2; ++plane)
|
||||||
{
|
{
|
||||||
state.PushVisibleSurface(lightmap);
|
if (auto lightmap = sector->subsectors[i]->lightmap[plane][0])
|
||||||
|
{
|
||||||
|
state.PushVisibleSurface(lightmap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (auto subsectors = sector->Level->levelMesh->XFloorToSurface.CheckKey(sector))
|
if (auto subsectors = sector->Level->levelMesh->XFloorToSurface.CheckKey(sector))
|
||||||
{
|
|
||||||
for (auto* surface : *subsectors)
|
|
||||||
{
|
{
|
||||||
if (surface)
|
for (auto* surface : *subsectors)
|
||||||
{
|
{
|
||||||
state.PushVisibleSurface(surface);
|
if (surface)
|
||||||
|
{
|
||||||
|
state.PushVisibleSurface(surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue