mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-01 14:20:55 +00:00
Move surface linking into DoomLevelMesh
This commit is contained in:
parent
db5c659fab
commit
45206f2184
4 changed files with 129 additions and 298 deletions
|
@ -3204,15 +3204,12 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
|
||||
SpawnThings(position);
|
||||
|
||||
// Load and link lightmaps - must be done after P_Spawn3DFloors (and SpawnThings? Potentially for baking static model actors?)
|
||||
#if 0
|
||||
if (!ForceNodeBuild)
|
||||
{
|
||||
LoadLightmap(map);
|
||||
}
|
||||
#endif
|
||||
// TODO read from ZDRayInfoThing
|
||||
Level->SunColor = FVector3(1.f, 1.f, 1.f);
|
||||
Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f);
|
||||
|
||||
Level->levelMesh = new DoomLevelMesh(*Level);
|
||||
InitLightmap(map);
|
||||
Level->lightmaps = true;
|
||||
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
|
@ -3266,282 +3263,3 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
|
||||
Level->aabbTree = new DoomLevelAABBTree(Level);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
||||
void MapLoader::SetSubsectorLightmap(const LightmapSurface &surface)
|
||||
{
|
||||
if (!surface.ControlSector)
|
||||
{
|
||||
int index = surface.Type == hwrenderer::ST_CEILING ? 1 : 0;
|
||||
surface.Subsector->lightmap[index][0] = surface;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = surface.Type == hwrenderer::ST_CEILING ? 0 : 1;
|
||||
const auto &ffloors = surface.Subsector->sector->e->XFloor.ffloors;
|
||||
for (unsigned int i = 0; i < ffloors.Size(); i++)
|
||||
{
|
||||
if (ffloors[i]->model == surface.ControlSector)
|
||||
{
|
||||
surface.Subsector->lightmap[index][i + 1] = surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::SetSideLightmap(const LightmapSurface &surface)
|
||||
{
|
||||
if (!surface.ControlSector)
|
||||
{
|
||||
if (surface.Type == hwrenderer::ST_UPPERSIDE)
|
||||
{
|
||||
surface.Side->lightmap[0] = surface;
|
||||
}
|
||||
else if (surface.Type == hwrenderer::ST_MIDDLESIDE)
|
||||
{
|
||||
surface.Side->lightmap[1] = surface;
|
||||
surface.Side->lightmap[2] = surface;
|
||||
}
|
||||
else if (surface.Type == hwrenderer::ST_LOWERSIDE)
|
||||
{
|
||||
surface.Side->lightmap[3] = surface;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &ffloors = surface.Side->sector->e->XFloor.ffloors;
|
||||
for (unsigned int i = 0; i < ffloors.Size(); i++)
|
||||
{
|
||||
if (ffloors[i]->model == surface.ControlSector)
|
||||
{
|
||||
surface.Side->lightmap[4 + i] = surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::BindLightmapSurfacesToGeometry()
|
||||
{
|
||||
// Allocate room for all surfaces
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Copy and build properties
|
||||
size_t index = 0;
|
||||
for (auto& surface : Level->levelMesh->Surfaces)
|
||||
{
|
||||
LightmapSurface l;
|
||||
memset(&l, 0, sizeof(LightmapSurface));
|
||||
|
||||
l.ControlSector = (sector_t*)surface.controlSector;
|
||||
l.Type = surface.type;
|
||||
l.LightmapNum = 0;
|
||||
|
||||
l.TexCoords = (float*) & Level->levelMesh->LightmapUvs[surface.startUvIndex];
|
||||
|
||||
l.LightmapNum = surface.atlasPageIndex;
|
||||
|
||||
if (surface.type == hwrenderer::ST_FLOOR || surface.type == hwrenderer::ST_CEILING)
|
||||
{
|
||||
l.Subsector = &Level->subsectors[surface.typeIndex];
|
||||
if (l.Subsector->firstline && l.Subsector->firstline->sidedef)
|
||||
l.Subsector->firstline->sidedef->sector->HasLightmaps = true;
|
||||
SetSubsectorLightmap(l);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.Side = &Level->sides[surface.typeIndex];
|
||||
SetSideLightmap(l);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MapLoader::InitLightmap(MapData* map)
|
||||
{
|
||||
// We have to reset everything as FLevelLocals is recycled between maps
|
||||
Level->LMSurfaces.Reset();
|
||||
|
||||
// TODO read from ZDRayInfoThing
|
||||
Level->SunColor = FVector3(1.f, 1.f, 1.f);
|
||||
Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f);
|
||||
|
||||
Level->levelMesh->SunColor = Level->SunColor; // TODO keep only one copy?
|
||||
Level->levelMesh->SunDirection = Level->SunDirection;
|
||||
|
||||
Level->lightmaps = true;
|
||||
|
||||
BindLightmapSurfacesToGeometry();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void MapLoader::LoadLightmap(MapData *map)
|
||||
{
|
||||
Level->LMTexCoords.Reset();
|
||||
Level->LMSurfaces.Reset();
|
||||
Level->LMTextureData.Reset();
|
||||
Level->LMTextureCount = 0;
|
||||
Level->LMTextureSize = 0;
|
||||
|
||||
// We have to reset everything as FLevelLocals is recycled between maps
|
||||
|
||||
//if (!Args->CheckParm("-enablelightmaps"))
|
||||
// return; // this feature is still too early WIP to allow general access
|
||||
|
||||
if (!map->Size(ML_LIGHTMAP))
|
||||
return;
|
||||
|
||||
FileReader fr;
|
||||
if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB, false, false))
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Load the surfaces we have lightmap data for
|
||||
|
||||
for (uint32_t i = 0; i < numSurfaces; i++)
|
||||
{
|
||||
LightmapSurface surface;
|
||||
memset(&surface, 0, sizeof(LightmapSurface));
|
||||
|
||||
SurfaceType type = (SurfaceType)fr.ReadUInt32();
|
||||
uint32_t typeIndex = fr.ReadUInt32();
|
||||
uint32_t controlSector = fr.ReadUInt32();
|
||||
uint32_t lightmapNum = fr.ReadUInt32();
|
||||
uint32_t firstTexCoord = fr.ReadUInt32();
|
||||
|
||||
if (controlSector != 0xffffffff)
|
||||
surface.ControlSector = &Level->sectors[controlSector];
|
||||
|
||||
surface.Type = type;
|
||||
surface.LightmapNum = lightmapNum;
|
||||
surface.TexCoords = &Level->LMTexCoords[firstTexCoord * 2];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Load texture coordinates
|
||||
|
||||
fr.Read(&Level->LMTexCoords[0], numTexCoords * 2 * sizeof(float));
|
||||
|
||||
// Load lightmap textures
|
||||
|
||||
Level->LMTextureCount = numTextures;
|
||||
Level->LMTextureSize = textureSize;
|
||||
Level->LMTextureData.Resize((numTexBytes + 1) / 2);
|
||||
uint8_t* data = (uint8_t*)&Level->LMTextureData[0];
|
||||
fr.Read(data, numTexBytes);
|
||||
#if 0
|
||||
// Apply compression predictor
|
||||
for (uint32_t i = 1; i < numTexBytes; i++)
|
||||
data[i] += data[i - 1];
|
||||
#endif
|
||||
}
|
||||
#endif
|
|
@ -304,17 +304,6 @@ public:
|
|||
void SetSlopes();
|
||||
void CopySlopes();
|
||||
|
||||
void SetSubsectorLightmap(const LightmapSurface &surface);
|
||||
void SetSideLightmap(const LightmapSurface &surface);
|
||||
|
||||
// Lightmap
|
||||
#if 0
|
||||
void LoadLightmap(MapData *map);
|
||||
#endif
|
||||
void InitLightmap(MapData* map);
|
||||
void BindLightmapSurfacesToGeometry();
|
||||
|
||||
|
||||
void LoadLevel(MapData *map, const char *lumpname, int position);
|
||||
|
||||
MapLoader(FLevelLocals *lev)
|
||||
|
|
|
@ -30,6 +30,9 @@ CCMD(dumplevelmesh)
|
|||
|
||||
DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
|
||||
{
|
||||
SunColor = doomMap.SunColor; // TODO keep only one copy?
|
||||
SunDirection = doomMap.SunDirection;
|
||||
|
||||
for (unsigned int i = 0; i < doomMap.sides.Size(); i++)
|
||||
{
|
||||
CreateSideSurfaces(doomMap, &doomMap.sides[i]);
|
||||
|
@ -81,9 +84,126 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
|
|||
}
|
||||
}
|
||||
|
||||
BindLightmapSurfacesToGeometry(doomMap);
|
||||
|
||||
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
|
||||
}
|
||||
|
||||
void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
|
||||
{
|
||||
// Allocate room for all surfaces
|
||||
|
||||
unsigned int allSurfaces = 0;
|
||||
|
||||
for (unsigned int i = 0; i < doomMap.sides.Size(); i++)
|
||||
allSurfaces += 4 + doomMap.sides[i].sector->e->XFloor.ffloors.Size();
|
||||
|
||||
for (unsigned int i = 0; i < doomMap.subsectors.Size(); i++)
|
||||
allSurfaces += 2 + doomMap.subsectors[i].sector->e->XFloor.ffloors.Size() * 2;
|
||||
|
||||
doomMap.LMSurfaces.Resize(allSurfaces);
|
||||
memset(&doomMap.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 < doomMap.sides.Size(); i++)
|
||||
{
|
||||
auto& side = doomMap.sides[i];
|
||||
side.lightmap = &doomMap.LMSurfaces[offset];
|
||||
offset += 4 + side.sector->e->XFloor.ffloors.Size();
|
||||
}
|
||||
for (unsigned int i = 0; i < doomMap.subsectors.Size(); i++)
|
||||
{
|
||||
auto& subsector = doomMap.subsectors[i];
|
||||
unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size();
|
||||
subsector.lightmap[0] = &doomMap.LMSurfaces[offset];
|
||||
subsector.lightmap[1] = &doomMap.LMSurfaces[offset + count];
|
||||
offset += count * 2;
|
||||
}
|
||||
|
||||
// Copy and build properties
|
||||
size_t index = 0;
|
||||
for (auto& surface : doomMap.levelMesh->Surfaces)
|
||||
{
|
||||
LightmapSurface l;
|
||||
memset(&l, 0, sizeof(LightmapSurface));
|
||||
|
||||
l.ControlSector = (sector_t*)surface.controlSector;
|
||||
l.Type = surface.type;
|
||||
l.LightmapNum = 0;
|
||||
|
||||
l.TexCoords = (float*)&doomMap.levelMesh->LightmapUvs[surface.startUvIndex];
|
||||
|
||||
l.LightmapNum = surface.atlasPageIndex;
|
||||
|
||||
if (surface.type == hwrenderer::ST_FLOOR || surface.type == hwrenderer::ST_CEILING)
|
||||
{
|
||||
l.Subsector = &doomMap.subsectors[surface.typeIndex];
|
||||
if (l.Subsector->firstline && l.Subsector->firstline->sidedef)
|
||||
l.Subsector->firstline->sidedef->sector->HasLightmaps = true;
|
||||
SetSubsectorLightmap(l);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.Side = &doomMap.sides[surface.typeIndex];
|
||||
SetSideLightmap(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::SetSubsectorLightmap(const LightmapSurface& surface)
|
||||
{
|
||||
if (!surface.ControlSector)
|
||||
{
|
||||
int index = surface.Type == hwrenderer::ST_CEILING ? 1 : 0;
|
||||
surface.Subsector->lightmap[index][0] = surface;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = surface.Type == hwrenderer::ST_CEILING ? 0 : 1;
|
||||
const auto& ffloors = surface.Subsector->sector->e->XFloor.ffloors;
|
||||
for (unsigned int i = 0; i < ffloors.Size(); i++)
|
||||
{
|
||||
if (ffloors[i]->model == surface.ControlSector)
|
||||
{
|
||||
surface.Subsector->lightmap[index][i + 1] = surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::SetSideLightmap(const LightmapSurface& surface)
|
||||
{
|
||||
if (!surface.ControlSector)
|
||||
{
|
||||
if (surface.Type == hwrenderer::ST_UPPERSIDE)
|
||||
{
|
||||
surface.Side->lightmap[0] = surface;
|
||||
}
|
||||
else if (surface.Type == hwrenderer::ST_MIDDLESIDE)
|
||||
{
|
||||
surface.Side->lightmap[1] = surface;
|
||||
surface.Side->lightmap[2] = surface;
|
||||
}
|
||||
else if (surface.Type == hwrenderer::ST_LOWERSIDE)
|
||||
{
|
||||
surface.Side->lightmap[3] = surface;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& ffloors = surface.Side->sector->e->XFloor.ffloors;
|
||||
for (unsigned int i = 0; i < ffloors.Size(); i++)
|
||||
{
|
||||
if (ffloors[i]->model == surface.ControlSector)
|
||||
{
|
||||
surface.Side->lightmap[4 + i] = surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side)
|
||||
{
|
||||
sector_t *front;
|
||||
|
|
|
@ -42,6 +42,10 @@ private:
|
|||
void CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor);
|
||||
void CreateSideSurfaces(FLevelLocals &doomMap, side_t *side);
|
||||
|
||||
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap);
|
||||
void SetSubsectorLightmap(const LightmapSurface& surface);
|
||||
void SetSideLightmap(const LightmapSurface& surface);
|
||||
|
||||
static bool IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side);
|
||||
static bool IsTopSideVisible(side_t* side);
|
||||
static bool IsBottomSideVisible(side_t* side);
|
||||
|
|
Loading…
Reference in a new issue