Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
SectionEdge: Further improved the design of this component
Edges can now be copied, taking advantage of implicitly shared
intercepts (until modified). Various API improvements to enhance
flexibility and/or factor out usage preconditions.

Note this is still very much a work in progress. There remains
several API and/or design issues to resolve.
  • Loading branch information
danij-deng committed May 4, 2013
1 parent ab2041c commit 07d615f
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 129 deletions.
45 changes: 31 additions & 14 deletions doomsday/client/include/map/hedge.h
Expand Up @@ -40,6 +40,13 @@ class Sector;
#define HEDGEINF_FACINGFRONT 0x0001
///@}

/// Logical clock-wise direction identifiers:
enum ClockDirection
{
Anticlockwise,
Clockwise
};

/**
* Map geometry half-edge.
*
Expand Down Expand Up @@ -77,6 +84,13 @@ class HEdge : public de::MapElement
To
};

/// Logical side identifiers:
enum
{
Front,
Back
};

public: /// @todo Make private:
/// Start and End vertexes of the segment.
Vertex *_from, *_to;
Expand Down Expand Up @@ -232,9 +246,10 @@ class HEdge : public de::MapElement
BspLeaf &bspLeaf() const;

/**
* Convenient accessor method for returning the sector attributed to the BSP
* leaf for the half-edge. One should first determine whether a sector is indeed
* attributed to the BSP leaf (e.g., by calling @ref BspLeaf::hasSector()).
* Convenient accessor method for returning the sector attributed to
* the BSP leaf for the half-edge. One should first determine whether
* a sector is indeed attributed to the BSP leaf (e.g., by calling
* @ref BspLeaf::hasSector()).
*
* @see bspLeaf(), BspLeaf::sector()
*/
Expand All @@ -243,6 +258,19 @@ class HEdge : public de::MapElement
/// Variant of @ref bspLeafSector() which returns a pointer.
inline Sector *bspLeafSectorPtr() const { return bspLeaf().sectorPtr(); }

/**
* Determines the side relative sector to be used for producing wall
* section geometry. Takes into account doom.exe map hack constructs.
* Also suitable for Polyobj lines.
*
* @pre A map line side is attributed (@ref hasLineSide()).
*
* @param side If non-zero return the back sector; otherwise the front.
*
* @return Map sector for the specified side. Can be @c 0.
*/
Sector *wallSectionSector(int side = Front) const;

/**
* Returns @c true iff a Line::Side is attributed to the half-edge.
*/
Expand Down Expand Up @@ -335,17 +363,6 @@ class HEdge : public de::MapElement
return pointOnSide(point);
}

/**
* Determines the side relative sectors for producing wall section geometry.
*
* @pre A map line side is attributed (@ref hasLineSide()).
*
* Return values:
* @param frontSec Front sector for the wall section is written here. Can be @c 0.
* @param backSec Back sector for the wall section is written here. Can be @c 0.
*/
void wallSectionSectors(Sector **frontSec = 0, Sector **backSec = 0) const;

/**
* Retrieve the bias surface for specified geometry @a groupId
*
Expand Down
29 changes: 10 additions & 19 deletions doomsday/client/include/map/lineowner.h
Expand Up @@ -21,9 +21,11 @@
#ifndef DENG_WORLD_MAP_LINEOWNER
#define DENG_WORLD_MAP_LINEOWNER

#include <de/binangle.h>

#include <de/Vector>

#include <de/binangle.h>
#include "HEdge"

class Line;

Expand All @@ -34,21 +36,10 @@ class Line;
*/
class LineOwner
{
public:
/// Ring navigation direction identifiers:
enum Direction
{
/// Previous (anticlockwise).
Previous,

/// Next (clockwise).
Next
};

public: /// @todo Make private:
Line *_line;

/// {Previous, Next} (i.e. {anticlk, clk}).
/// {Anitclockwise, Clockwise}
LineOwner *_link[2];

/// Angle between this and the next line owner, clockwise.
Expand Down Expand Up @@ -86,32 +77,32 @@ class LineOwner
* Navigate to the adjacent line owner in the ring (if any). Note this may
* be the same LineOwner.
*/
LineOwner &navigate(Direction dir = Previous) { return *_link[dir]; }
LineOwner &navigate(ClockDirection dir = Anticlockwise) { return *_link[dir]; }

/// @copydoc navigate()
LineOwner const &navigate(Direction dir = Previous) const { return *_link[dir]; }
LineOwner const &navigate(ClockDirection dir = Anticlockwise) const { return *_link[dir]; }

/**
* Returns the previous line owner in the ring (anticlockwise). Note that
* this may be the same LineOwner.
*
* @see hasPrev()
*/
inline LineOwner &prev() { return navigate(Previous); }
inline LineOwner &prev() { return navigate(Anticlockwise); }

/// @copydoc prev()
inline LineOwner const &prev() const { return navigate(Previous); }
inline LineOwner const &prev() const { return navigate(Anticlockwise); }

/**
* Returns the next line owner in the ring (clockwise). Note that this may
* be the same LineOwner.
*
* @see hasNext()
*/
inline LineOwner &next() { return navigate(Next); }
inline LineOwner &next() { return navigate(Clockwise); }

/// @copydoc next()
inline LineOwner const &next() const { return navigate(Next); }
inline LineOwner const &next() const { return navigate(Clockwise); }

/**
* Returns the line "owner".
Expand Down
31 changes: 29 additions & 2 deletions doomsday/client/include/map/sectionedge.h
Expand Up @@ -46,19 +46,38 @@ class SectionEdge

struct Intercept
{
SectionEdge *owner;
double distance;

Intercept(double distance = 0) : distance(distance) {}
Intercept(SectionEdge *owner, double distance = 0);
Intercept(Intercept const &other);

inline bool operator < (Intercept const &other) const {
return distance < other.distance;
}

de::Vector3d origin() const;
};

typedef QList<Intercept> Intercepts;

public:
SectionEdge(HEdge &hedge, int edge, int section);
SectionEdge(Line::Side &lineSide, int section, coord_t lineOffset,
Vertex &lineVertex, ClockDirection neighborScanDirection,
Sector *frontSec, Sector *backSec);

SectionEdge(HEdge &hedge, int section, int edge);

SectionEdge(SectionEdge const &other);

inline SectionEdge &operator = (SectionEdge other) {
d.swap(other.d);
return *this;
}

inline void swap(SectionEdge &other) {
d.swap(other.d);
}

inline Intercept const & operator [] (int index) const {
return at(index);
Expand Down Expand Up @@ -98,4 +117,12 @@ class SectionEdge
DENG2_PRIVATE(d)
};

namespace std {
// std::swap specialization for SectionEdge
template <>
inline void swap<SectionEdge>(SectionEdge &a, SectionEdge &b) {
a.swap(b);
}
}

#endif // DENG_WORLD_MAP_SECTION_EDGE
28 changes: 14 additions & 14 deletions doomsday/client/src/edit_map.cpp
Expand Up @@ -451,7 +451,7 @@ static int lineAngleSorter(void const *a, void const *b)
LineOwner *own[2] = { (LineOwner *)a, (LineOwner *)b };
for(uint i = 0; i < 2; ++i)
{
if(own[i]->_link[LineOwner::Previous]) // We have a cached result.
if(own[i]->_link[Anticlockwise]) // We have a cached result.
{
angles[i] = own[i]->angle();
}
Expand All @@ -466,7 +466,7 @@ static int lineAngleSorter(void const *a, void const *b)
own[i]->_angle = angles[i] = bamsAtan2(-100 *dx, 100 * dy);

// Mark as having a cached angle.
own[i]->_link[LineOwner::Previous] = (LineOwner *) 1;
own[i]->_link[Anticlockwise] = (LineOwner *) 1;
}
}

Expand All @@ -484,19 +484,19 @@ static LineOwner *mergeLineOwners(LineOwner *left, LineOwner *right,
LineOwner tmp;
LineOwner *np = &tmp;

tmp._link[LineOwner::Next] = np;
tmp._link[Clockwise] = np;
while(left && right)
{
if(compare(left, right) <= 0)
{
np->_link[LineOwner::Next] = left;
np->_link[Clockwise] = left;
np = left;

left = &left->next();
}
else
{
np->_link[LineOwner::Next] = right;
np->_link[Clockwise] = right;
np = right;

right = &right->next();
Expand All @@ -506,11 +506,11 @@ static LineOwner *mergeLineOwners(LineOwner *left, LineOwner *right,
// At least one of these lists is now empty.
if(left)
{
np->_link[LineOwner::Next] = left;
np->_link[Clockwise] = left;
}
if(right)
{
np->_link[LineOwner::Next] = right;
np->_link[Clockwise] = right;
}

// Is the list empty?
Expand Down Expand Up @@ -539,7 +539,7 @@ static LineOwner *splitLineOwners(LineOwner *list)
}
} while(lista);

listc->_link[LineOwner::Next] = NULL;
listc->_link[Clockwise] = NULL;
return listb;
}

Expand All @@ -549,7 +549,7 @@ static LineOwner *splitLineOwners(LineOwner *list)
static LineOwner *sortLineOwners(LineOwner *list,
int (*compare) (void const *a, void const *b))
{
if(list && list->_link[LineOwner::Next])
if(list && list->_link[Clockwise])
{
LineOwner *p = splitLineOwners(list);

Expand Down Expand Up @@ -579,14 +579,14 @@ static void setVertexLineOwner(Vertex *vtx, Line *lineptr, LineOwner **storage)
LineOwner *newOwner = (*storage)++;

newOwner->_line = lineptr;
newOwner->_link[LineOwner::Previous] = NULL;
newOwner->_link[Anticlockwise] = NULL;

// Link it in.
// NOTE: We don't bother linking everything at this stage since we'll
// be sorting the lists anyway. After which we'll finish the job by
// setting the prev and circular links.
// So, for now this is only linked singlely, forward.
newOwner->_link[LineOwner::Next] = vtx->_lineOwners;
newOwner->_link[Clockwise] = vtx->_lineOwners;
vtx->_lineOwners = newOwner;

// Link the line to its respective owner node.
Expand Down Expand Up @@ -656,16 +656,16 @@ static void buildVertexLineOwnerRings()
LineOwner *p = &last->next();
while(p)
{
p->_link[LineOwner::Previous] = last;
p->_link[Anticlockwise] = last;

// Convert to a relative angle between last and this.
last->_angle = last->angle() - p->angle();

last = p;
p = &p->next();
}
last->_link[LineOwner::Next] = v->_lineOwners;
v->_lineOwners->_link[LineOwner::Previous] = last;
last->_link[Clockwise] = v->_lineOwners;
v->_lineOwners->_link[Anticlockwise] = last;

// Set the angle of the last owner.
last->_angle = last->angle() - firstAngle;
Expand Down
25 changes: 12 additions & 13 deletions doomsday/client/src/map/hedge.cpp
Expand Up @@ -174,29 +174,28 @@ coord_t HEdge::length() const
return _length;
}

void HEdge::wallSectionSectors(Sector **frontSec, Sector **backSec) const
Sector *HEdge::wallSectionSector(int side) const
{
if(!d->lineSide)
/// @throw MissingLineError Attempted with no line attributed.
throw MissingLineSideError("HEdge::wallSectionSectors", "No line.side is attributed");
throw MissingLineSideError("HEdge::wallSectionSector", "No line.side is attributed");

if(d->lineSide->line().isFromPolyobj())
Line::Side const &mapSide = *d->lineSide;
if(mapSide.line().isFromPolyobj())
{
if(frontSec) *frontSec = bspLeaf().sectorPtr();
if(backSec) *backSec = 0;
return;
if(side == Front) return bspLeaf().sectorPtr();
return 0;
}

if(!d->lineSide->line().isSelfReferencing())
if(!mapSide.line().isSelfReferencing())
{
if(frontSec) *frontSec = bspLeaf().sectorPtr();
if(backSec) *backSec = hasTwin()? twin().bspLeaf().sectorPtr() : 0;
return;
if(side == Front) return bspLeaf().sectorPtr();
return hasTwin()? twin().bspLeaf().sectorPtr() : 0;
}

// Special case: so called "self-referencing" lines use the sector's of the map line.
if(frontSec) *frontSec = d->lineSide->sectorPtr();
if(backSec) *backSec = d->lineSide->sectorPtr();
// Special case: so called "self-referencing" lines should use the
// sector of the map line side.
return mapSide.sectorPtr();
}

biassurface_t &HEdge::biasSurfaceForGeometryGroup(uint groupId)
Expand Down

0 comments on commit 07d615f

Please sign in to comment.