Skip to content

Scrap dlight lighthead link lists #3039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/g_level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,9 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
primaryLevel->totaltime = 0;
primaryLevel->spawnindex = 0;

primaryLevel->lightlists.wall_dlist.clear();
primaryLevel->lightlists.flat_dlist.clear();

if (!multiplayer || !deathmatch)
{
InitPlayerClasses ();
Expand Down
10 changes: 10 additions & 0 deletions src/g_levellocals.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

#pragma once

#include <unordered_map>

#include "doomdata.h"
#include "g_level.h"
#include "r_defs.h"
Expand All @@ -58,6 +60,12 @@
#include "doom_levelmesh.h"
#include "p_visualthinker.h"

struct FGlobalDLightLists
{
std::unordered_map<FSection*, std::unordered_map<FDynamicLight*, FLightNode*>> flat_dlist;
std::unordered_map<side_t*, std::unordered_map<FDynamicLight*, FLightNode*>> wall_dlist;
};

//============================================================================
//
// This is used to mark processed portals for some collection functions.
Expand Down Expand Up @@ -745,6 +753,8 @@ struct FLevelLocals
bool notexturefill;
int ImpactDecalCount;

FGlobalDLightLists lightlists;

FDynamicLight *lights;
DVisualThinker* VisualThinkerHead = nullptr;

Expand Down
1 change: 0 additions & 1 deletion src/gamedata/r_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,6 @@ struct side_t
int16_t TierLights[3]; // per-tier light levels
uint16_t Flags;
int UDMFIndex; // needed to access custom UDMF fields which are stored in loading order.
FLightNode * lighthead; // all dynamic lights that may affect this wall
LightmapSurface* lightmap;
seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering
int numsegs;
Expand Down
204 changes: 96 additions & 108 deletions src/playsim/a_dynlight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ static FDynamicLight *GetLight(FLevelLocals *Level)
ret->mShadowmapIndex = 1024;
ret->Level = Level;
ret->Pos.X = -10000000; // not a valid coordinate.
if (!ret->touchlists) ret->touchlists = new FDynamicLightTouchLists;
return ret;
}

Expand Down Expand Up @@ -249,6 +250,7 @@ void FDynamicLight::Tick()
if (!target)
{
// How did we get here? :?
UnlinkLight();
ReleaseLight();
return;
}
Expand Down Expand Up @@ -418,84 +420,78 @@ void FDynamicLight::UpdateLocation()

//=============================================================================
//
// These have been copied from the secnode code and modified for the light links
//
// P_AddSecnode() searches the current list to see if this sector is
// already there. If not, it adds a sector node at the head of the list of
// sectors this object appears in. This is called when creating a list of
// nodes that will get linked in later. Returns a pointer to the new node.
// Attempts to emplace the light node in the unordered_map
//
//=============================================================================

FLightNode * AddLightNode(FLightNode ** thread, void * linkto, FDynamicLight * light, FLightNode *& nextnode)
void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef)
{
FLightNode * node;
auto updateFlatTList = [&](FSection *sec)
{
touchlists->flat_tlist.try_emplace(sec, sec);
};
auto updateWallTList = [&](side_t *sidedef)
{
touchlists->wall_tlist.try_emplace(sidedef, sidedef);
};

node = nextnode;
while (node)
{
if (node->targ==linkto) // Already have a node for this sector?
if (section)
{
auto flatLightList = Level->lightlists.flat_dlist.find(section);
if (flatLightList != Level->lightlists.flat_dlist.end())
{
node->lightsource = light; // Yes. Setting m_thing says 'keep it'.
return(nextnode);
}
node = node->nextTarget;
}

// Couldn't find an existing node for this sector. Add one at the head
// of the list.

node = new FLightNode;

node->targ = linkto;
node->lightsource = light;

node->prevTarget = &nextnode;
node->nextTarget = nextnode;

if (nextnode) nextnode->prevTarget = &node->nextTarget;

// Add new node at head of sector thread starting at s->touching_thinglist

node->prevLight = thread;
node->nextLight = *thread;
if (node->nextLight) node->nextLight->prevLight=&node->nextLight;
*thread = node;
return(node);
}
if (flatLightList->second.find(this) == flatLightList->second.end())
{
FLightNode * node = new FLightNode;
node->lightsource = this;
node->targ = section;

flatLightList->second.try_emplace(this, node);
updateFlatTList(section);
}
}
else
{
FLightNode * node = new FLightNode;
node->lightsource = this;
node->targ = section;

//=============================================================================
//
// P_DelSecnode() deletes a sector node from the list of
// sectors this object appears in. Returns a pointer to the next node
// on the linked list, or nullptr.
//
//=============================================================================
std::unordered_map<FDynamicLight *, FLightNode *> u = { {this, node} };
Level->lightlists.flat_dlist.try_emplace(section, u);
updateFlatTList(section);
}
}
else if (sidedef)
{
auto wallLightList = Level->lightlists.wall_dlist.find(sidedef);
if (wallLightList != Level->lightlists.wall_dlist.end())
{
if (wallLightList->second.find(this) == wallLightList->second.end())
{
FLightNode * node = new FLightNode;
node->lightsource = this;
node->targ = sidedef;

static FLightNode * DeleteLightNode(FLightNode * node)
{
FLightNode * tn; // next node on thing thread

if (node)
{

*node->prevTarget = node->nextTarget;
if (node->nextTarget) node->nextTarget->prevTarget=node->prevTarget;
wallLightList->second.try_emplace(this, node);
updateWallTList(sidedef);
}
}
else
{
FLightNode * node = new FLightNode;
node->lightsource = this;
node->targ = sidedef;

*node->prevLight = node->nextLight;
if (node->nextLight) node->nextLight->prevLight=node->prevLight;

// Return this node to the freelist
tn=node->nextTarget;
delete node;
return(tn);
std::unordered_map<FDynamicLight *, FLightNode *> u = { {this, node} };
Level->lightlists.wall_dlist.try_emplace(sidedef, u);
updateWallTList(sidedef);
}
}
return(nullptr);
}




//==========================================================================
//
// Gets the light's distance to a line
Expand Down Expand Up @@ -550,7 +546,7 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
auto pos = collected_ss[i].pos;
section = collected_ss[i].sect;

touching_sector = AddLightNode(&section->lighthead, section, this, touching_sector);
AddLightNode(section, NULL);


auto processSide = [&](side_t *sidedef, const vertex_t *v1, const vertex_t *v2)
Expand All @@ -562,7 +558,8 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
if ((pos.Y - v1->fY()) * (v2->fX() - v1->fX()) + (v1->fX() - pos.X) * (v2->fY() - v1->fY()) <= 0)
{
linedef->validcount = ::validcount;
touching_sides = AddLightNode(&sidedef->lighthead, sidedef, this, touching_sides);

AddLightNode(NULL, sidedef);
}
else if (linedef->sidedef[0] == sidedef && linedef->sidedef[1] == nullptr)
{
Expand Down Expand Up @@ -664,22 +661,6 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,

void FDynamicLight::LinkLight()
{
// mark the old light nodes
FLightNode * node;

node = touching_sides;
while (node)
{
node->lightsource = nullptr;
node = node->nextTarget;
}
node = touching_sector;
while (node)
{
node->lightsource = nullptr;
node = node->nextTarget;
}

if (radius>0)
{
// passing in radius*radius allows us to do a distance check without any calls to sqrt
Expand All @@ -690,31 +671,6 @@ void FDynamicLight::LinkLight()
CollectWithinRadius(Pos, sect, float(radius*radius));

}

// Now delete any nodes that won't be used. These are the ones where
// m_thing is still nullptr.

node = touching_sides;
while (node)
{
if (node->lightsource == nullptr)
{
node = DeleteLightNode(node);
}
else
node = node->nextTarget;
}

node = touching_sector;
while (node)
{
if (node->lightsource == nullptr)
{
node = DeleteLightNode(node);
}
else
node = node->nextTarget;
}
}


Expand All @@ -725,8 +681,40 @@ void FDynamicLight::LinkLight()
//==========================================================================
void FDynamicLight::UnlinkLight ()
{
while (touching_sides) touching_sides = DeleteLightNode(touching_sides);
while (touching_sector) touching_sector = DeleteLightNode(touching_sector);
for (const auto& [key, value] : touchlists->wall_tlist)
{
auto sidedef = value;
if (!sidedef) continue;

auto wallLightList = Level->lightlists.wall_dlist.find(sidedef);
if (wallLightList != Level->lightlists.wall_dlist.end())
{
auto light = wallLightList->second.find(this);
if (light != wallLightList->second.end())
{
delete light->second;
wallLightList->second.erase(light);
}
}
}
for (const auto& [key, value] : touchlists->flat_tlist)
{
auto sec = value;
if (!sec) continue;

auto flatLightList = Level->lightlists.flat_dlist.find(sec);
if (flatLightList != Level->lightlists.flat_dlist.end())
{
auto light = flatLightList->second.find(this);
if (light != flatLightList->second.end())
{
delete light->second;
flatLightList->second.erase(light);
}
}
}
delete touchlists;
touchlists = nullptr;
shadowmapped = false;
}

Expand Down
8 changes: 8 additions & 0 deletions src/playsim/a_dynlight.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ struct FLightNode
};
};

struct FDynamicLightTouchLists
{
std::unordered_map<FSection*, FSection*> flat_tlist;
std::unordered_map<side_t*, side_t*> wall_tlist;
};

struct FDynamicLight
{
friend class FLightDefaults;
Expand Down Expand Up @@ -245,6 +251,7 @@ struct FDynamicLight

void Tick();
void UpdateLocation();
void AddLightNode(FSection *section, side_t *sidedef);
void LinkLight();
void UnlinkLight();
void ReleaseLight();
Expand Down Expand Up @@ -286,6 +293,7 @@ struct FDynamicLight
bool swapped;
bool explicitpitch;

FDynamicLightTouchLists *touchlists;
};


1 change: 0 additions & 1 deletion src/r_data/r_sections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,6 @@ class FSectionCreator
dest.sector = &Level->sectors[group.groupedSections[0].section->sectorindex];
dest.mapsection = (short)group.groupedSections[0].section->mapsection;
dest.hacked = false;
dest.lighthead = nullptr;
dest.validcount = 0;
dest.segments.Set(&output.allLines[numsegments], group.segments.Size());
dest.sides.Set(&output.allSides[numsides], group.sideMap.CountUsed());
Expand Down
1 change: 0 additions & 1 deletion src/r_data/r_sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ struct FSection
TArrayView<side_t *> sides; // contains all sidedefs, including the internal ones that do not make up the outer shape.
TArrayView<subsector_t *> subsectors; // contains all subsectors making up this section
sector_t *sector;
FLightNode *lighthead; // Light nodes (blended and additive)
BoundingRect bounds;
int vertexindex; // This is relative to the start of the entire sector's vertex plane data because it needs to be used with different sources.
int vertexcount;
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/hwrenderer/scene/hw_drawinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ struct HWDrawInfo
void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node);
void AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node);

void GetDynSpriteLight(AActor *self, float x, float y, float z, FLightNode *node, int portalgroup, float *out);
void GetDynSpriteLight(AActor *self, float x, float y, float z, FSection *sec, int portalgroup, float *out);
void GetDynSpriteLight(AActor *thing, particle_t *particle, float *out);

void PreparePlayerSprites(sector_t * viewsector, area_t in_area);
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/hwrenderer/scene/hw_drawstructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ class HWFlat
int dynlightindex;

void CreateSkyboxVertices(FFlatVertex *buffer);
void SetupLights(HWDrawInfo *di, FLightNode *head, FDynLightData &lightdata, int portalgroup);
void SetupLights(HWDrawInfo *di, FDynLightData &lightdata, int portalgroup);

void PutFlat(HWDrawInfo *di, bool fog = false);
void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture);
Expand Down
Loading