From e2f07d27755fcd16999238bf7df747fecba42c7c Mon Sep 17 00:00:00 2001 From: danij Date: Sat, 14 Sep 2013 17:30:29 +0100 Subject: [PATCH] World|Sector: Cleaned up Mobj => Sector linkage --- doomsday/client/include/world/p_object.h | 5 +- doomsday/client/include/world/sector.h | 18 ++++-- doomsday/client/src/world/map.cpp | 77 +++++++++--------------- doomsday/client/src/world/p_mobj.cpp | 21 +------ doomsday/client/src/world/sector.cpp | 53 ++++++++++++---- 5 files changed, 89 insertions(+), 85 deletions(-) diff --git a/doomsday/client/include/world/p_object.h b/doomsday/client/include/world/p_object.h index 83873b51da..86437f7b5c 100644 --- a/doomsday/client/include/world/p_object.h +++ b/doomsday/client/include/world/p_object.h @@ -43,8 +43,7 @@ typedef struct mobj_s #define DEFAULT_FRICTION FIX2FLT(0xe800) #define NOMOMENTUM_THRESHOLD (0.0001) -#define IS_SECTOR_LINKED(mo) ((mo)->sPrev != NULL) -#define IS_BLOCK_LINKED(mo) ((mo)->bNext != NULL) +#define IS_BLOCK_LINKED(mo) ((mo)->bNext != 0) DENG_EXTERN_C int useSRVO, useSRVOAngle; @@ -103,7 +102,7 @@ float Mobj_ShadowStrength(mobj_t *mobj); coord_t Mobj_ApproxPointDistance(mobj_t *start, coord_t const *point); -boolean Mobj_UnlinkFromSector(mobj_t *mobj); +boolean Mobj_IsSectorLinked(mobj_t *mobj); /** * @return The current floatbob offset for the mobj, if the mobj is flagged diff --git a/doomsday/client/include/world/sector.h b/doomsday/client/include/world/sector.h index cdf094b289..8a5b976f6a 100644 --- a/doomsday/client/include/world/sector.h +++ b/doomsday/client/include/world/sector.h @@ -221,10 +221,6 @@ class Sector : public de::MapElement // Plane identifiers: enum { Floor, Ceiling }; -public: /// @todo Make private: - /// Head of the linked list of mobjs "in" the sector (not owned). - struct mobj_s *_mobjList; - public: /** * Construct a new sector. @@ -503,6 +499,20 @@ class Sector : public de::MapElement */ struct mobj_s *firstMobj() const; + /** + * Unlink the mobj from the list of mobjs "in" the sector. + * + * @param mobj Mobj to be unlinked. + */ + void unlink(struct mobj_s *mobj); + + /** + * Link the mobj to the head of the list of mobjs "in" the sector. + * + * @param mobj Mobj to be linked. + */ + void link(struct mobj_s *mobj); + /** * Returns the @em validCount of the sector. Used by some legacy iteration * algorithms for marking sectors as processed/visited. diff --git a/doomsday/client/src/world/map.cpp b/doomsday/client/src/world/map.cpp index 72cc4406b8..e079bfa2db 100644 --- a/doomsday/client/src/world/map.cpp +++ b/doomsday/client/src/world/map.cpp @@ -109,36 +109,24 @@ struct EditableElements DENG2_PIMPL(Map), DENG2_OBSERVES(bsp::Partitioner, UnclosedSectorFound) { - /// @c true= editing is currently enabled. bool editingEnabled; - - /// Editable map element LUTs: EditableElements editable; - /// Universal resource identifier for the map. Uri uri; + char oldUniqueId[256]; ///< Used with some legacy definitions. - /// Old unique identifier for the map (used with some legacy definitions). - char oldUniqueId[256]; - - /// Boundary points which encompass the entire map. - AABoxd bounds; + AABoxd bounds; ///< Boundary points which encompass the entire map - /// Map thinkers. QScopedPointer thinkers; - - /// Mesh from which we'll assign geometries. - Mesh mesh; + Mesh mesh; ///< All map geometries. /// Element LUTs: Sectors sectors; Lines lines; Polyobjs polyobjs; - /// BSP root element. + /// BSP data structure: MapElement *bspRoot; - - /// BSP element LUTs: BspNodes bspNodes; BspLeafs bspLeafs; @@ -153,7 +141,7 @@ DENG2_OBSERVES(bsp::Partitioner, UnclosedSectorFound) nodepile_t mobjNodes; nodepile_t lineNodes; - nodeindex_t *lineLinks; // Indices to roots. + nodeindex_t *lineLinks; ///< Indices to roots. #ifdef __CLIENT__ PlaneSet trackedPlanes; @@ -165,21 +153,15 @@ DENG2_OBSERVES(bsp::Partitioner, UnclosedSectorFound) /// Shadow Bias data. struct Bias { - /// Time in milliseconds of the "current" frame. - uint currentTime; - - /// Frame number of the last update. + uint currentTime; ///< The "current" frame in milliseconds. uint lastChangeOnFrame; - - /// The set of light sources. - BiasSources sources; + BiasSources sources; ///< All bias light sources (owned). Bias() : currentTime(0), lastChangeOnFrame(0) {} } bias; - /// Luminous object data. - Lumobjs lumobjs; + Lumobjs lumobjs; ///< All lumobjs (owned). QScopedPointer decorator; @@ -187,7 +169,7 @@ DENG2_OBSERVES(bsp::Partitioner, UnclosedSectorFound) coord_t skyCeilingHeight; #endif - // Current LOS trace state. + // Current LOS trace state: /// @todo Does not belong here. TraceOpening traceOpening; divline_t traceLine; @@ -635,6 +617,17 @@ DENG2_OBSERVES(bsp::Partitioner, UnclosedSectorFound) return bspRoot != 0; } + /// @return @c true= @a mobj was unlinked successfully. + bool unlinkMobjFromSectors(mobj_t &mobj) + { + if(Mobj_IsSectorLinked(&mobj)) + { + mobj.bspLeaf->sector().unlink(&mobj); + return true; + } + return false; + } + /** * Construct an initial (empty) line blockmap. * @@ -1957,7 +1950,7 @@ int Map::unlink(mobj_t &mo) { int links = 0; - if(Mobj_UnlinkFromSector(&mo)) + if(d->unlinkMobjFromSectors(mo)) links |= DDLINK_SECTOR; if(d->unlinkMobjInBlockmap(mo)) links |= DDLINK_BLOCKMAP; @@ -1969,29 +1962,17 @@ int Map::unlink(mobj_t &mo) void Map::link(mobj_t &mo, byte flags) { - // Link into the sector. - mo.bspLeaf = &bspLeafAt_FixedPrecision(mo.origin); + BspLeaf &bspLeafAtOrigin = bspLeafAt_FixedPrecision(mo.origin); + // Link into the sector? + /// @todo fixme: Never link to a degenerate BSP leaf! if(flags & DDLINK_SECTOR) { - /// @todo fixme: Never link to a degenerate BSP leaf! - DENG_ASSERT(mo.bspLeaf->hasSector()); - - // Unlink from the current sector, if any. - Sector &sec = mo.bspLeaf->sector(); - - if(mo.sPrev) - Mobj_UnlinkFromSector(&mo); - - // Link the new mobj to the head of the list. - // Prev pointers point to the pointer that points back to us. - // (Which practically disallows traversing the list backwards.) - - if((mo.sNext = sec.firstMobj())) - mo.sNext->sPrev = &mo.sNext; - - *(mo.sPrev = &sec._mobjList) = &mo; + d->unlinkMobjFromSectors(mo); + DENG_ASSERT(bspLeafAtOrigin.hasSector()); + bspLeafAtOrigin.sector().link(&mo); } + mo.bspLeaf = &bspLeafAtOrigin; // Link into blockmap? if(flags & DDLINK_BLOCKMAP) @@ -2015,7 +1996,7 @@ void Map::link(mobj_t &mo, byte flags) player->inVoid = true; - if(player->mo->bspLeaf && player->mo->bspLeaf->hasSector()) + if(player->mo->bspLeaf) { BspLeaf &bspLeaf = *player->mo->bspLeaf; if(bspLeaf.polyContains(player->mo->origin)) diff --git a/doomsday/client/src/world/p_mobj.cpp b/doomsday/client/src/world/p_mobj.cpp index 6ea7e4a0e3..b8edb990ac 100644 --- a/doomsday/client/src/world/p_mobj.cpp +++ b/doomsday/client/src/world/p_mobj.cpp @@ -161,26 +161,9 @@ void P_MobjRecycle(mobj_t* mo) unusedMobjs = mo; } -/** - * Two links to update: - * 1) The link to us from the previous node (sprev, always set) will - * be modified to point to the node following us. - * 2) If there is a node following us, set its sprev pointer to point - * to the pointer that points back to it (our sprev, just modified). - */ -boolean Mobj_UnlinkFromSector(mobj_t *mo) +boolean Mobj_IsSectorLinked(mobj_t *mo) { - if(!mo || !IS_SECTOR_LINKED(mo)) - return false; - - if((*mo->sPrev = mo->sNext)) - mo->sNext->sPrev = mo->sPrev; - - // Not linked any more. - mo->sNext = 0; - mo->sPrev = 0; - - return true; + return mo != 0 && mo->bspLeaf != 0 && mo->sPrev != 0; } /** diff --git a/doomsday/client/src/world/sector.cpp b/doomsday/client/src/world/sector.cpp index 42adfdc594..3ba870c4db 100644 --- a/doomsday/client/src/world/sector.cpp +++ b/doomsday/client/src/world/sector.cpp @@ -32,6 +32,7 @@ #include "world/map.h" #include "world/maputil.h" +#include "world/p_object.h" #include "world/sector.h" @@ -40,8 +41,7 @@ using namespace de; DENG2_PIMPL(Sector), DENG2_OBSERVES(Plane, HeightChange) { - /// Bounding box for the whole sector (all clusters). - AABoxd aaBox; + AABoxd aaBox; ///< Bounding box for the whole sector (all clusters). bool needAABoxUpdate; ///< @c true= marked for update. SoundEmitter emitter; ///< Head of the sound emitter chain. @@ -49,6 +49,7 @@ DENG2_OBSERVES(Plane, HeightChange) Planes planes; ///< All owned planes. Sides sides; ///< All referencing line sides (not owned). Clusters clusters; ///< All owned BSP leaf clusters. + mobj_t *mobjList; ///< All mobjs "in" the sector (not owned). float lightLevel; ///< Ambient light level. Vector3f lightColor; ///< Ambient light color. @@ -56,9 +57,7 @@ DENG2_OBSERVES(Plane, HeightChange) int validCount; #ifdef __CLIENT__ - /// Rough approximation of sector area (map units squared). @c <0 means an - /// update is necessary. - coord_t roughArea; + coord_t roughArea; ///< Approximated. @c <0 means an update is needed. /// Ambient lighting data for the bias lighting model. LightGridData lightGridData; @@ -67,6 +66,7 @@ DENG2_OBSERVES(Plane, HeightChange) Instance(Public *i, float lightLevel, Vector3f const &lightColor) : Base(i), needAABoxUpdate(false), // No BSP leafs thus no geometry. + mobjList(0), lightLevel(lightLevel), lightColor(lightColor), validCount(0) @@ -187,9 +187,7 @@ DENG2_OBSERVES(Plane, HeightChange) Sector::Sector(float lightLevel, Vector3f const &lightColor) : MapElement(DMU_SECTOR), d(new Instance(this, lightLevel, lightColor)) -{ - _mobjList = 0; -} +{} float Sector::lightLevel() const { @@ -233,7 +231,7 @@ void Sector::setLightColor(Vector3f const &newLightColor) void Sector::setLightColorComponent(int component, float newStrength) { - DENG_ASSERT(component >= 0 && component < 3); + DENG2_ASSERT(component >= 0 && component < 3); newStrength = de::clamp(0.f, newStrength, 1.f); if(!de::fequal(d->lightColor[component], newStrength)) { @@ -247,7 +245,40 @@ void Sector::setLightColorComponent(int component, float newStrength) struct mobj_s *Sector::firstMobj() const { - return _mobjList; + return d->mobjList; +} + +/** + * Two links to update: + * 1) The link to the mobj from the previous node (sprev, always set) will + * be modified to point to the node following it. + * 2) If there is a node following the mobj, set its sprev pointer to point + * to the pointer that points back to it (the mobj's sprev, just modified). + */ +void Sector::unlink(mobj_t *mobj) +{ + if(!mobj || !Mobj_IsSectorLinked(mobj)) + return; + + if((*mobj->sPrev = mobj->sNext)) + mobj->sNext->sPrev = mobj->sPrev; + + // Not linked any more. + mobj->sNext = 0; + mobj->sPrev = 0; +} + +void Sector::link(mobj_t *mobj) +{ + if(!mobj) return; + + // Prev pointers point to the pointer that points back to us. + // (Which practically disallows traversing the list backwards.) + + if((mobj->sNext = d->mobjList)) + mobj->sNext->sPrev = &mobj->sNext; + + *(mobj->sPrev = &d->mobjList) = mobj; } SoundEmitter &Sector::soundEmitter() @@ -737,7 +768,7 @@ int Sector::property(DmuArgs &args) const args.setValue(DMT_SECTOR_EMITTER, &emitterAdr, 0); break; } case DMT_MOBJS: - args.setValue(DMT_SECTOR_MOBJLIST, &_mobjList, 0); + args.setValue(DMT_SECTOR_MOBJLIST, &d->mobjList, 0); break; case DMU_VALID_COUNT: args.setValue(DMT_SECTOR_VALIDCOUNT, &d->validCount, 0);