Skip to content

Commit

Permalink
World|ContactBlockmap|Client: Use a regular Blockmap for Contact spre…
Browse files Browse the repository at this point in the history
…ading
  • Loading branch information
danij-deng committed Oct 7, 2013
1 parent 0e49568 commit 33c7490
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 71 deletions.
6 changes: 4 additions & 2 deletions doomsday/client/include/world/blockmap.h
Expand Up @@ -122,9 +122,11 @@ class Blockmap

bool unlink(CellBlock const &cellBlock, void *elem);

int iterate(Cell const &cell, int (*callback) (void *elem, void *context), void *context) const;
void unlinkAll();

int iterate(CellBlock const &cellBlock, int (*callback) (void *elem, void *context), void *context) const;
int iterate(Cell const &cell, int (*callback) (void *elem, void *context), void *context = 0) const;

int iterate(CellBlock const &cellBlock, int (*callback) (void *elem, void *context), void *context = 0) const;

/**
* Retrieve an immutable pointer to the underlying Gridmap instance
Expand Down
97 changes: 66 additions & 31 deletions doomsday/client/src/world/blockmap.cpp
Expand Up @@ -41,29 +41,32 @@ struct RingNode
struct CellData
{
RingNode *ringNodes;

/// Running total of the number of elements linked in this cell.
int elemCount;

bool link(void *elem)
{
RingNode *node = allocNode();
node->elem = elem;
elemCount++;
return true;
}
int elemCount; ///< Total number of linked elements.

bool unlink(void *elem)
{
if(RingNode *node = findNode(elem))
{
node->elem = 0;
elemCount--;
clearElement(*node);
return true;
}
return false;
}

void unlinkAll()
{
for(RingNode *node = ringNodes; node; node = node->next)
{
clearElement(*node);
}
}

bool link(void *elem)
{
addElement(newNode(), elem);
return true;
}

int iterate(int (*callback) (void *elem, void *context), void *context)
{
RingNode *node = ringNodes;
Expand All @@ -73,8 +76,8 @@ struct CellData

if(node->elem)
{
int result = callback(node->elem, context);
if(result) return result; // Stop iteration.
if(int result = callback(node->elem, context))
return result; // Stop iteration.
}

node = next;
Expand All @@ -83,17 +86,7 @@ struct CellData
}

private:
RingNode *findNode(void *elem)
{
if(!elem) return 0;
for(RingNode *found = ringNodes; found; found = found->next)
{
if(found->elem == elem) return found;
}
return 0;
}

RingNode *allocNode()
RingNode &newNode()
{
RingNode *node = 0;

Expand All @@ -103,8 +96,9 @@ struct CellData
node = (RingNode *) Z_Malloc(sizeof(*node), PU_MAP, 0);
node->next = 0;
node->prev = 0;
node->elem = 0;
ringNodes = node;
return node;
return *node;
}

// Is there an available node in the ring we can reuse?
Expand All @@ -114,14 +108,40 @@ struct CellData
if(!node->elem)
{
// This will do nicely.
return node;
return *node;
}

// Add a new node to the ring.
node->next = (RingNode *) Z_Malloc(sizeof(*node), PU_MAP, 0);
node->next->next = 0;
node->next->prev = node;
return node->next;
node->next->elem = 0;
return *node->next;
}

RingNode *findNode(void *elem)
{
if(!elem) return 0;
for(RingNode *found = ringNodes; found; found = found->next)
{
if(found->elem == elem) return found;
}
return 0;
}

void clearElement(RingNode &node)
{
if(!node.elem) return;

node.elem = 0;
elemCount--;
}

void addElement(RingNode &node, void *elem)
{
DENG2_ASSERT(node.elem == 0);
node.elem = elem;
elemCount++;
}
};

Expand Down Expand Up @@ -290,10 +310,10 @@ struct BlockUnlinkWorkerParams
bool didUnlink;
};

static int blockUnlinkWorker(void *cdPtr, void *parameters)
static int blockUnlinkWorker(void *cdPtr, void *contaxt)
{
CellData *cellData = (CellData *) cdPtr;
BlockUnlinkWorkerParams *p = (BlockUnlinkWorkerParams *) parameters;
BlockUnlinkWorkerParams *p = (BlockUnlinkWorkerParams *) contaxt;
if(cellData->unlink(p->elem))
{
p->didUnlink = true;
Expand All @@ -311,6 +331,21 @@ bool Blockmap::unlink(CellBlock const &cellBlock, void *elem)
return parm.didUnlink;
}

static int blockUnlinkAllWorker(void *cdPtr, void *context)
{
DENG2_UNUSED(context);
if(CellData *cellData = static_cast<CellData *>(cdPtr))
{
cellData->unlinkAll();
}
return false; // Continue iteration.
}

void Blockmap::unlinkAll()
{
d->iterate(blockUnlinkAllWorker);
}

int Blockmap::cellElementCount(Cell const &cell) const
{
if(CellData *cellData = (CellData *)d->cellData(cell))
Expand Down

0 comments on commit 33c7490

Please sign in to comment.