Skip to content

Commit

Permalink
HEdge: API improvements
Browse files Browse the repository at this point in the history
Added a navigate() method which returns the relative neighbor of
the half-edge in the specified ClockDirection. Also removed the
unnecessary next/prevIsThis() methods.
  • Loading branch information
danij-deng committed May 11, 2013
1 parent ec3e058 commit 69b1eb8
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 82 deletions.
31 changes: 11 additions & 20 deletions doomsday/client/include/map/hedge.h
Expand Up @@ -184,36 +184,27 @@ class HEdge : public de::MapElement
}

/**
* Returns the linked @em next half-edge (clockwise) around the face of
* the half-edge (which might be *this* half-edge).
* Returns the neighbor half-edge in the specified @a direction around the
* face of the polygon (which might be *this* half-edge in the case of a
* degenerate polygon).
*
* @see nextIsThis()
* @param direction Relative direction for desired neighbor half-edge.
*/
HEdge &next() const;
HEdge &navigate(ClockDirection direction) const;

/**
* Returns @c true iff the @em next half-edge (clockwise) around the face
* of the half-edge is *this*.
* Returns the @em clockwise neighbor half-edge around the face of the polygon.
*
* @see next()
* @see navigate(), nextIsThis()
*/
inline bool nextIsThis() const { return &next() == this; }
inline HEdge &next() const { return navigate(Clockwise); }

/**
* Returns the linked @em previous half-edge (anticlockwise) around the
* face of the half-edge (which might be *this* half-edge).
* Returns the @em anticlockwise neighbor half-edge around the face of the polygon.
*
* @see prevIsThis()
* @see navigate(), prevIsThis()
*/
HEdge &prev() const;

/**
* Returns @c true iff the @em previous half-edge (anticlockwise) around
* the face of the half-edge is *this*.
*
* @see prev()
*/
inline bool prevIsThis() const { return &prev() == this; }
inline HEdge &prev() const { return navigate(Anticlockwise); }

/**
* Returns @c true iff a @em twin is linked to the half-edge.
Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/map/bspleaf.cpp
Expand Up @@ -206,7 +206,7 @@ BspLeaf::~BspLeaf()
// Break the ring, if linked.
if(he->_prev)
{
he->_prev->_next = NULL;
he->_prev->_next = 0;
}

while(he)
Expand Down
21 changes: 9 additions & 12 deletions doomsday/client/src/map/hedge.cpp
Expand Up @@ -28,22 +28,26 @@ using namespace de;

DENG2_PIMPL(HEdge)
{
/// Map Line::Side attributed to the half-edge. Can be @c 0 (mini-edge).
/// Map Line::Side attributed to the half-edge. Can be @c 0 (partition segment).
Line::Side *lineSide;

Instance(Public *i)
: Base(i),
lineSide(0)
{}

inline HEdge **neighborAdr(ClockDirection direction) {
return direction == Clockwise? &self._next : &self._prev;
}
};

HEdge::HEdge(Vertex &from, Line::Side *lineSide)
: MapElement(DMU_HEDGE), d(new Instance(this))
{
_from = &from;
_to = 0;
_next = 0;
_prev = 0;
_next = this;
_prev = this;
_twin = 0;
_bspLeaf = 0;
_angle = 0;
Expand Down Expand Up @@ -97,16 +101,9 @@ Vertex const &HEdge::vertex(int to) const
return const_cast<Vertex const &>(const_cast<HEdge *>(this)->vertex(to));
}

HEdge &HEdge::next() const
{
DENG2_ASSERT(_next != 0);
return *_next;
}

HEdge &HEdge::prev() const
HEdge &HEdge::navigate(ClockDirection direction) const
{
DENG2_ASSERT(_prev != 0);
return *_prev;
return **d->neighborAdr(direction);
}

bool HEdge::hasTwin() const
Expand Down
100 changes: 51 additions & 49 deletions doomsday/client/src/render/rend_main.cpp
Expand Up @@ -160,7 +160,7 @@ static void Rend_DrawSoundOrigins();
static void Rend_DrawSurfaceVectors();
static void Rend_DrawVertexIndices();

static uint buildLeafPlaneGeometry(BspLeaf const &leaf, bool antiClockwise,
static uint buildLeafPlaneGeometry(BspLeaf const &leaf, ClockDirection direction,
coord_t height, rvertex_t **verts, uint *vertsSize);

// Draw state:
Expand Down Expand Up @@ -1754,7 +1754,8 @@ static void writeLeafPlane(Plane &plane)

uint numVertices;
rvertex_t *rvertices;
buildLeafPlaneGeometry(*leaf, (plane.type() == Plane::Ceiling), plane.visHeight(),
buildLeafPlaneGeometry(*leaf, (plane.type() == Plane::Ceiling)? Anticlockwise : Clockwise,
plane.visHeight(),
&rvertices, &numVertices);

MaterialSnapshot const &ms = material->prepare(mapSurfaceMaterialSpec(GL_REPEAT, GL_REPEAT));
Expand Down Expand Up @@ -1994,29 +1995,31 @@ static inline void buildStripEdge(Vector2d const &vXY,
* | | or | | if antiClockwise
* 0--2 3--1
*/
static void buildSkyFixStrip(BspLeaf *leaf, HEdge *startNode, HEdge *endNode,
bool _antiClockwise, int skyCap, rvertex_t **verts, uint *vertsSize, rtexcoord_t **coords)
static void buildSkyMaskStrip(HEdge &startNode, HEdge &endNode, ClockDirection direction,
int skyCap, rvertex_t **verts, uint *vertsSize, rtexcoord_t **coords)
{
int const antiClockwise = _antiClockwise? 1:0;
DENG_ASSERT(startNode.hasBspLeaf());
DENG_ASSERT(&startNode.bspLeaf() == &endNode.bspLeaf());

*vertsSize = 0;
*verts = 0;

if(!startNode || !endNode || !skyCap) return;
if(!skyCap) return;

// Count verts.
if(startNode == endNode)
if(&startNode == &endNode)
{
// Special case: the whole edge loop.
*vertsSize += 2 * (leaf->hedgeCount() + 1);
*vertsSize += 2 * (startNode.bspLeaf().hedgeCount() + 1);
}
else
{
HEdge *afterEndNode = antiClockwise? &endNode->prev() : &endNode->next();
HEdge *node = startNode;
HEdge *afterEndNode = &endNode.navigate(direction);
HEdge *node = &startNode;
do
{
*vertsSize += 2;
} while((node = antiClockwise? &node->prev() : &node->next()) != afterEndNode);
} while((node = &node->navigate(direction)) != afterEndNode);
}

// Build geometry.
Expand All @@ -2026,12 +2029,13 @@ static void buildSkyFixStrip(BspLeaf *leaf, HEdge *startNode, HEdge *endNode,
*coords = R_AllocRendTexCoords(*vertsSize);
}

HEdge *node = startNode;
int const windOffset = direction == Anticlockwise? 1 : 0;
HEdge *node = &startNode;
float texS = float( node->hasLineSide()? node->lineOffset() : 0 );
uint n = 0;
do
{
HEdge *hedge = (antiClockwise? &node->prev() : node);
HEdge *hedge = (direction == Anticlockwise? &node->prev() : node);
coord_t zBottom, zTop;

skyFixZCoords(hedge, skyCap, &zBottom, &zTop);
Expand All @@ -2040,55 +2044,54 @@ static void buildSkyFixStrip(BspLeaf *leaf, HEdge *startNode, HEdge *endNode,
if(n == 0)
{
// Add the first edge.
rvertex_t *v1 = &(*verts)[n + antiClockwise];
rvertex_t *v2 = &(*verts)[n + (antiClockwise^1)];
rtexcoord_t *t1 = coords? &(*coords)[n + antiClockwise] : NULL;
rtexcoord_t *t2 = coords? &(*coords)[n + (antiClockwise^1)] : NULL;
rvertex_t *v1 = &(*verts)[n + windOffset];
rvertex_t *v2 = &(*verts)[n + (windOffset^1)];
rtexcoord_t *t1 = coords? &(*coords)[n + windOffset] : 0;
rtexcoord_t *t2 = coords? &(*coords)[n + (windOffset^1)] : 0;

buildStripEdge(node->fromOrigin(), zBottom, zTop, texS, v1, v2, t1, t2);

if(coords)
{
texS += antiClockwise? -node->prev().length() : hedge->length();
texS += direction == Anticlockwise? -node->prev().length() : hedge->length();
}

n += 2;
}

// Add the next edge.
{
rvertex_t *v1 = &(*verts)[n + antiClockwise];
rvertex_t *v2 = &(*verts)[n + (antiClockwise^1)];
rtexcoord_t *t1 = coords? &(*coords)[n + antiClockwise] : NULL;
rtexcoord_t *t2 = coords? &(*coords)[n + (antiClockwise^1)] : NULL;
rvertex_t *v1 = &(*verts)[n + windOffset];
rvertex_t *v2 = &(*verts)[n + (windOffset^1)];
rtexcoord_t *t1 = coords? &(*coords)[n + windOffset] : 0;
rtexcoord_t *t2 = coords? &(*coords)[n + (windOffset^1)] : 0;

buildStripEdge((antiClockwise? &node->prev() : &node->next())->fromOrigin(),
zBottom, zTop, texS, v1, v2, t1, t2);
buildStripEdge(node->navigate(direction).fromOrigin(),
zBottom, zTop, texS, v1, v2, t1, t2);

if(coords)
{
texS += antiClockwise? -hedge->length() : hedge->next().length();
}

n += 2;
if(coords)
{
texS += direction == Anticlockwise? -hedge->length() : hedge->next().length();
}
} while((node = antiClockwise? &node->prev() : &node->next()) != endNode);

n += 2;

} while((node = &node->navigate(direction)) != &endNode);
}

static void Rend_WriteBspLeafSkyFixStripGeometry(BspLeaf *leaf, HEdge *startNode,
HEdge *endNode, bool antiClockwise, int skyFix, Material *material)
static void writeSkyMaskStrip(HEdge &startNode, HEdge &endNode, ClockDirection direction,
int skyFix, Material *material)
{
int const rendPolyFlags = RPF_DEFAULT | (!devRendSkyMode? RPF_SKYMASK : 0);
rtexcoord_t *coords = 0;
rvertex_t *verts;
uint vertsSize;

buildSkyFixStrip(leaf, startNode, endNode, antiClockwise, skyFix,
&verts, &vertsSize, devRendSkyMode? &coords : NULL);
buildSkyMaskStrip(startNode, endNode, direction, skyFix,
&verts, &vertsSize, devRendSkyMode? &coords : 0);

if(!devRendSkyMode)
{
RL_AddPoly(PT_TRIANGLE_STRIP, rendPolyFlags, vertsSize, verts, NULL);
RL_AddPoly(PT_TRIANGLE_STRIP, rendPolyFlags, vertsSize, verts, 0);
}
else
{
Expand All @@ -2113,14 +2116,14 @@ static void Rend_WriteBspLeafSkyFixStripGeometry(BspLeaf *leaf, HEdge *startNode
* the trifan, else the mid point of this leaf will be used instead.
*
* @param leaf BspLeaf instance.
* @param antiClockwise @c true= wind vertices in anticlockwise order (else clockwise).
* @param direction Vertex winding direction.
* @param height Z map space height coordinate to be set for each vertex.
* @param verts Built vertices are written here.
* @param vertsSize Number of built vertices is written here. Can be @c NULL.
*
* @return Number of built vertices (same as written to @a vertsSize).
*/
static uint buildLeafPlaneGeometry(BspLeaf const &leaf, bool antiClockwise,
static uint buildLeafPlaneGeometry(BspLeaf const &leaf, ClockDirection direction,
coord_t height, rvertex_t **verts, uint *vertsSize)
{
DENG_ASSERT(verts != 0);
Expand All @@ -2144,7 +2147,7 @@ static uint buildLeafPlaneGeometry(BspLeaf const &leaf, bool antiClockwise,
{
V3f_Set((*verts)[n].pos, node->fromOrigin().x, node->fromOrigin().y, height);
n++;
} while((node = antiClockwise? &node->prev() : &node->next()) != baseNode);
} while((node = &node->navigate(direction)) != baseNode);

// The last vertex is always equal to the first.
if(!fanBase)
Expand All @@ -2167,7 +2170,7 @@ static void writeLeafSkyMaskStrips(int skyFix)
if(!(skyFix & (SKYCAP_LOWER|SKYCAP_UPPER)))
return;

bool const antiClockwise = false;
ClockDirection direction = Clockwise;
bool const splitForSkyMaterials = (devRendSkyMode && renderTextures != 2);

// We may need to break the half-edge loop into multiple strips.
Expand All @@ -2180,7 +2183,7 @@ static void writeLeafSkyMaskStrips(int skyFix)
HEdge *node = base;
forever
{
HEdge *hedge = (antiClockwise? &node->prev() : node);
HEdge *hedge = (direction == Anticlockwise? &node->prev() : node);
bool endStrip = false, beginNewStrip = false;

// Is a fix or two necessary for this edge?
Expand Down Expand Up @@ -2226,8 +2229,7 @@ static void writeLeafSkyMaskStrips(int skyFix)
if(endStrip && startNode)
{
// We have complete strip; build and write it.
Rend_WriteBspLeafSkyFixStripGeometry(bspLeaf, startNode, node, antiClockwise,
skyFix, startMaterial);
writeSkyMaskStrip(*startNode, *node, direction, skyFix, startMaterial);

// End the current strip.
startNode = 0;
Expand All @@ -2237,7 +2239,7 @@ static void writeLeafSkyMaskStrips(int skyFix)
if(beginNewStrip) continue;

// On to the next node.
node = antiClockwise? &node->prev() : &node->next();
node = &node->navigate(direction);

// Are we done?
if(node == base) break;
Expand All @@ -2246,8 +2248,7 @@ static void writeLeafSkyMaskStrips(int skyFix)
// Have we an unwritten strip? - build it.
if(startNode)
{
Rend_WriteBspLeafSkyFixStripGeometry(bspLeaf, startNode, base, antiClockwise,
skyFix, startMaterial);
writeSkyMaskStrip(*startNode, *base, direction, skyFix, startMaterial);
}
}

Expand All @@ -2263,10 +2264,11 @@ static void writeLeafSkyMaskCap(int skyCap)

rvertex_t *verts;
uint numVerts;
buildLeafPlaneGeometry(*bspLeaf, (skyCap & SKYCAP_UPPER) != 0, skyCapZ(bspLeaf, skyCap),
buildLeafPlaneGeometry(*bspLeaf, (skyCap & SKYCAP_UPPER)? Anticlockwise : Clockwise,
skyCapZ(bspLeaf, skyCap),
&verts, &numVerts);

RL_AddPoly(PT_FAN, RPF_DEFAULT | RPF_SKYMASK, numVerts, verts, NULL);
RL_AddPoly(PT_FAN, RPF_DEFAULT | RPF_SKYMASK, numVerts, verts, 0);
R_FreeRendVertices(verts);
}

Expand Down

0 comments on commit 69b1eb8

Please sign in to comment.