ZDRay lump loading adjustments

This commit is contained in:
Magnus Norddahl 2024-01-16 12:42:58 +01:00
commit ee7771f71f
8 changed files with 283 additions and 247 deletions

View file

@ -3012,7 +3012,14 @@ void MapLoader::InitLevelMesh(MapData* map)
Level->levelMesh = new DoomLevelMesh(*Level);
// Lightmap binding/loading
LoadLightmap(map);
if (!LoadLightmap(map))
{
if (Level->lightmaps)
{
Level->levelMesh->StaticMesh->SetupTileTransforms();
Level->levelMesh->StaticMesh->PackLightmapAtlas(0);
}
}
}
bool MapLoader::LoadLightmap(MapData* map)
@ -3025,12 +3032,12 @@ bool MapLoader::LoadLightmap(MapData* map)
return false;
int version = fr.ReadInt32();
if (version < 2)
if (version < 3)
{
Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n");
return false;
}
else if (version != 2)
else if (version != 3)
{
Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n");
return false;
@ -3038,14 +3045,13 @@ bool MapLoader::LoadLightmap(MapData* map)
uint32_t numTiles = fr.ReadUInt32();
uint32_t numTexPixels = fr.ReadUInt32();
uint32_t numTexCoords = fr.ReadUInt32(); // To do: remove from a future version of the format. We don't need this.
if (developer >= 5)
{
Printf("LoadLightmap: Tiles: %u, Pixels: %u, UVs: %u\n", numTiles, numTexPixels, numTexCoords);
Printf("LoadLightmap: Tiles: %u, Pixels: %u\n", numTiles, numTexPixels);
}
if (numTiles == 0 || numTexCoords == 0 || numTexPixels == 0)
if (numTiles == 0 || numTexPixels == 0)
return false;
int errors = 0;
@ -3058,9 +3064,9 @@ bool MapLoader::LoadLightmap(MapData* map)
uint32_t controlSector; // 0xFFFFFFFF is none
uint16_t width, height; // in pixels
uint32_t pixelsOffset; // offset in pixels array
uint32_t uvCount, uvOffset;
DoomLevelMeshSurface* targetSurface;
FVector3 translateWorldToLocal;
FVector3 projLocalToU;
FVector3 projLocalToV;
};
TArray<TileEntry> tileEntries;
@ -3076,8 +3082,15 @@ bool MapLoader::LoadLightmap(MapData* map)
entry.width = fr.ReadUInt16();
entry.height = fr.ReadUInt16();
entry.pixelsOffset = fr.ReadUInt32();
entry.uvCount = fr.ReadUInt32();
entry.uvOffset = fr.ReadUInt32();
entry.translateWorldToLocal.X = fr.ReadFloat();
entry.translateWorldToLocal.Y = fr.ReadFloat();
entry.translateWorldToLocal.Z = fr.ReadFloat();
entry.projLocalToU.X = fr.ReadFloat();
entry.projLocalToU.Y = fr.ReadFloat();
entry.projLocalToU.Z = fr.ReadFloat();
entry.projLocalToV.X = fr.ReadFloat();
entry.projLocalToV.Y = fr.ReadFloat();
entry.projLocalToV.Z = fr.ReadFloat();
}
// Load pixels
@ -3086,18 +3099,9 @@ bool MapLoader::LoadLightmap(MapData* map)
uint8_t* data = (uint8_t*)&textureData[0];
fr.Read(data, numTexPixels * 3 * sizeof(uint16_t));
// Load texture coordinates
// TArray<FVector2> zdrayUvs;
// zdrayUvs.Resize(numTexCoords);
// fr.Read(&zdrayUvs[0], numTexCoords * 2 * sizeof(float));
auto submesh = Level->levelMesh->StaticMesh.get();
const auto textureSize = submesh->LMTextureSize;
// Start with empty lightmap textures
submesh->LMTextureData.Resize(submesh->LMTextureCount * textureSize * textureSize * 3);
memset(submesh->LMTextureData.Data(), 0, submesh->LMTextureData.Size() * sizeof(uint16_t));
// Create lookup for finding tiles
std::map<LightmapTileBinding, LightmapTile*> levelTiles;
for (LightmapTile& tile : submesh->LightmapTiles)
@ -3105,7 +3109,8 @@ bool MapLoader::LoadLightmap(MapData* map)
levelTiles[tile.Binding] = &tile;
}
// Bind tiles and copy their pixels to the texture
// Bind tiles and use the lump's tile transform
TArray<std::pair<const TileEntry*, LightmapTile*>> foundBindings;
for (const TileEntry& entry : tileEntries)
{
LightmapTileBinding binding;
@ -3122,34 +3127,58 @@ bool MapLoader::LoadLightmap(MapData* map)
continue;
}
LightmapTile* tile = it->second;
// To do: add transform info to the lump so that we can stretch the pixels as the lump lightmapper might be using fixed point coordinates that could cause alignment issues
if (tile->AtlasLocation.Width != entry.width || tile->AtlasLocation.Height != entry.height)
if (entry.width == 0 || entry.height == 0)
{
if (errors < 10 && developer >= 1)
Printf("Lightmap tile size mismatch (type = %d, index = %d, control sector = %d)\n", entry.type, entry.typeIndex, entry.controlSector);
Printf("Invalid lightmap tile found (type = %d, index = %d, control sector = %d)\n", entry.type, entry.typeIndex, entry.controlSector);
errors++;
continue;
}
const uint16_t* src = textureData.Data() + entry.pixelsOffset;
LightmapTile* tile = it->second;
tile->AtlasLocation.Width = entry.width;
tile->AtlasLocation.Height = entry.height;
tile->Transform.TranslateWorldToLocal = entry.translateWorldToLocal;
tile->Transform.ProjLocalToU = entry.projLocalToU;
tile->Transform.ProjLocalToV = entry.projLocalToV;
tile->NeedsUpdate = false;
foundBindings.Push({ &entry, tile });
}
// Setup the tile transform for any tile missing in the lump (shouldn't be any, but if there are we let the lightmapper bake them)
for (auto& tile : submesh->LightmapTiles)
{
if (tile.NeedsUpdate)
tile.SetupTileTransform(submesh->LMTextureSize);
}
// Place all tiles in atlas textures
submesh->PackLightmapAtlas(0);
// Start with empty lightmap textures
submesh->LMTextureData.Resize(submesh->LMTextureCount * textureSize * textureSize * 3);
memset(submesh->LMTextureData.Data(), 0, submesh->LMTextureData.Size() * sizeof(uint16_t));
// Copy tile pixels to the texture
for (auto& binding : foundBindings)
{
const TileEntry* entry = binding.first;
LightmapTile* tile = binding.second;
const uint16_t* src = textureData.Data() + entry->pixelsOffset;
uint16_t* dst = &submesh->LMTextureData[tile->AtlasLocation.ArrayIndex * textureSize * textureSize * 3];
int destx = tile->AtlasLocation.X;
int desty = tile->AtlasLocation.Y;
int width = tile->AtlasLocation.Width;
int height = tile->AtlasLocation.Height;
int x = tile->AtlasLocation.X;
int y = tile->AtlasLocation.Y;
int w = tile->AtlasLocation.Width;
int h = tile->AtlasLocation.Height;
for (int yy = 0; yy < w; yy++)
for (int yy = 0; yy < height; yy++)
{
const uint16_t* srcline = src + yy * w * 3;
uint16_t* dstline = dst + (x + yy * textureSize) * 3;
for (int xx = 0, end = w * 3; xx < end; xx++)
{
dstline[xx] = srcline[xx];
}
uint16_t* dstline = dst + (destx + (desty + yy) * textureSize) * 3;
const uint16_t* srcline = src + yy * (width * 3);
memcpy(dstline, srcline, width * 6);
}
tile->NeedsUpdate = false;