- moved main polyobject array into FLevelLocals and simplified the setup process to not depend on P_SpawnMapThing.

Since the SpawnedThings array is still available when polyobjects are spawned it makes no sense to create an expensive linked list in P_SpawnMapThing.
This can be done far better by scanning through the array again and collect all matching items in a second array.
This commit is contained in:
Christoph Oelckers 2018-12-28 10:08:39 +01:00
parent 84a28454dc
commit 64595abe60
12 changed files with 72 additions and 126 deletions

View file

@ -2333,10 +2333,9 @@ void AM_showSS()
AM_drawSeg(sub->firstline + i, yellow); AM_drawSeg(sub->firstline + i, yellow);
} }
for (int i = 0; i <po_NumPolyobjs; i++) for (auto &poly : level.Polyobjects)
{ {
FPolyObj *po = &polyobjs[i]; FPolyNode *pnode = poly.subsectorlinks;
FPolyNode *pnode = po->subsectorlinks;
while (pnode != NULL) while (pnode != NULL)
{ {

View file

@ -190,24 +190,6 @@ size_t PropagateMark()
obj->GetClass()->Size; obj->GetClass()->Size;
} }
//==========================================================================
//
// PropagateAll
//
// Empties the gray list by propagating every single object in it.
//
//==========================================================================
static size_t PropagateAll()
{
size_t m = 0;
while (Gray != NULL)
{
m += PropagateMark();
}
return m;
}
//========================================================================== //==========================================================================
// //
// SweepList // SweepList
@ -668,14 +650,14 @@ size_t DSectorMarker::PropagateMark()
moretodo = true; moretodo = true;
} }
if (!moretodo && polyobjs != NULL) if (!moretodo && level.Polyobjects.Size() > 0)
{ {
for (i = 0; i < POLYSTEPSIZE && PolyNum + i < po_NumPolyobjs; ++i) for (i = 0; i < POLYSTEPSIZE && PolyNum + i < (int)level.Polyobjects.Size(); ++i)
{ {
GC::Mark(polyobjs[PolyNum + i].interpolation); GC::Mark(level.Polyobjects[PolyNum + i].interpolation);
} }
marked += i * sizeof(FPolyObj); marked += i * sizeof(FPolyObj);
if (PolyNum + i < po_NumPolyobjs) if (PolyNum + i < (int)level.Polyobjects.Size())
{ {
PolyNum += i; PolyNum += i;
moretodo = true; moretodo = true;

View file

@ -42,6 +42,7 @@
#include "portal.h" #include "portal.h"
#include "p_blockmap.h" #include "p_blockmap.h"
#include "p_local.h" #include "p_local.h"
#include "po_man.h"
#include "p_destructible.h" #include "p_destructible.h"
#include "r_data/r_sections.h" #include "r_data/r_sections.h"
#include "r_data/r_canvastexture.h" #include "r_data/r_canvastexture.h"
@ -62,6 +63,7 @@ struct FLevelData
node_t *headgamenode; node_t *headgamenode;
TArray<uint8_t> rejectmatrix; TArray<uint8_t> rejectmatrix;
TArray<zone_t> Zones; TArray<zone_t> Zones;
TArray<FPolyObj> Polyobjects;
TArray<FSectorPortal> sectorPortals; TArray<FSectorPortal> sectorPortals;
TArray<FLinePortal> linePortals; TArray<FLinePortal> linePortals;

View file

@ -108,6 +108,8 @@ TArray<FMapThing> MapThingsConverted;
bool ForceNodeBuild; bool ForceNodeBuild;
void PO_Init();
#define MISSING_TEXTURE_WARN_LIMIT 20 #define MISSING_TEXTURE_WARN_LIMIT 20
void BloodCrypt (void *data, int key, int len); void BloodCrypt (void *data, int key, int len);

View file

@ -81,7 +81,7 @@ class MapLoader
TMap<unsigned, unsigned> MapThingsUserDataIndex; // from mapthing idx -> user data idx TMap<unsigned, unsigned> MapThingsUserDataIndex; // from mapthing idx -> user data idx
TArray<FUDMFKey> MapThingsUserData; TArray<FUDMFKey> MapThingsUserData;
int sidecount; int sidecount = 0;
TArray<int> linemap; TArray<int> linemap;
TMap<int, EDLinedef> EDLines; TMap<int, EDLinedef> EDLines;
@ -130,6 +130,7 @@ class MapLoader
void ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &missingtex); void ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &missingtex);
void SetMapThingUserData(AActor *actor, unsigned udi); void SetMapThingUserData(AActor *actor, unsigned udi);
void CreateBlockMap(); void CreateBlockMap();
void PO_Init(void);
public: public:
void LoadMapinfoACSLump(); void LoadMapinfoACSLump();

View file

@ -5251,17 +5251,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
case SMT_PolySpawn: case SMT_PolySpawn:
case SMT_PolySpawnCrush: case SMT_PolySpawnCrush:
case SMT_PolySpawnHurt: case SMT_PolySpawnHurt:
{ return nullptr;
polyspawns_t *polyspawn = new polyspawns_t;
polyspawn->next = polyspawns;
polyspawn->pos = mthing->pos;
polyspawn->angle = mthing->angle;
polyspawn->type = mentry->Special;
polyspawns = polyspawn;
if (mentry->Special != SMT_PolyAnchor)
po_NumPolyobjs++;
return NULL;
}
case SMT_Player1Start: case SMT_Player1Start:
case SMT_Player2Start: case SMT_Player2Start:

View file

@ -935,7 +935,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
if (arc.GetSize("linedefs") != level.lines.Size() || if (arc.GetSize("linedefs") != level.lines.Size() ||
arc.GetSize("sidedefs") != level.sides.Size() || arc.GetSize("sidedefs") != level.sides.Size() ||
arc.GetSize("sectors") != level.sectors.Size() || arc.GetSize("sectors") != level.sectors.Size() ||
arc.GetSize("polyobjs") != (unsigned)po_NumPolyobjs || arc.GetSize("polyobjs") != level.Polyobjects.Size() ||
memcmp(chk, level.md5, 16)) memcmp(chk, level.md5, 16))
{ {
I_Error("Savegame is from a different level"); I_Error("Savegame is from a different level");
@ -1007,7 +1007,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
// [ZZ] serialize events // [ZZ] serialize events
E_SerializeEvents(arc); E_SerializeEvents(arc);
DThinker::SerializeThinkers(arc, hubload); DThinker::SerializeThinkers(arc, hubload);
arc.Array("polyobjs", polyobjs, po_NumPolyobjs); arc("polyobjs", level.Polyobjects);
SerializeSubsectors(arc, "subsectors"); SerializeSubsectors(arc, "subsectors");
StatusBar->SerializeMessages(arc); StatusBar->SerializeMessages(arc);
AM_SerializeMarkers(arc); AM_SerializeMarkers(arc);

View file

@ -285,6 +285,7 @@ void P_FreeLevelData ()
level.rejectmatrix.Clear(); level.rejectmatrix.Clear();
level.Zones.Clear(); level.Zones.Clear();
level.blockmap.Clear(); level.blockmap.Clear();
level.Polyobjects.Clear();
if (PolyBlockMap != nullptr) if (PolyBlockMap != nullptr)
{ {
@ -301,12 +302,6 @@ void P_FreeLevelData ()
delete[] PolyBlockMap; delete[] PolyBlockMap;
PolyBlockMap = nullptr; PolyBlockMap = nullptr;
} }
if (polyobjs != nullptr)
{
delete[] polyobjs;
polyobjs = nullptr;
}
po_NumPolyobjs = 0;
level.deathmatchstarts.Clear(); level.deathmatchstarts.Clear();
level.AllPlayerStarts.Clear(); level.AllPlayerStarts.Clear();

View file

@ -40,6 +40,8 @@
#include "actorinlines.h" #include "actorinlines.h"
#include "v_text.h" #include "v_text.h"
#include "maploader/maploader.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
#define PO_MAXPOLYSEGS 64 #define PO_MAXPOLYSEGS 64
@ -146,9 +148,6 @@ static void ReleaseAllPolyNodes();
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
polyblock_t **PolyBlockMap; polyblock_t **PolyBlockMap;
FPolyObj *polyobjs; // list of all poly-objects on the level
int po_NumPolyobjs;
polyspawns_t *polyspawns; // [RH] Let P_SpawnMapThings() find our thingies for us
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -770,16 +769,14 @@ bool EV_StopPoly(int polynum)
FPolyObj *PO_GetPolyobj (int polyNum) FPolyObj *PO_GetPolyobj (int polyNum)
{ {
int i; for(auto &poly : level.Polyobjects)
for (i = 0; i < po_NumPolyobjs; i++)
{ {
if (polyobjs[i].tag == polyNum) if (poly.tag == polyNum)
{ {
return &polyobjs[i]; return &poly;
} }
} }
return NULL; return nullptr;
} }
@ -1405,16 +1402,15 @@ void FPolyObj::ClosestPoint(const DVector2 &fpos, DVector2 &out, side_t **side)
static void InitBlockMap (void) static void InitBlockMap (void)
{ {
int i;
int bmapwidth = level.blockmap.bmapwidth; int bmapwidth = level.blockmap.bmapwidth;
int bmapheight = level.blockmap.bmapheight; int bmapheight = level.blockmap.bmapheight;
PolyBlockMap = new polyblock_t *[bmapwidth*bmapheight]; PolyBlockMap = new polyblock_t *[bmapwidth*bmapheight];
memset (PolyBlockMap, 0, bmapwidth*bmapheight*sizeof(polyblock_t *)); memset (PolyBlockMap, 0, bmapwidth*bmapheight*sizeof(polyblock_t *));
for (i = 0; i < po_NumPolyobjs; i++) for(auto &poly : level.Polyobjects)
{ {
polyobjs[i].LinkPolyobj(); poly.LinkPolyobj();
} }
} }
@ -1521,7 +1517,7 @@ static void SpawnPolyobj (int index, int tag, int type)
{ {
unsigned int ii; unsigned int ii;
int i; int i;
FPolyObj *po = &polyobjs[index]; FPolyObj *po = &level.Polyobjects[index];
for (ii = 0; ii < KnownPolySides.Size(); ++ii) for (ii = 0; ii < KnownPolySides.Size(); ++ii)
{ {
@ -1547,7 +1543,7 @@ static void SpawnPolyobj (int index, int tag, int type)
{ {
sd->linedef->special = 0; sd->linedef->special = 0;
sd->linedef->args[0] = 0; sd->linedef->args[0] = 0;
IterFindPolySides(&polyobjs[index], sd); IterFindPolySides(&level.Polyobjects[index], sd);
po->MirrorNum = sd->linedef->args[1]; po->MirrorNum = sd->linedef->args[1];
po->crush = (type != SMT_PolySpawn) ? 3 : 0; po->crush = (type != SMT_PolySpawn) ? 3 : 0;
po->bHurtOnTouch = (type == SMT_PolySpawnHurt); po->bHurtOnTouch = (type == SMT_PolySpawnHurt);
@ -1652,16 +1648,8 @@ static void TranslateToStartSpot (int tag, const DVector2 &origin)
FPolyObj *po; FPolyObj *po;
DVector2 delta; DVector2 delta;
po = NULL; po = PO_GetPolyobj(tag);
for (int i = 0; i < po_NumPolyobjs; i++) if (po == nullptr)
{
if (polyobjs[i].tag == tag)
{
po = &polyobjs[i];
break;
}
}
if (po == NULL)
{ // didn't match the tag with a polyobj tag { // didn't match the tag with a polyobj tag
Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag);
return; return;
@ -1702,60 +1690,64 @@ static void TranslateToStartSpot (int tag, const DVector2 &origin)
// //
//========================================================================== //==========================================================================
void PO_Init (void) void MapLoader::PO_Init (void)
{ {
// [RH] Hexen found the polyobject-related things by reloading the map's int NumPolyobjs = 0;
// THINGS lump here and scanning through it. I have P_SpawnMapThing() TArray<FMapThing *> polythings;
// record those things instead, so that in here we simply need to for (auto &mthing : MapThingsConverted)
// look at the polyspawns list. {
polyspawns_t *polyspawn, **prev; if (mthing.EdNum == 0 || mthing.EdNum == -1) continue;
FDoomEdEntry *mentry = mthing.info;
switch (mentry->Special)
{
case SMT_PolyAnchor:
case SMT_PolySpawn:
case SMT_PolySpawnCrush:
case SMT_PolySpawnHurt:
polythings.Push(&mthing);
if (mentry->Special != SMT_PolyAnchor)
NumPolyobjs++;
}
}
int polyIndex; int polyIndex;
// [RH] Make this faster // [RH] Make this faster
InitSideLists (); InitSideLists ();
polyobjs = new FPolyObj[po_NumPolyobjs]; Level->Polyobjects.Resize(NumPolyobjs);
polyIndex = 0; // index polyobj number polyIndex = 0; // index polyobj number
// Find the startSpot points, and spawn each polyobj // Find the startSpot points, and spawn each polyobj
for (polyspawn = polyspawns, prev = &polyspawns; polyspawn;) for (int i=polythings.Size()-1; i >= 0; i--)
{ {
// 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch // 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch
if (polyspawn->type >= SMT_PolySpawn && polyspawn->type <= SMT_PolySpawnHurt) int type = polythings[i]->info->Special;
if (type >= SMT_PolySpawn && type <= SMT_PolySpawnHurt)
{ {
// Polyobj StartSpot Pt. // Polyobj StartSpot Pt.
polyobjs[polyIndex].StartSpot.pos = polyspawn->pos; Level->Polyobjects[polyIndex].StartSpot.pos = polythings[i]->pos;
SpawnPolyobj(polyIndex, polyspawn->angle, polyspawn->type); SpawnPolyobj(polyIndex, polythings[i]->angle, type);
polyIndex++; polyIndex++;
*prev = polyspawn->next;
delete polyspawn;
polyspawn = *prev;
} }
else }
for (int i = polythings.Size() - 1; i >= 0; i--)
{ {
prev = &polyspawn->next; int type = polythings[i]->info->Special;
polyspawn = polyspawn->next; if (type == SMT_PolyAnchor)
}
}
for (polyspawn = polyspawns; polyspawn;)
{
polyspawns_t *next = polyspawn->next;
if (polyspawn->type == SMT_PolyAnchor)
{ {
// Polyobj Anchor Pt. // Polyobj Anchor Pt.
TranslateToStartSpot (polyspawn->angle, polyspawn->pos); TranslateToStartSpot (polythings[i]->angle, polythings[i]->pos);
} }
delete polyspawn;
polyspawn = next;
} }
polyspawns = NULL;
// check for a startspot without an anchor point // check for a startspot without an anchor point
for (polyIndex = 0; polyIndex < po_NumPolyobjs; polyIndex++) for (auto &poly : Level->Polyobjects)
{ {
if (polyobjs[polyIndex].OriginalPts.Size() == 0) if (poly.OriginalPts.Size() == 0)
{ {
Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", polyobjs[polyIndex].tag); Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", poly.tag);
} }
} }
InitBlockMap(); InitBlockMap();
@ -1765,7 +1757,7 @@ void PO_Init (void)
// mark all subsectors which have a seg belonging to a polyobj // mark all subsectors which have a seg belonging to a polyobj
// These ones should not be rendered on the textured automap. // These ones should not be rendered on the textured automap.
for (auto &ss : level.subsectors) for (auto &ss : Level->subsectors)
{ {
for(uint32_t j=0;j<ss.numlines; j++) for(uint32_t j=0;j<ss.numlines; j++)
{ {
@ -1778,7 +1770,7 @@ void PO_Init (void)
} }
} }
// clear all polyobj specials so that they do not obstruct using other lines. // clear all polyobj specials so that they do not obstruct using other lines.
for (auto &line : level.lines) for (auto &line : Level->lines)
{ {
if (line.special == Polyobj_ExplicitLine || line.special == Polyobj_StartLine) if (line.special == Polyobj_ExplicitLine || line.special == Polyobj_StartLine)
{ {
@ -1847,9 +1839,9 @@ void FPolyObj::ClearSubsectorLinks()
void FPolyObj::ClearAllSubsectorLinks() void FPolyObj::ClearAllSubsectorLinks()
{ {
for (int i = 0; i < po_NumPolyobjs; i++) for(auto &poly : level.Polyobjects)
{ {
polyobjs[i].ClearSubsectorLinks(); poly.ClearSubsectorLinks();
} }
ReleaseAllPolyNodes(); ReleaseAllPolyNodes();
} }
@ -2173,11 +2165,11 @@ void FPolyObj::CreateSubsectorLinks()
void PO_LinkToSubsectors() void PO_LinkToSubsectors()
{ {
for (int i = 0; i < po_NumPolyobjs; i++) for(auto &poly : level.Polyobjects)
{ {
if (polyobjs[i].subsectorlinks == NULL) if (poly.subsectorlinks == nullptr)
{ {
polyobjs[i].CreateSubsectorLinks(); poly.CreateSubsectorLinks();
} }
} }
} }

View file

@ -116,7 +116,6 @@ private:
bool CheckMobjBlocking (side_t *sd); bool CheckMobjBlocking (side_t *sd);
}; };
extern FPolyObj *polyobjs; // list of all poly-objects on the level
struct polyblock_t struct polyblock_t
{ {
@ -144,22 +143,6 @@ bool EV_MovePolyTo (line_t *line, int polyNum, double speed, const DVector2 &pos
bool EV_OpenPolyDoor (line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type); bool EV_OpenPolyDoor (line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type);
bool EV_StopPoly (int polyNum); bool EV_StopPoly (int polyNum);
// [RH] Data structure for P_SpawnMapThing() to keep track
// of polyobject-related things.
struct polyspawns_t
{
polyspawns_t *next;
DVector2 pos;
short angle;
short type;
};
extern int po_NumPolyobjs;
extern polyspawns_t *polyspawns; // [RH] list of polyobject things to spawn
void PO_Init ();
bool PO_Busy (int polyobj); bool PO_Busy (int polyobj);
FPolyObj *PO_GetPolyobj(int polyNum); FPolyObj *PO_GetPolyobj(int polyNum);

View file

@ -1449,12 +1449,12 @@ FSerializer &SerializePointer(FSerializer &arc, const char *key, T *&value, T **
template<> FSerializer &Serialize(FSerializer &arc, const char *key, FPolyObj *&value, FPolyObj **defval) template<> FSerializer &Serialize(FSerializer &arc, const char *key, FPolyObj *&value, FPolyObj **defval)
{ {
return SerializePointer(arc, key, value, defval, polyobjs); return SerializePointer(arc, key, value, defval, level.Polyobjects.Data());
} }
template<> FSerializer &Serialize(FSerializer &arc, const char *key, const FPolyObj *&value, const FPolyObj **defval) template<> FSerializer &Serialize(FSerializer &arc, const char *key, const FPolyObj *&value, const FPolyObj **defval)
{ {
return SerializePointer<const FPolyObj>(arc, key, value, defval, polyobjs); return SerializePointer<const FPolyObj>(arc, key, value, defval, level.Polyobjects.Data());
} }
template<> FSerializer &Serialize(FSerializer &arc, const char *key, side_t *&value, side_t **defval) template<> FSerializer &Serialize(FSerializer &arc, const char *key, side_t *&value, side_t **defval)

View file

@ -1343,7 +1343,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n
_CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF);
// Use this to break at a specific allocation number. // Use this to break at a specific allocation number.
_crtBreakAlloc = 227524; //_crtBreakAlloc = 227524;
#endif #endif
DoMain (hInstance); DoMain (hInstance);