Skip to content

Commit

Permalink
Refactor: Collate the BspBuilder's HEdges in collateBSP
Browse files Browse the repository at this point in the history
It is now unnecessary to split this job into a secondary traversal
as the builder now constructs two trees in parallel (one for the
purposes of guiding the build process and the other containing the
work-in-progress BSP tree elements).
  • Loading branch information
danij-deng committed Mar 17, 2013
1 parent 34ff7bb commit e139c9f
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 142 deletions.
208 changes: 91 additions & 117 deletions doomsday/client/src/edit_map.cpp
Expand Up @@ -1300,80 +1300,20 @@ static void findBounds(Vertex const** vertexes, uint numVertexes, vec2d_t min, v
}
}

struct HEdgeCollectorParms
{
GameMap *map;
BspBuilder *builder;
};

static int hedgeCollector(BspTreeNode &tree, void *parameters)
{
if(tree.isLeaf())
{
HEdgeCollectorParms* p = static_cast<HEdgeCollectorParms*>(parameters);
BspLeaf *leaf = tree.userData()->castTo<BspLeaf>();
HEdge *base = leaf->firstHEdge();
HEdge *hedge = base;
do
{
// Take ownership of this HEdge.
p->builder->take(hedge);

// Add this HEdge to the LUT.
hedge->_origIndex = p->map->hedges.count();
p->map->hedges.append(hedge);

if(hedge->hasLine())
{
Vertex const &vtx = hedge->line().vertex(hedge->lineSideId());

hedge->_sector = hedge->line().sectorPtr(hedge->lineSideId());
hedge->_lineOffset = V2d_Distance(hedge->v1Origin(), vtx.origin());
}

hedge->_angle = bamsAtan2(int( hedge->v2Origin()[VY] - hedge->v1Origin()[VY] ),
int( hedge->v2Origin()[VX] - hedge->v1Origin()[VX] )) << FRACBITS;

// Calculate the length of the segment.
hedge->_length = V2d_Distance(hedge->v2Origin(), hedge->v1Origin());

if(hedge->_length == 0)
hedge->_length = 0.01f; // Hmm...

} while((hedge = &hedge->next()) != base);
}
return false; // Continue traversal.
}

static void collateHEdges(BspBuilder &builder, GameMap &map)
{
DENG2_ASSERT(map.hedges.isEmpty());

if(!builder.numHEdges()) return; // Should never happen.
#ifdef DENG2_QT_4_7_OR_NEWER
map.hedges.reserve(builder.numHEdges());
#endif

HEdgeCollectorParms parms;
parms.builder = &builder;
parms.map = &map;
builder.root()->traverseInOrder(hedgeCollector, &parms);
}

static void collateVertexes(BspBuilder &builder, GameMap &map,
uint *numEditableVertexes, Vertex const ***editableVertexes)
uint numEditableVertexes, Vertex const **editableVertexes)
{
uint bspVertexCount = builder.numVertexes();

DENG2_ASSERT(map.vertexes.isEmpty());
#ifdef DENG2_QT_4_7_OR_NEWER
map.vertexes.reserve(*numEditableVertexes + bspVertexCount);
map.vertexes.reserve(numEditableVertexes + bspVertexCount);
#endif

uint n = 0;
for(; n < *numEditableVertexes; ++n)
for(; n < numEditableVertexes; ++n)
{
Vertex *vtx = const_cast<Vertex *>((*editableVertexes)[n]);
Vertex *vtx = const_cast<Vertex *>(editableVertexes[n]);
map.vertexes.append(vtx);
}

Expand All @@ -1392,6 +1332,39 @@ struct CollateBspElementsParms
GameMap *map;
};

static void collateBspLeafHEdges(BspLeaf &leaf, CollateBspElementsParms const &parms)
{
HEdge *base = leaf.firstHEdge();
HEdge *hedge = base;
do
{
// Take ownership of this HEdge.
parms.builder->take(hedge);

// Add this HEdge to the LUT.
hedge->_origIndex = parms.map->hedges.count();
parms.map->hedges.append(hedge);

if(hedge->hasLine())
{
Vertex const &vtx = hedge->line().vertex(hedge->lineSideId());

hedge->_sector = hedge->line().sectorPtr(hedge->lineSideId());
hedge->_lineOffset = V2d_Distance(hedge->v1Origin(), vtx.origin());
}

hedge->_angle = bamsAtan2(int( hedge->v2Origin()[VY] - hedge->v1Origin()[VY] ),
int( hedge->v2Origin()[VX] - hedge->v1Origin()[VX] )) << FRACBITS;

// Calculate the length of the segment.
hedge->_length = V2d_Distance(hedge->v2Origin(), hedge->v1Origin());

if(hedge->_length == 0)
hedge->_length = 0.01f; // Hmm...

} while((hedge = &hedge->next()) != base);
}

static void collateBspElements(BspTreeNode &tree, CollateBspElementsParms const &parms)
{
// We are only interested in BspNodes at this level.
Expand All @@ -1406,34 +1379,32 @@ static void collateBspElements(BspTreeNode &tree, CollateBspElementsParms const
node->_index = parms.map->bspNodes.count();
parms.map->bspNodes.append(node);

if(BspTreeNode *right = tree.right())
if(tree.hasRightLeaf())
{
if(right->isLeaf())
{
// Take ownership of this BspLeaf.
DENG2_ASSERT(right->userData());
BspLeaf *leaf = right->userData()->castTo<BspLeaf>();
parms.builder->take(leaf);

// Add this BspLeaf to the LUT.
leaf->_index = parms.map->bspLeafs.count();
parms.map->bspLeafs.append(leaf);
}
// Take ownership of the built BspLeaf.
DENG2_ASSERT(tree.right().userData() != 0);
BspLeaf *leaf = tree.right().userData()->castTo<BspLeaf>();
parms.builder->take(leaf);

// Add this BspLeaf to the LUT.
leaf->_index = parms.map->bspLeafs.count();
parms.map->bspLeafs.append(leaf);

collateBspLeafHEdges(*leaf, parms);
}

if(BspTreeNode *left = tree.left())
if(tree.hasLeftLeaf())
{
if(left->isLeaf())
{
// Take ownership of this BspLeaf.
DENG2_ASSERT(left->userData());
BspLeaf *leaf = left->userData()->castTo<BspLeaf>();
parms.builder->take(leaf);

// Add this BspLeaf to the LUT.
leaf->_index = parms.map->bspLeafs.count();
parms.map->bspLeafs.append(leaf);
}
// Take ownership of the built BspLeaf.
DENG2_ASSERT(tree.left().userData() != 0);
BspLeaf *leaf = tree.left().userData()->castTo<BspLeaf>();
parms.builder->take(leaf);

// Add this BspLeaf to the LUT.
leaf->_index = parms.map->bspLeafs.count();
parms.map->bspLeafs.append(leaf);

collateBspLeafHEdges(*leaf, parms);
}
}

Expand All @@ -1445,17 +1416,23 @@ static int collateBspElementsWorker(BspTreeNode &tree, void *parameters)

static void collateBSP(BspBuilder &builder, GameMap &map)
{
DENG2_ASSERT(map.hedges.isEmpty());
DENG2_ASSERT(map.bspLeafs.isEmpty());
DENG2_ASSERT(map.bspNodes.isEmpty());

#ifdef DENG2_QT_4_7_OR_NEWER
map.hedges.reserve(builder.numHEdges());
map.bspNodes.reserve(builder.numNodes());
map.bspLeafs.reserve(builder.numLeafs());
#endif

BspTreeNode *rootNode = builder.root();
map.bsp = rootNode->userData();

CollateBspElementsParms parms;
parms.builder = &builder;
parms.map = &map;

if(rootNode->isLeaf())
{
// Take ownership of this leaf.
Expand All @@ -1467,39 +1444,14 @@ static void collateBSP(BspBuilder &builder, GameMap &map)
leaf->_index = 0;
map.bspLeafs.append(leaf);

collateBspLeafHEdges(*leaf, parms);

return;
}

CollateBspElementsParms parms;
parms.builder = &builder;
parms.map = &map;
rootNode->traversePostOrder(collateBspElementsWorker, &parms);
}

static void saveBsp(BspBuilder &builder, GameMap &map, uint numEditableVertexes,
Vertex const **editableVertexes)
{
dint32 rHeight, lHeight;
BspTreeNode *rootNode = builder.root();
if(!rootNode->isLeaf())
{
rHeight = dint32(rootNode->right()->height());
lHeight = dint32(rootNode->left()->height());
}
else
{
rHeight = lHeight = 0;
}

LOG_INFO("BSP built: (%d:%d) %d Nodes, %d Leafs, %d HEdges, %d Vertexes.")
<< rHeight << lHeight << builder.numNodes() << builder.numLeafs()
<< builder.numHEdges() << builder.numVertexes();

collateHEdges(builder, map);
collateVertexes(builder, map, &numEditableVertexes, &editableVertexes);
collateBSP(builder, map);
}

static bool buildBsp(GameMap &gamemap)
{
DENG2_ASSERT(e_map);
Expand All @@ -1513,11 +1465,33 @@ static bool buildBsp(GameMap &gamemap)
BspBuilder nodeBuilder(gamemap, e_map->vertexCount(), e_map->verticesAsArray(), bspFactor);

// Build the BSP.
bool builtOK = nodeBuilder.build();
bool builtOK = nodeBuilder.buildBsp();
if(builtOK)
{
Vertex const **e_mapVertexesArray = e_map->verticesAsArray();
uint const e_mapNumVertexes = e_map->vertexCount();

BspTreeNode &treeRoot = *nodeBuilder.root();

// Determine the depth of the two main branches.
dint32 rHeight, lHeight;
if(!treeRoot.isLeaf())
{
rHeight = dint32( treeRoot.right().height() );
lHeight = dint32( treeRoot.left().height() );
}
else
{
rHeight = lHeight = 0;
}

LOG_INFO("BSP built: (%d:%d) %d Nodes, %d Leafs, %d HEdges, %d Vertexes.")
<< rHeight << lHeight << nodeBuilder.numNodes() << nodeBuilder.numLeafs()
<< nodeBuilder.numHEdges() << nodeBuilder.numVertexes();

// Take ownership of the built map data elements.
saveBsp(nodeBuilder, gamemap, e_map->vertexCount(), e_map->verticesAsArray());
collateVertexes(nodeBuilder, gamemap, e_mapNumVertexes, e_mapVertexesArray);
collateBSP(nodeBuilder, gamemap);
}

// How much time did we spend?
Expand Down
55 changes: 30 additions & 25 deletions doomsday/client/src/map/bspbuilder.cpp
@@ -1,5 +1,4 @@
/** @file bspbuilder.cpp BspBuilder interface class.
* @ingroup map
/** @file bspbuilder.cpp BSP Builder.
*
* @authors Copyright © 2013 Daniel Swanson <danij@dengine.net>
*
Expand All @@ -25,70 +24,76 @@
#include "map/bsp/partitioner.h"

using namespace de;
using namespace bsp;

BspBuilder::BspBuilder(GameMap& map, uint numEditableVertexes, const Vertex **editableVertexes, int splitCostFactor)
DENG2_PIMPL_NOREF(BspBuilder)
{
partitioner = new bsp::Partitioner(map, numEditableVertexes, editableVertexes, splitCostFactor);
}
/// The space partitioner.
Partitioner partitioner;

Instance(GameMap &map, uint numEditableVertexes, Vertex const **editableVertexes)
: partitioner(map, numEditableVertexes, editableVertexes)
{}
};

BspBuilder::~BspBuilder()
BspBuilder::BspBuilder(GameMap &map, uint numEditableVertexes, Vertex const **editableVertexes,
int splitCostFactor)
: d(new Instance(map, numEditableVertexes, editableVertexes))
{
delete partitioner;
d->partitioner.setSplitCostFactor(splitCostFactor);
}

BspBuilder& BspBuilder::setSplitCostFactor(int factor)
void BspBuilder::setSplitCostFactor(int newFactor)
{
partitioner->setSplitCostFactor(factor);
return *this;
d->partitioner.setSplitCostFactor(newFactor);
}

bool BspBuilder::build()
bool BspBuilder::buildBsp()
{
try
{
return partitioner->build();
return d->partitioner.build();
}
catch(de::Error const& er)
catch(Error const &er)
{
LOG_AS("BspBuilder");
LOG_WARNING("%s.") << er.asText();
}
return false;
}

BspTreeNode* BspBuilder::root() const
BspTreeNode *BspBuilder::root() const
{
return partitioner->root();
return d->partitioner.root();
}

uint BspBuilder::numNodes()
{
return partitioner->numNodes();
return d->partitioner.numNodes();
}

uint BspBuilder::numLeafs()
{
return partitioner->numLeafs();
return d->partitioner.numLeafs();
}

uint BspBuilder::numHEdges()
{
return partitioner->numHEdges();
return d->partitioner.numHEdges();
}

uint BspBuilder::numVertexes()
{
return partitioner->numVertexes();
return d->partitioner.numVertexes();
}

Vertex& BspBuilder::vertex(uint idx)
Vertex &BspBuilder::vertex(uint idx)
{
DENG2_ASSERT(partitioner->vertex(idx).type() == DMU_VERTEX);
return partitioner->vertex(idx);
DENG2_ASSERT(d->partitioner.vertex(idx).type() == DMU_VERTEX);
return d->partitioner.vertex(idx);
}

BspBuilder& BspBuilder::take(de::MapElement* ob)
void BspBuilder::take(MapElement *mapElement)
{
partitioner->release(ob);
return *this;
d->partitioner.release(mapElement);
}

0 comments on commit e139c9f

Please sign in to comment.