Skip to content

Commit

Permalink
ConvexSubspace: Encapsulate all BSP leaf geometry generation
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Jun 4, 2013
1 parent be4d749 commit 6209efd
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 134 deletions.
24 changes: 9 additions & 15 deletions doomsday/client/include/map/bsp/convexsubspace.h
Expand Up @@ -105,12 +105,6 @@ class ConvexSubspace
*/
inline bool isEmpty() const { return segmentCount() == 0; }

/**
* Returns @c true iff at least one line segment in the set is derived from
* a map line.
*/
bool hasMapLineSegment() const;

/**
* Add more line segments to the subspace. It is assumed that the new set
* conforms to, or is compatible with the subspace.
Expand Down Expand Up @@ -153,24 +147,22 @@ class ConvexSubspace
return *this;
}

Polygon *buildLeafGeometry() const;

/**
* Determines from the set of line segments which sector to attribute to
* any BSP leaf we might subsequently produce for them.
* Build and assign all geometries to the BSP leaf specified. Note that
* any existing geometries will be replaced (thus destroyed by BspLeaf).
* Also, a map sector is chosen and attributed to the BSP leaf.
*
* This choice is presently determined with a heuristic accounting of the
* number of references to each candidate sector. References are divided
* into groups according to the "type" of the referencing line segment for
* rating.
* @param bspLeaf BSP leaf to build geometry for.
*/
Sector *chooseSectorForBspLeaf() const;
void buildGeometry(BspLeaf &bspLeaf) const;

/**
* The BspLeaf to which the subspace has been attributed. May return @c 0
* if not attributed.
*
* @see setBspLeaf()
*
* @todo Refactor away.
*/
BspLeaf *bspLeaf() const;

Expand All @@ -181,6 +173,8 @@ class ConvexSubspace
* Can be @c 0 (to clear the attribution).
*
* @see bspLeaf()
*
* @todo Refactor away.
*/
void setBspLeaf(BspLeaf *newBspLeaf);

Expand Down
185 changes: 98 additions & 87 deletions doomsday/client/src/map/bsp/convexsubspace.cpp
Expand Up @@ -209,6 +209,20 @@ DENG2_PIMPL_NOREF(ConvexSubspace)
bspLeaf (other.bspLeaf)
{}

/**
* Returns @c true iff at least one line segment in the set is derived from
* a map line.
*/
bool hasMapLineSegment()
{
foreach(LineSegment::Side *seg, segments)
{
if(seg->hasMapSide())
return true;
}
return false;
}

Vector2d findCenter()
{
Vector2d center;
Expand Down Expand Up @@ -412,129 +426,116 @@ void ConvexSubspace::addOneSegment(LineSegment::Side const &newSegment)
}
}

Polygon *ConvexSubspace::buildLeafGeometry() const
void ConvexSubspace::buildGeometry(BspLeaf &leaf) const
{
if(isEmpty()) return 0;
LOG_AS("ConvexSubspace::buildGeometry");

if(d->needRebuildContinuities)
{
d->buildContinuityMap();
}

// Construct the polygon and ring of half-edges.
Polygon *poly = new Polygon;

// Iterate backwards so that the half-edges can be linked clockwise.
for(int i = d->orderedSegments.size(); i-- > 0; )
bool const isDegenerate = segmentCount() < 3;
if(!isDegenerate)
{
LineSegment::Side *lineSeg = d->orderedSegments[i].segment;
Line::Side *mapSide = lineSeg->mapSidePtr();
HEdge *hedge = new HEdge(lineSeg->from());

// Ownership of the segment will be assigned to the space partitioner.
Segment *seg = new Segment(mapSide, hedge);
// Sanity check.
if(!d->hasMapLineSegment())
throw Error("ConvexSubspace::buildGeometry", "No map line segment");

// Attribute the half-edge to the segment.
hedge->setMapElement(seg);
// Construct the polygon and ring of half-edges.
Polygon *poly = new Polygon;

if(mapSide)
// Iterate backwards so that the half-edges can be linked clockwise.
for(int i = d->orderedSegments.size(); i-- > 0; )
{
seg->setLineSideOffset(Vector2d(mapSide->from().origin() - lineSeg->from().origin()).length());
}
LineSegment::Side *lineSeg = d->orderedSegments[i].segment;
Line::Side *mapSide = lineSeg->mapSidePtr();
HEdge *hedge = new HEdge(lineSeg->from());

seg->setLength(Vector2d(lineSeg->to().origin() - lineSeg->from().origin()).length());
// Ownership of the segment will be assigned to the space partitioner.
Segment *seg = new Segment(mapSide, hedge);

seg->setAngle(bamsAtan2(int( lineSeg->to().origin().y - lineSeg->from().origin().y ),
int( lineSeg->to().origin().x - lineSeg->from().origin().x )) << FRACBITS);
// Attribute the half-edge to the segment.
hedge->setMapElement(seg);

// Link the new half-edge for this line segment to the head of
// the list in the new polygon geometry.
hedge->setNext(poly->_hedge);
poly->_hedge = hedge;
if(mapSide)
{
seg->setLineSideOffset(Vector2d(mapSide->from().origin() - lineSeg->from().origin()).length());
}

// Is there a half-edge on the back side we need to twin with?
if(lineSeg->back().hasSegment())
{
lineSeg->back().segment().hedge().setTwin(hedge);
hedge->setTwin(&lineSeg->back().segment().hedge());
seg->setLength(Vector2d(lineSeg->to().origin() - lineSeg->from().origin()).length());

seg->setBack(&lineSeg->back().segment());
seg->back().setBack(seg);
}
seg->setAngle(bamsAtan2(int( lineSeg->to().origin().y - lineSeg->from().origin().y ),
int( lineSeg->to().origin().x - lineSeg->from().origin().x )) << FRACBITS);

// Link the new segment with the line segment.
lineSeg->setSegment(seg);
}
// Link the new half-edge for this line segment to the head of
// the list in the new polygon geometry.
hedge->setNext(poly->_hedge);
poly->_hedge = hedge;

// Link the half-edges anticlockwise and close the ring.
HEdge *hedge = poly->_hedge;
forever
{
// There is now one more half-edge in this polygon.
poly->_hedgeCount += 1;
// Is there a half-edge on the back side we need to twin with?
if(lineSeg->back().hasSegment())
{
lineSeg->back().segment().hedge().setTwin(hedge);
hedge->setTwin(&lineSeg->back().segment().hedge());

// Attribute the half edge to the Polygon.
/// @todo Encapsulate in Polygon.
hedge->setPoly(poly);
seg->setBack(&lineSeg->back().segment());
seg->back().setBack(seg);
}

if(hedge->hasNext())
{
// Link anticlockwise.
hedge->next().setPrev(hedge);
hedge = &hedge->next();
// Link the new segment with the line segment.
lineSeg->setSegment(seg);
}
else

// Link the half-edges anticlockwise and close the ring.
HEdge *hedge = poly->_hedge;
forever
{
// Circular link.
hedge->setNext(poly->_hedge);
hedge->next().setPrev(hedge);
break;
}
}
// There is now one more half-edge in this polygon.
poly->_hedgeCount += 1;

/// @todo Polygon should encapsulate.
poly->updateAABox();
poly->updateCenter();
// Attribute the half edge to the Polygon.
/// @todo Encapsulate in Polygon.
hedge->setPoly(poly);

return poly;
}
if(hedge->hasNext())
{
// Link anticlockwise.
hedge->next().setPrev(hedge);
hedge = &hedge->next();
}
else
{
// Circular link.
hedge->setNext(poly->_hedge);
hedge->next().setPrev(hedge);
break;
}
}

Sector *ConvexSubspace::chooseSectorForBspLeaf() const
{
if(isEmpty()) return 0;
/// @todo Polygon should encapsulate.
poly->updateAABox();
poly->updateCenter();

if(d->needRebuildContinuities)
{
d->buildContinuityMap();
// Assign the polygon geometry to the BSP leaf (takes ownership).
leaf.setPoly(poly);
}
return d->sector;
}

BspLeaf *ConvexSubspace::bspLeaf() const
{
return d->bspLeaf;
}
// Determine which sector to attribute to the BSP leaf.
leaf.setSector(d->sector);

void ConvexSubspace::setBspLeaf(BspLeaf *newBspLeaf)
{
d->bspLeaf = newBspLeaf;
if(!leaf.hasSector())
{
LOG_WARNING("BspLeaf %p is degenerate/orphan (%d half-edges).")
<< de::dintptr(&leaf) << (leaf.hasPoly()? leaf.poly().hedgeCount() : 0);
}
}

int ConvexSubspace::segmentCount() const
{
return d->segments.count();
}

bool ConvexSubspace::hasMapLineSegment() const
{
foreach(LineSegment::Side *seg, d->segments)
{
if(seg->hasMapSide())
return true;
}
return false;
}

OrderedSegments const &ConvexSubspace::segments() const
{
if(d->needRebuildOrderedSegments)
Expand All @@ -544,5 +545,15 @@ OrderedSegments const &ConvexSubspace::segments() const
return d->orderedSegments;
}

BspLeaf *ConvexSubspace::bspLeaf() const
{
return d->bspLeaf;
}

void ConvexSubspace::setBspLeaf(BspLeaf *newBspLeaf)
{
d->bspLeaf = newBspLeaf;
}

} // namespace bsp
} // namespace de
42 changes: 10 additions & 32 deletions doomsday/client/src/map/bsp/partitioner.cpp
Expand Up @@ -1420,41 +1420,19 @@ DENG2_PIMPL(Partitioner)
foreach(ConvexSubspace const &subspace, convexSubspaces)
{
/// @todo Move BSP leaf construction here.
BspLeaf *leaf = subspace.bspLeaf();
BspLeaf &bspLeaf = *subspace.bspLeaf();

bool const isDegenerate = subspace.segmentCount() < 3;
if(!isDegenerate)
{
// Sanity check.
if(!subspace.hasMapLineSegment())
throw Error("Partitioner::buildLeafGeometries",
QString("ConvexSubspace 0x%1 has no map line segment")
.arg(dintptr(&subspace), 0, 16));

// Construct a new polygon geometry and assign it to
// the BSP leaf (takes ownership).
leaf->setPoly(subspace.buildLeafGeometry());

// Account for the new segments.
HEdge *firstHEdge = leaf->poly().firstHEdge();
HEdge *hedge = firstHEdge;
do
{
if(hedge->mapElement())
{
// There is now one more Segment.
numSegments += 1;
}
} while((hedge = &hedge->next()) != firstHEdge);
}

// Determine which sector to attribute to the BSP leaf.
leaf->setSector(subspace.chooseSectorForBspLeaf());
subspace.buildGeometry(bspLeaf);

if(!leaf->hasSector())
// Account the new segments.
/// @todo Refactor away.
foreach(OrderedSegment const &oseg, subspace.segments())
{
LOG_WARNING("BspLeaf %p is degenerate/orphan (%d half-edges).")
<< de::dintptr(leaf) << (leaf->hasPoly()? leaf->poly().hedgeCount() : 0);
if(oseg.segment->hasSegment())
{
// There is now one more Segment.
numSegments += 1;
}
}
}

Expand Down

0 comments on commit 6209efd

Please sign in to comment.