From 58269a18f0359da2f0ba3ab4da80ca87c6be1f8d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 1 Aug 2010 05:16:09 +0000 Subject: [PATCH] - Use a flood-fill algorithm to define polyobjects with PolyObj_StartLine instead of a simple loop-following algorithm. This fixes the polyobjects in http://www.doomworld.com/idgames/index.php?id=6291 SVN r2482 (trunk) --- src/p_setup.cpp | 30 ++++++------------------- src/p_setup.h | 23 +++++++++++++++++++ src/po_man.cpp | 60 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 69 insertions(+), 44 deletions(-) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 452cb0dcf5..4df7a367e0 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -128,27 +128,8 @@ FLightStack* LightStacks; TArray MapThingsConverted; int sidecount; -struct sidei_t // [RH] Only keep BOOM sidedef init stuff around for init -{ - union - { - // Used when unpacking sidedefs and assigning - // properties based on linedefs. - struct - { - short tag, special; - short alpha; - DWORD map; - } a; +sidei_t *sidetemp; - // Used when grouping sidedefs into loops. - struct - { - DWORD first, next; - char lineside; - } b; - }; -} *sidetemp; TArray linemap; bool UsingGLNodes; @@ -2261,9 +2242,8 @@ static void P_LoopSidedefs () sides[right].LeftSide = i; } - // Throw away sidedef init info now that we're done with it - delete[] sidetemp; - sidetemp = NULL; + // We keep the sidedef init info around until after polyobjects are initialized, + // so don't delete just yet. } int P_DetermineTranslucency (int lumpnum) @@ -3866,6 +3846,10 @@ void P_SetupLevel (char *lumpname, int position) PO_Init (); // Initialize the polyobjs times[16].Unclock(); + assert(sidetemp != NULL); + delete[] sidetemp; + sidetemp = NULL; + // if deathmatch, randomly spawn the active players if (deathmatch) { diff --git a/src/p_setup.h b/src/p_setup.h index c751c989ca..80196e3173 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -111,4 +111,27 @@ int P_TranslateSectorSpecial (int); int GetUDMFInt(int type, int index, const char *key); fixed_t GetUDMFFixed(int type, int index, const char *key); +struct sidei_t // [RH] Only keep BOOM sidedef init stuff around for init +{ + union + { + // Used when unpacking sidedefs and assigning + // properties based on linedefs. + struct + { + short tag, special; + short alpha; + DWORD map; + } a; + + // Used when grouping sidedefs into loops. + struct + { + DWORD first, next; + char lineside; + } b; + }; +}; +extern sidei_t *sidetemp; + #endif diff --git a/src/po_man.cpp b/src/po_man.cpp index c240e28fa2..93662f64ea 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -27,6 +27,7 @@ #include "r_interpolate.h" #include "g_level.h" #include "po_man.h" +#include "p_setup.h" // MACROS ------------------------------------------------------------------ @@ -1334,41 +1335,58 @@ static void KillSideLists () KnownPolySides.ShrinkToFit (); } +//========================================================================== +// +// AddPolyVert +// +// Helper function for IterFindPolySides() +// +//========================================================================== + +static void AddPolyVert(TArray &vnum, DWORD vert) +{ + for (unsigned int i = vnum.Size() - 1; i-- != 0; ) + { + if (vnum[i] == vert) + { // Already in the set. No need to add it. + return; + } + } + vnum.Push(vert); +} + //========================================================================== // // IterFindPolySides // +// Beginning with the first vertex of the starting side, for each vertex +// in vnum, add all the sides that use it as a first vertex to the polyobj, +// and add all their second vertices to vnum. This continues until there +// are no new vertices in vnum. +// //========================================================================== static void IterFindPolySides (FPolyObj *po, side_t *side) { - SDWORD j; - int i; - vertex_t *v1 = side->V1(); + static TArray vnum; + unsigned int vnumat; - po->Sidedefs.Push(side); + assert(sidetemp != NULL); - // This for loop exists solely to avoid infinitely looping on badly - // formed polyobjects. - for (i = 0; i < numsides; i++) + vnum.Clear(); + vnum.Push(DWORD(side->V1() - vertexes)); + vnumat = 0; + + while (vnum.Size() != vnumat) { - int v2 = int(side->V2() - vertexes); - j = side->RightSide; - - if (j == NO_SIDE) + DWORD sidenum = sidetemp[vnum[vnumat++]].b.first; + while (sidenum != NO_SIDE) { - break; + po->Sidedefs.Push(&sides[sidenum]); + AddPolyVert(vnum, DWORD(sides[sidenum].V2() - vertexes)); + sidenum = sidetemp[sidenum].b.next; } - side = &sides[j]; - - if (side->V1() == v1) - { - return; - } - po->Sidedefs.Push(side); } - I_Error ("IterFindPolySides: Non-closed Polyobj at linedef %d.\n", - side->linedef-lines); }