From 7737cb06a091b3aadd653694c72fe4fa3af2bc7a Mon Sep 17 00:00:00 2001 From: danij Date: Thu, 13 Jun 2013 02:19:08 +0100 Subject: [PATCH] BspLeaf: Multiple polyobjs can now be linked to a BSP leaf Note that this does not mean that intersecting geometry is now dealt with, however. --- doomsday/client/include/world/bspleaf.h | 24 ++++++++++++------- doomsday/client/src/render/lumobj.cpp | 2 +- doomsday/client/src/render/rend_main.cpp | 26 ++++++++------------- doomsday/client/src/world/bspleaf.cpp | 20 ++++++++++------ doomsday/client/src/world/linesighttest.cpp | 18 +++++++------- doomsday/client/src/world/polyobj.cpp | 13 ++++------- 6 files changed, 52 insertions(+), 51 deletions(-) diff --git a/doomsday/client/include/world/bspleaf.h b/doomsday/client/include/world/bspleaf.h index 9f1df5dfec..9937e4ace9 100644 --- a/doomsday/client/include/world/bspleaf.h +++ b/doomsday/client/include/world/bspleaf.h @@ -22,6 +22,7 @@ #define DENG_WORLD_BSPLEAF_H #include +#include #include #include @@ -71,7 +72,8 @@ class BspLeaf : public de::MapElement DENG2_ERROR(UnknownGeometryGroupError); #endif - typedef QList Segments; + typedef QSet Polyobjs; + typedef QList Segments; public: /// @todo Make private: #ifdef __CLIENT__ @@ -202,20 +204,26 @@ class BspLeaf : public de::MapElement /** * Returns @c true iff at least one polyobj is linked to the BSP leaf. */ - inline bool hasPolyobj() { return firstPolyobj() != 0; } + inline bool hasPolyobj() { return !polyobjs().isEmpty(); } /** - * Returns a pointer to the first polyobj linked to the BSP leaf; otherwise @c 0. + * Add the given @a polyobj to the set of those linked to the BSP leaf. + * Ownership is unaffected. If the polyobj is already linked in this set + * then nothing will happen. */ - struct polyobj_s *firstPolyobj() const; + void addOnePolyobj(struct polyobj_s const &polyobj); /** - * Change the first polyobj linked to the BSP leaf. + * Remove the given @a polyobj from the set of those linked to the BSP leaf. * - * @param newPolyobj New polyobj to be attributed. Ownership is unaffected. - * Can be @c 0 (to clear the attribution). + * @return @c true= @a polyobj was linked and subsequently removed. */ - void setFirstPolyobj(struct polyobj_s *newPolyobj); + bool removeOnePolyobj(polyobj_s const &polyobj); + + /** + * Provides access to the set of polyobjs linked to the BSP leaf. + */ + Polyobjs const &polyobjs() const; /** * Returns the vector described by the offset from the map coordinate space diff --git a/doomsday/client/src/render/lumobj.cpp b/doomsday/client/src/render/lumobj.cpp index ae54c83583..a33821298d 100644 --- a/doomsday/client/src/render/lumobj.cpp +++ b/doomsday/client/src/render/lumobj.cpp @@ -1164,7 +1164,7 @@ boolean LOIT_ClipLumObjBySight(void *data, void *context) // We need to figure out if any of the polyobj's segments lies // between the viewpoint and the lumobj. BspLeaf *bspLeaf = (BspLeaf *) context; - Polyobj *po = bspLeaf->firstPolyobj(); + foreach(Polyobj *po, bspLeaf->polyobjs()) foreach(Line *line, po->lines()) { Segment *segment = line->front().leftSegment(); diff --git a/doomsday/client/src/render/rend_main.cpp b/doomsday/client/src/render/rend_main.cpp index 2315cd0819..5d68733750 100644 --- a/doomsday/client/src/render/rend_main.cpp +++ b/doomsday/client/src/render/rend_main.cpp @@ -2124,9 +2124,7 @@ static void writeLeafPolyobjs() BspLeaf *leaf = currentBspLeaf; DENG_ASSERT(!isNullLeaf(leaf)); - Polyobj *po = leaf->firstPolyobj(); - if(!po) return; - + foreach(Polyobj *po, leaf->polyobjs()) foreach(Line *line, po->lines()) { Segment *seg = line->front().leftSegment(); @@ -2182,16 +2180,14 @@ static void markFrontFacingSegments() seg->setFlags(Segment::FacingFront, dot < 0? UnsetFlags : SetFlags); } - if(Polyobj *po = bspLeaf->firstPolyobj()) + foreach(Polyobj *po, bspLeaf->polyobjs()) + foreach(Line *line, po->lines()) { - foreach(Line *line, po->lines()) - { - Segment *seg = line->front().leftSegment(); + Segment *seg = line->front().leftSegment(); - // Which way is it facing? - double dot = viewFacingDot(seg->from().origin(), seg->to().origin()); - seg->setFlags(Segment::FacingFront, dot < 0? UnsetFlags : SetFlags); - } + // Which way is it facing? + double dot = viewFacingDot(seg->from().origin(), seg->to().origin()); + seg->setFlags(Segment::FacingFront, dot < 0? UnsetFlags : SetFlags); } } @@ -2290,12 +2286,10 @@ static void clipFrontFacingSegments() clipFrontFacingSegment(*seg); } - if(Polyobj *po = bspLeaf->firstPolyobj()) + foreach(Polyobj *po, bspLeaf->polyobjs()) + foreach(Line *line, po->lines()) { - foreach(Line *line, po->lines()) - { - clipFrontFacingSegment(*line->front().leftSegment()); - } + clipFrontFacingSegment(*line->front().leftSegment()); } } diff --git a/doomsday/client/src/world/bspleaf.cpp b/doomsday/client/src/world/bspleaf.cpp index a4e3f95e7b..82a86e9aa5 100644 --- a/doomsday/client/src/world/bspleaf.cpp +++ b/doomsday/client/src/world/bspleaf.cpp @@ -76,8 +76,8 @@ DENG2_PIMPL(BspLeaf) /// Sector attributed to the leaf. @note can be @c 0 (degenerate!). Sector *sector; - /// First Polyobj in the leaf. Can be @c 0 (none). - Polyobj *polyobj; + /// Set of polyobjs linked to the leaf (not owned). + Polyobjs polyobjs; #ifdef __CLIENT__ @@ -103,7 +103,6 @@ DENG2_PIMPL(BspLeaf) needUpdateClockwiseSegments(false), needUpdateAllSegments(false), sector(sector), - polyobj(0), #ifdef __CLIENT__ fanBase(0), needUpdateFanBase(true), @@ -413,14 +412,21 @@ void BspLeaf::setSector(Sector *newSector) d->sector = newSector; } -Polyobj *BspLeaf::firstPolyobj() const +void BspLeaf::addOnePolyobj(Polyobj const &polyobj) { - return d->polyobj; + d->polyobjs.insert(const_cast(&polyobj)); } -void BspLeaf::setFirstPolyobj(Polyobj *newPolyobj) +bool BspLeaf::removeOnePolyobj(polyobj_s const &polyobj) { - d->polyobj = newPolyobj; + int sizeBefore = d->polyobjs.size(); + d->polyobjs.remove(const_cast(&polyobj)); + return d->polyobjs.size() != sizeBefore; +} + +BspLeaf::Polyobjs const &BspLeaf::polyobjs() const +{ + return d->polyobjs; } int BspLeaf::validCount() const diff --git a/doomsday/client/src/world/linesighttest.cpp b/doomsday/client/src/world/linesighttest.cpp index 11ca2018b4..2b9418968f 100644 --- a/doomsday/client/src/world/linesighttest.cpp +++ b/doomsday/client/src/world/linesighttest.cpp @@ -238,19 +238,17 @@ DENG2_PIMPL(LineSightTest) if(bspLeaf.isDegenerate()) return false; - if(Polyobj *po = bspLeaf.firstPolyobj()) + // Check polyobj lines. + foreach(Polyobj *po, bspLeaf.polyobjs()) + foreach(Line *line, po->lines()) { - // Check polyobj lines. - foreach(Line *line, po->lines()) - { - if(line->validCount() == validCount) - continue; + if(line->validCount() == validCount) + continue; - line->setValidCount(validCount); + line->setValidCount(validCount); - if(!crossLine(line->front())) - return false; // Stop traversal. - } + if(!crossLine(line->front())) + return false; // Stop traversal. } // Check the line segment geometries. diff --git a/doomsday/client/src/world/polyobj.cpp b/doomsday/client/src/world/polyobj.cpp index 7bb676c970..4dd571c20c 100644 --- a/doomsday/client/src/world/polyobj.cpp +++ b/doomsday/client/src/world/polyobj.cpp @@ -131,9 +131,11 @@ void Polyobj::unlink() { if(_bspLeaf) { + _bspLeaf->removeOnePolyobj(*this); + _bspLeaf = 0; + /// @todo Do not assume polyobj is from the CURRENT map. App_World().map().unlinkPolyobj(*this); - _bspLeaf = 0; } } @@ -155,14 +157,7 @@ void Polyobj::link() /// @todo Do not assume polyobj is from the CURRENT map. if(BspLeaf *bspLeaf = App_World().map().bspLeafAtPoint(avg)) { - if(bspLeaf->hasPolyobj()) - { - LOG_WARNING("Multiple polyobjs in a single BSP leaf\n" - " (BSP leaf %i, sector %i). Previous polyobj overridden.") - << bspLeaf->indexInMap() - << bspLeaf->sector().indexInMap(); - } - bspLeaf->setFirstPolyobj(this); + bspLeaf->addOnePolyobj(*this); _bspLeaf = bspLeaf; } }