Skip to content

Commit

Permalink
BSP Builder|Cleanup: Hide SuperBlock's private instance data
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Mar 29, 2012
1 parent 28b6967 commit 285462c
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 74 deletions.
45 changes: 16 additions & 29 deletions doomsday/engine/portable/include/bspbuilder/superblockmap.hh
Expand Up @@ -31,8 +31,6 @@
#define LIBDENG_BSPBUILDER_SUPERBLOCKMAP

#include "dd_types.h"

#include "kdtree.h" /// @todo Remove me.
#include "bspbuilder/hedges.hh"

#include <list>
Expand All @@ -50,6 +48,13 @@ namespace de {

class SuperBlockmap;

/**
* Subblocks:
* RIGHT - has the lower coordinates.
* LEFT - has the higher coordinates.
* Division of a block always occurs horizontally:
* e.g. 512x512 -> 256x512 -> 256x256.
*/
class SuperBlock {
friend class SuperBlockmap;

Expand All @@ -68,19 +73,17 @@ public:
}

private:
SuperBlock(SuperBlockmap& blockmap) :
_bmap(blockmap), _hedges(0), _realNum(0), _miniNum(0)
{}

~SuperBlock() { clear(); }
SuperBlock(SuperBlockmap& blockmap);
SuperBlock(SuperBlock& parent, ChildId childId, bool splitVertical);
~SuperBlock();

public:
/**
* Retrieve the SuperBlockmap which owns this block.
*
* @return The owning SuperBlockmap instance.
*/
SuperBlockmap& blockmap() const { return _bmap; }
SuperBlockmap& blockmap() const;

/**
* Retrieve the axis-aligned bounding box defined for this superblock
Expand Down Expand Up @@ -133,8 +136,9 @@ public:
*/
int traverse(int (C_DECL *callback)(SuperBlock*, void*), void* parameters=NULL);

inline HEdges::const_iterator hedgesBegin() const { return _hedges.begin(); }
inline HEdges::const_iterator hedgesEnd() const { return _hedges.end(); }
/// Half-edges completely contained by this block.
HEdges::const_iterator hedgesBegin() const;
HEdges::const_iterator hedgesEnd() const;

void findHEdgeBounds(AABoxf& bounds);

Expand Down Expand Up @@ -170,26 +174,9 @@ public:
*/
bsp_hedge_t* hedgePop();

protected:
/// KdTree node in the owning SuperBlockmap.
KdTreeNode* _tree;

private:
void clear();

void inline incrementHEdgeCount(bsp_hedge_t* hedge);
void inline linkHEdge(bsp_hedge_t* hedge);

/// SuperBlockmap that owns this SuperBlock.
SuperBlockmap& _bmap;

/// Half-edges completely contained by this block.
HEdges _hedges;

/// Number of real half-edges and minihedges contained by this block
/// (including all sub-blocks below it).
int _realNum;
int _miniNum;
struct Instance;
Instance* d;
};

class SuperBlockmap {
Expand Down
142 changes: 97 additions & 45 deletions doomsday/engine/portable/src/bspbuilder/superblockmap.cpp
Expand Up @@ -27,65 +27,121 @@
#include "de_console.h"
#include "p_mapdata.h"

#include "kdtree.h"
#include "bspbuilder/hedges.hh"
#include "bspbuilder/superblockmap.hh"

using namespace de;

void SuperBlock::clear()
struct SuperBlock::Instance
{
_hedges.clear();
KdTreeNode_SetUserData(_tree, NULL);
/// SuperBlockmap that owns this SuperBlock.
SuperBlockmap& bmap;

/// KdTree node in the owning SuperBlockmap.
KdTreeNode* tree;

/// Half-edges completely contained by this block.
SuperBlock::HEdges hedges;

/// Number of real half-edges and minihedges contained by this block
/// (including all sub-blocks below it).
int realNum;
int miniNum;

Instance(SuperBlockmap& blockmap) :
bmap(blockmap), tree(0), hedges(0), realNum(0), miniNum(0)
{}

~Instance()
{
KdTreeNode_SetUserData(tree, NULL);
}

void inline linkHEdge(bsp_hedge_t* hedge)
{
if(!hedge) return;
hedges.push_front(hedge);
}

void incrementHEdgeCount(bsp_hedge_t* hedge)
{
if(!hedge) return;
if(hedge->info.lineDef) realNum++;
else miniNum++;
}

void decrementHEdgeCount(bsp_hedge_t* hedge)
{
if(!hedge) return;
if(hedge->info.lineDef) realNum--;
else miniNum--;
}
};

SuperBlock::SuperBlock(SuperBlockmap& blockmap)
{
d = new Instance(blockmap);
}

SuperBlock::SuperBlock(SuperBlock& parent, ChildId childId, bool splitVertical)
{
d = new Instance(parent.blockmap());
d->tree = KdTreeNode_AddChild(parent.d->tree, 0.5, int(splitVertical), childId==LEFT, this);
}

SuperBlock::~SuperBlock()
{
delete d;
}

SuperBlockmap& SuperBlock::blockmap() const
{
return d->bmap;
}

const AABox& SuperBlock::bounds() const
{
return *KdTreeNode_Bounds(_tree);
return *KdTreeNode_Bounds(d->tree);
}

bool SuperBlock::hasChild(ChildId childId) const
{
assertValidChildId(childId);
return NULL != KdTreeNode_Child(_tree, childId==LEFT);
return NULL != KdTreeNode_Child(d->tree, childId==LEFT);
}

SuperBlock& SuperBlock::child(ChildId childId)
{
assertValidChildId(childId);
KdTreeNode* subtree = KdTreeNode_Child(_tree, childId==LEFT);
KdTreeNode* subtree = KdTreeNode_Child(d->tree, childId==LEFT);
if(!subtree) Con_Error("SuperBlock::child: Has no %s subblock.", childId==LEFT? "left" : "right");
return *static_cast<SuperBlock*>(KdTreeNode_UserData(subtree));
}

SuperBlock* SuperBlock::addChild(ChildId childId, bool splitVertical)
{
assertValidChildId(childId);
SuperBlock* child = new SuperBlock(_bmap);
child->_tree = KdTreeNode_AddChild(_tree, 0.5, int(splitVertical), childId==LEFT, child);
SuperBlock* child = new SuperBlock(*this, childId, splitVertical);
return child;
}

uint SuperBlock::hedgeCount(bool addReal, bool addMini) const
SuperBlock::HEdges::const_iterator SuperBlock::hedgesBegin() const
{
uint total = 0;
if(addReal) total += _realNum;
if(addMini) total += _miniNum;
return total;
return d->hedges.begin();
}

void SuperBlock::incrementHEdgeCount(bsp_hedge_t* hedge)
SuperBlock::HEdges::const_iterator SuperBlock::hedgesEnd() const
{
if(!hedge) return;
if(hedge->info.lineDef) _realNum++;
else _miniNum++;
return d->hedges.end();
}

void SuperBlock::linkHEdge(bsp_hedge_t* hedge)
uint SuperBlock::hedgeCount(bool addReal, bool addMini) const
{
if(!hedge) return;
_hedges.push_front(hedge);
// Associate ourself.
hedge->block = this;
uint total = 0;
if(addReal) total += d->realNum;
if(addMini) total += d->miniNum;
return total;
}

static void initAABoxFromHEdgeVertexes(AABoxf* aaBox, const bsp_hedge_t* hedge)
Expand All @@ -105,7 +161,7 @@ void SuperBlock::findHEdgeBounds(AABoxf& bounds)
bool initialized = false;
AABoxf hedgeAABox;

for(HEdges::iterator it = _hedges.begin(); it != _hedges.end(); ++it)
for(HEdges::iterator it = d->hedges.begin(); it != d->hedges.end(); ++it)
{
bsp_hedge_t* hedge = *it;
initAABoxFromHEdgeVertexes(&hedgeAABox, hedge);
Expand All @@ -130,12 +186,14 @@ SuperBlock* SuperBlock::hedgePush(bsp_hedge_t* hedge)
for(;;)
{
// Update half-edge counts.
sb->incrementHEdgeCount(hedge);
sb->d->incrementHEdgeCount(hedge);

if(sb->blockmap().isLeaf(*sb))
{
// No further subdivision possible.
sb->linkHEdge(hedge);
sb->d->linkHEdge(hedge);
// Associate ourself.
hedge->block = sb;
break;
}

Expand All @@ -162,7 +220,9 @@ SuperBlock* SuperBlock::hedgePush(bsp_hedge_t* hedge)
if(p1 != p2)
{
// Line crosses midpoint; link it in and return.
sb->linkHEdge(hedge);
sb->d->linkHEdge(hedge);
// Associate ourself.
hedge->block = sb;
break;
}

Expand All @@ -181,14 +241,13 @@ SuperBlock* SuperBlock::hedgePush(bsp_hedge_t* hedge)

bsp_hedge_t* SuperBlock::hedgePop()
{
if(_hedges.empty()) return NULL;
if(d->hedges.empty()) return NULL;

bsp_hedge_t* hedge = _hedges.front();
_hedges.pop_front();
bsp_hedge_t* hedge = d->hedges.front();
d->hedges.pop_front();

// Update half-edge counts.
if(hedge->info.lineDef) _realNum--;
else _miniNum--;
d->decrementHEdgeCount(hedge);

// Disassociate ourself.
hedge->block = NULL;
Expand All @@ -202,12 +261,12 @@ int SuperBlock::traverse(int (C_DECL *callback)(SuperBlock*, void*), void* param
int result = callback(this, parameters);
if(result) return result;

if(_tree)
if(d->tree)
{
// Recursively handle subtrees.
for(uint num = 0; num < 2; ++num)
{
KdTreeNode* node = KdTreeNode_Child(_tree, num);
KdTreeNode* node = KdTreeNode_Child(d->tree, num);
if(!node) continue;

SuperBlock* child = static_cast<SuperBlock*>(KdTreeNode_UserData(node));
Expand All @@ -223,22 +282,15 @@ int SuperBlock::traverse(int (C_DECL *callback)(SuperBlock*, void*), void* param

struct SuperBlockmap::Instance
{
/**
* The KdTree of SuperBlocks.
*
* Subblocks:
* RIGHT - has the lower coordinates.
* LEFT - has the higher coordinates.
* Division of a block always occurs horizontally:
* e.g. 512x512 -> 256x512 -> 256x256.
*/
/// The KdTree of SuperBlocks.
KdTree* kdTree;

Instance(SuperBlockmap& bmap, const AABox& bounds)
{
kdTree = KdTree_New(&bounds);
// Attach the root node.
SuperBlock* block = new SuperBlock(bmap);
block->_tree = KdTreeNode_SetUserData(KdTree_Root(kdTree), block);
block->d->tree = KdTreeNode_SetUserData(KdTree_Root(kdTree), block);
}

~Instance()
Expand All @@ -248,13 +300,13 @@ struct SuperBlockmap::Instance

void clearBlockWorker(SuperBlock& block)
{
if(block._tree)
if(block.d->tree)
{
// Recursively handle sub-blocks.
KdTreeNode* child;
for(uint num = 0; num < 2; ++num)
{
child = KdTreeNode_Child(block._tree, num);
child = KdTreeNode_Child(block.d->tree, num);
if(!child) continue;

SuperBlock* blockPtr = static_cast<SuperBlock*>(KdTreeNode_UserData(child));
Expand Down

0 comments on commit 285462c

Please sign in to comment.