Navigation Menu

Skip to content

Commit

Permalink
World|Map|Client: de::Map has ownership of the contact blockmaps
Browse files Browse the repository at this point in the history
Todo: Cleanup.
  • Loading branch information
danij-deng committed Oct 7, 2013
1 parent 33c7490 commit 9f892e6
Show file tree
Hide file tree
Showing 9 changed files with 515 additions and 628 deletions.
4 changes: 2 additions & 2 deletions doomsday/client/include/world/blockmap.h
Expand Up @@ -35,8 +35,8 @@ namespace de {
class Blockmap
{
public:
typedef Gridmap::Cell Cell;
typedef Gridmap::CellBlock CellBlock;
typedef GridmapCell Cell;
typedef GridmapCellBlock CellBlock;

public:
/**
Expand Down
116 changes: 71 additions & 45 deletions doomsday/client/include/world/contactblockmap.h
Expand Up @@ -22,74 +22,103 @@
#define DENG_CLIENT_WORLD_CONTACTBLOCKMAP_H

#include <de/aabox.h>

#include <de/Vector>

#include "world/map.h"

class BspLeaf;
struct Contact;
class Lumobj;

class ContactBlockmap
enum ContactType
{
ContactMobj = 0,
ContactLumobj,

ContactTypeCount
};

/// @todo Obviously, polymorphism is a better solution.
struct Contact
{
public:
Contact *nextUsed; ///< Next in the used list (if any, not owned).
Contact *next; ///< Next in global list of contacts (if any, not owned).

ContactType _type; ///< Logical identifier.
void *_object; ///< The contacted object.

ContactType type() const;

void *objectPtr() const;

template <class ObjectType>
ObjectType &objectAs() const {
DENG2_ASSERT(_object != 0);
return *static_cast<ObjectType *>(_object);
}

/**
* Construct a new contact blockmap.
*
* @param bounds Bounding box of the blockmap.
* @param blockSize Size of each block.
* Returns a copy of the linked object's origin in map space.
*/
ContactBlockmap(AABoxd const &bounds, uint blockSize = 128);
de::Vector3d objectOrigin() const;

/**
* Returns the origin of the blockmap in the map coordinate space.
* Returns the linked object's radius in map space.
*/
de::Vector2d origin() const;
double objectRadius() const;

/**
* Returns the bounds of the blockmap in the map coordinate space.
* Returns an axis-aligned bounding box for the linked object in map space.
*/
AABoxd const &bounds() const;
AABoxd objectAABox() const;

/**
* @param contact Contact to be linked. Note that if the object's origin
* lies outside the blockmap it will not be linked!
* Returns the BSP leaf at the linked object's origin in map space.
*/
BspLeaf &objectBspLeafAtOrigin() const;
};

struct ListNode;

struct ContactList
{
// Start reusing list nodes.
static void reset();

void link(Contact *contact);

/**
* Clear all linked contacts.
*/
void unlinkAll();
ListNode *begin() const;

private:
/**
* Spread contacts in the blockmap to any touched neighbors.
*
* @param box Map space region in which to perform spreading.
* Create a new list node. If there are none available in the list of
* used objects a new one will be allocated and linked to the global list.
*/
void spreadAllContacts(AABoxd const &box);
static ListNode *newNode(void *object);

private:
DENG2_PRIVATE(d)
ListNode *_head;
};

/**
* To be called during game change/on shutdown to destroy all contact blockmaps.
* This is necessary because the blockmaps are allocated from the Zone using a
* To be called during game change/on shutdown to destroy all contact lists.
* This is necessary because the lists are allocated from the Zone using a
* >= PU_MAP purge level and access to them is handled with global pointers.
*
* @todo Encapsulate allocation of and access to the blockmaps in de::Map
* @todo Encapsulate allocation of and access to the lists in de::Map
*/
void R_DestroyContactBlockmaps();
void R_DestroyContactLists();

/**
* Initialize contact blockmaps for the current map.
* Initialize contact lists for the current map.
*/
void R_InitContactBlockmaps(de::Map &map);
void R_InitContactLists(de::Map &map);

/**
* To be called at the beginning of a render frame to clear all contacts ready
* for the new frame.
* To be called at the beginning of a render frame to clear all contact lists
* ready for the new frame.
*/
void R_ClearContacts(de::Map &map);
void R_ClearContactLists(de::Map &map);

/**
* Add a new contact for the specified mobj, for spreading purposes.
Expand All @@ -102,30 +131,27 @@ void R_AddContact(struct mobj_s &mobj);
void R_AddContact(Lumobj &lumobj);

/**
* To be called to link all contacts into the contact blockmaps.
*
* @todo Why don't we link contacts immediately? -ds
* Traverse the list of contacts for the current render frame.
*/
void R_LinkContacts();
int R_ContactIterator(int (*callback) (Contact &, void *), void *context = 0);

/**
* Perform all contact spreading for the specified @a BspLeaf. Note this should
* only be called once per BSP leaf per render frame!
* Returns the contact list for the specified BSP @a leaf and contact @a type.
*/
void R_SpreadContacts(BspLeaf &bspLeaf);
ContactList &R_ContactList(BspLeaf &leaf, ContactType type);

/**
* Traverse the list of mobj contacts linked directly to @a bspLeaf, for the
* current render frame.
* Traverse the list of mobj contacts linked directly to the specified BSP @a leaf,
* for the current render frame.
*/
int R_IterateBspLeafMobjContacts(BspLeaf &bspLeaf,
int R_IterateBspLeafMobjContacts(BspLeaf &leaf,
int (*callback) (struct mobj_s &, void *), void *context = 0);

/**
* Traverse the list of lumobj contacts linked directly to @a bspLeaf, for the
* current render frame.
* Traverse the list of lumobj contacts linked directly to the specified BSP @a leaf,
* for the current render frame.
*/
int R_IterateBspLeafLumobjContacts(BspLeaf &bspLeaf,
int R_IterateBspLeafLumobjContacts(BspLeaf &leaf,
int (*callback) (Lumobj &, void *), void *context = 0);

#endif // DENG_CLIENT_WORLD_CONTACTBLOCKMAP_H
Expand Down
10 changes: 10 additions & 0 deletions doomsday/client/include/world/map.h
Expand Up @@ -805,6 +805,11 @@ class Map
*/
void initLightGrid();

/**
* Perform spreading of all contacts in the specified map space @a region.
*/
void spreadAllContacts(AABoxd const &region);

protected:
/// Observes World FrameBegin
void worldFrameBegins(World &world, bool resetNextViewer);
Expand Down Expand Up @@ -845,6 +850,11 @@ class Map
* Must be called before rendering a frame with bias lighting enabled.
*/
void initBias();

/**
* Initialize the map object => BSP leaf "contact" blockmaps.
*/
void initContactBlockmaps();
#endif // __CLIENT__

public:
Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/dd_main.cpp
Expand Up @@ -1500,7 +1500,7 @@ bool App_ChangeGame(Game &game, bool allowReload)

#ifdef __CLIENT__
R_ClearViewData();
R_DestroyContactBlockmaps();
R_DestroyContactLists();
P_ControlShutdown();

Con_Execute(CMDS_DDAY, "clearbindings", true, false);
Expand Down
5 changes: 4 additions & 1 deletion doomsday/client/src/render/rend_main.cpp
Expand Up @@ -2499,7 +2499,10 @@ static void drawCurrentLeaf()
leaf->markVisible();

markLeafFrontFacingWalls();
R_SpreadContacts(*leaf);

// Perform contact spreading for this map region.
leaf->map().spreadAllContacts(leaf->poly().aaBox());

Rend_RadioBspLeafEdges(*leaf);

/*
Expand Down
8 changes: 4 additions & 4 deletions doomsday/client/src/world/blockmap.cpp
Expand Up @@ -273,10 +273,10 @@ struct BlockLinkWorkerParams
bool didLink;
};

static int blockLinkWorker(void *cdPtr, void *parameters)
static int blockLinkWorker(void *cdPtr, void *context)
{
CellData *cellData = (CellData *) cdPtr;
BlockLinkWorkerParams *p = (BlockLinkWorkerParams *) parameters;
BlockLinkWorkerParams *p = (BlockLinkWorkerParams *) context;
if(cellData->link(p->elem))
{
p->didLink = true;
Expand Down Expand Up @@ -310,10 +310,10 @@ struct BlockUnlinkWorkerParams
bool didUnlink;
};

static int blockUnlinkWorker(void *cdPtr, void *contaxt)
static int blockUnlinkWorker(void *cdPtr, void *context)
{
CellData *cellData = (CellData *) cdPtr;
BlockUnlinkWorkerParams *p = (BlockUnlinkWorkerParams *) contaxt;
BlockUnlinkWorkerParams *p = (BlockUnlinkWorkerParams *) context;
if(cellData->unlink(p->elem))
{
p->didUnlink = true;
Expand Down

0 comments on commit 9f892e6

Please sign in to comment.