From c58f5095d9600650873bf362c230e263f81b2400 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Dec 2018 10:18:25 +0100 Subject: [PATCH] - fixed sprite sorting in the hardware renderer. This did no longer sort sprites in the same position reliably since the feature to render sprites which only partially are inside a sector was added. With this, sprites in the same position are no longer guaranteed to be added to the render list in sequence. Fixed by adding an 'order' field to AActor which gets incremented with each spawned actor and reset when a new level is started. The software renderer will also need a variation of this fix but its data no longer has access to the defining actor when being sorted, so a bit more work is needed here. --- src/actor.h | 2 ++ src/g_level.cpp | 2 ++ src/g_levellocals.h | 1 + src/hwrenderer/scene/hw_drawlist.cpp | 2 +- src/hwrenderer/scene/hw_sprites.cpp | 2 +- src/p_mobj.cpp | 2 ++ src/p_saveg.cpp | 1 + 7 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/actor.h b/src/actor.h index d3a6d94aa..90d42ccbd 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1237,6 +1237,8 @@ public: // When was this actor spawned? int SpawnTime; + uint32_t SpawnOrder; + // ThingIDs static void ClearTIDHashes (); diff --git a/src/g_level.cpp b/src/g_level.cpp index fdc5b1778..03bf94cc8 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -496,6 +496,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) level.time = 0; level.maptime = 0; level.totaltime = 0; + level.spawnindex = 0; if (!multiplayer || !deathmatch) { @@ -869,6 +870,7 @@ void G_DoCompleted (void) } level.time = 0; level.maptime = 0; + level.spawnindex = 0; } finishstate = mode; diff --git a/src/g_levellocals.h b/src/g_levellocals.h index ee9cbbe9c..a91db47ff 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -108,6 +108,7 @@ struct FLevelLocals : public FLevelData int starttime; int partime; int sucktime; + uint32_t spawnindex; level_info_t *info; int cluster; diff --git a/src/hwrenderer/scene/hw_drawlist.cpp b/src/hwrenderer/scene/hw_drawlist.cpp index 0cf6a8010..5b19288c1 100644 --- a/src/hwrenderer/scene/hw_drawlist.cpp +++ b/src/hwrenderer/scene/hw_drawlist.cpp @@ -588,7 +588,7 @@ inline int HWDrawList::CompareSprites(SortNode * a,SortNode * b) int res = s1->depth - s2->depth; if (res != 0) return -res; - else return (i_compatflags & COMPATF_SPRITESORT)? s1->index-s2->index : s2->index-s1->index; + else return (i_compatflags & COMPATF_SPRITESORT)? s2->index-s1->index : s1->index-s2->index; } //========================================================================== diff --git a/src/hwrenderer/scene/hw_sprites.cpp b/src/hwrenderer/scene/hw_sprites.cpp index f8c716686..17e794892 100644 --- a/src/hwrenderer/scene/hw_sprites.cpp +++ b/src/hwrenderer/scene/hw_sprites.cpp @@ -1062,7 +1062,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t // end of light calculation actor = thing; - index = di->spriteindex++; // this assumes that sprites from the same sector are added sequentially, i.e. by the same thread. + index = thing->SpawnOrder; particle = nullptr; const bool drawWithXYBillboard = (!(actor->renderflags & RF_FORCEYBILLBOARD) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 992a9134f..2b7a69382 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -362,6 +362,7 @@ void AActor::Serialize(FSerializer &arc) A("renderrequired", RenderRequired) A("friendlyseeblocks", friendlyseeblocks) A("spawntime", SpawnTime) + A("spawnorder", SpawnOrder) A("friction", Friction); } @@ -4409,6 +4410,7 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a actor = static_cast(const_cast(type)->CreateNew ()); actor->SpawnTime = level.totaltime; + actor->SpawnOrder = level.spawnindex++; // Set default dialogue actor->ConversationRoot = GetConversation(actor->GetClass()->TypeName); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index f9078dea5..adfbdfda6 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -971,6 +971,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) ("level.skyfog", level.skyfog) ("level.deathsequence", level.deathsequence) ("level.bodyqueslot", level.bodyqueslot) + ("level.spawnindex", level.spawnindex) .Array("level.bodyque", level.bodyque, level.BODYQUESIZE); // Hub transitions must keep the current total time