diff --git a/doomsday/engine/portable/include/gamemap.h b/doomsday/engine/portable/include/gamemap.h index d4ff849efe..4da95ad1e1 100644 --- a/doomsday/engine/portable/include/gamemap.h +++ b/doomsday/engine/portable/include/gamemap.h @@ -371,6 +371,9 @@ int GameMap_IterateCellMobjs(GameMap* map, const uint coords[2], int GameMap_IterateCellBlockMobjs(GameMap* map, const GridmapBlock* blockCoords, int (*callback) (struct mobj_s*, void*), void* paramaters); +int GameMap_MobjsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (struct mobj_s*, void*), void* parameters); + /** * Construct an initial (empty) LineDef Blockmap for this map. * @@ -386,6 +389,27 @@ int GameMap_IterateCellLineDefs(GameMap* map, const uint coords[2], int GameMap_IterateCellBlockLineDefs(GameMap* map, const GridmapBlock* blockCoords, int (*callback) (linedef_t*, void*), void* paramaters); +int GameMap_IterateCellPolyobjLineDefs(GameMap* map, const uint coords[2], + int (*callback) (linedef_t*, void*), void* paramaters); +int GameMap_IterateCellBlockPolyobjLineDefs(GameMap* map, const GridmapBlock* blockCoords, + int (*callback) (linedef_t*, void*), void* paramaters); + +int GameMap_LineDefsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (linedef_t*, void*), void* paramaters); + +int GameMap_PolyobjLinesBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (linedef_t*, void*), void* parameters); + +/** + * LineDefs and Polyobj LineDefs (note Polyobj LineDefs are iterated first). + * + * The validCount flags are used to avoid checking lines that are marked + * in multiple mapblocks, so increment validCount before the first call + * to GameMap_IterateCellLineDefs(), then make one or more calls to it. + */ +int GameMap_AllLineDefsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (linedef_t*, void*), void* paramaters); + /** * Construct an initial (empty) Subsector Blockmap for this map. * @@ -403,6 +427,9 @@ int GameMap_IterateCellBlockSubsectors(GameMap* map, const GridmapBlock* blockCo sector_t* sector, const AABoxf* box, int localValidCount, int (*callback) (subsector_t*, void*), void* paramaters); +int GameMap_SubsectorsBoxIterator(GameMap* map, const AABoxf* box, sector_t* sector, + int (*callback) (subsector_t*, void*), void* parameters); + /** * Construct an initial (empty) Polyobj Blockmap for this map. * @@ -419,10 +446,13 @@ int GameMap_IterateCellPolyobjs(GameMap* map, const uint coords[2], int GameMap_IterateCellBlockPolyobjs(GameMap* map, const GridmapBlock* blockCoords, int (*callback) (polyobj_t*, void*), void* paramaters); -int GameMap_IterateCellPolyobjLineDefs(GameMap* map, const uint coords[2], - int (*callback) (linedef_t*, void*), void* paramaters); -int GameMap_IterateCellBlockPolyobjLineDefs(GameMap* map, const GridmapBlock* blockCoords, - int (*callback) (linedef_t*, void*), void* paramaters); +/** + * The validCount flags are used to avoid checking polys that are marked in + * multiple mapblocks, so increment validCount before the first call, then + * make one or more calls to it. + */ +int GameMap_PolyobjsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (struct polyobj_s*, void*), void* parameters); /** * Traces a line between @a from and @a to, making a callback for each diff --git a/doomsday/engine/portable/include/p_maputil.h b/doomsday/engine/portable/include/p_maputil.h index 66c4021a8b..cfc5ca25c6 100644 --- a/doomsday/engine/portable/include/p_maputil.h +++ b/doomsday/engine/portable/include/p_maputil.h @@ -128,41 +128,64 @@ boolean P_IsPointXYInSector(float x, float y, const sector_t* sector); */ boolean P_IsPointXYInSubsector(float x, float y, const subsector_t* subsector); -void P_MobjLink(mobj_t* mo, byte flags); -int P_MobjUnlink(mobj_t* mo); +void P_MobjLink(mobj_t* mo, byte flags); +int P_MobjUnlink(mobj_t* mo); -int PIT_AddLineDefIntercepts(linedef_t* ld, void* paramaters); -int PIT_AddMobjIntercepts(mobj_t* mobj, void* paramaters); +/** + * @important Caller must ensure that the mobj is currently unlinked. + */ +void P_LinkMobjToLineDefs(mobj_t* mo); + +/** + * Unlinks the mobj from all the lines it's been linked to. Can be called + * without checking that the list does indeed contain lines. + */ +boolean P_UnlinkMobjFromLineDefs(mobj_t* mo); + +/** + * @important The mobj must be currently unlinked. + */ +void P_LinkMobjInBlockmap(mobj_t* mo); + +boolean P_UnlinkMobjFromBlockmap(mobj_t* mo); -int P_MobjLinesIterator(mobj_t *mo, - int (*func) (linedef_t *, void *), - void *); -int P_MobjSectorsIterator(mobj_t *mo, - int (*func) (sector_t *, void *), - void *data); -int P_LineMobjsIterator(linedef_t *line, - int (*func) (mobj_t *, void *), - void *data); -int P_SectorTouchingMobjsIterator(sector_t *sector, - int (*func) (mobj_t *, - void *), - void *data); +int PIT_AddLineDefIntercepts(linedef_t* ld, void* parameters); +int PIT_AddMobjIntercepts(mobj_t* mobj, void* parameters); -int P_MobjsBoxIterator(const AABoxf* box, int (*callback) (mobj_t*, void*), void* paramaters); +int P_MobjLinesIterator(mobj_t* mo, int (*func) (linedef_t*, void*), void* parameters); -int P_LinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* paramaters); +int P_MobjSectorsIterator(mobj_t* mo, int (*func) (sector_t*, void*), void* parameters); -int P_PolyobjsBoxIterator(const AABoxf* box, int (*callback) (polyobj_t*, void*), void* paramaters); +int P_LineMobjsIterator(linedef_t* lineDef, int (*func) (mobj_t*, void*), void* parameters); -int P_PolyobjLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* paramaters); +int P_SectorTouchingMobjsIterator(sector_t* sector, int (*func) (mobj_t*, void*), void *parameters); -// LineDefs and Polyobj in LineDefs (note Polyobj LineDefs are iterated first). -int P_AllLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* paramaters); +int P_MobjsBoxIterator(const AABoxf* box, int (*callback) (mobj_t*, void*), void* parameters); + +int P_LinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* parameters); + +/** + * The validCount flags are used to avoid checking polys that are marked in + * multiple mapblocks, so increment validCount before the first call, then + * make one or more calls to it. + */ +int P_PolyobjsBoxIterator(const AABoxf* box, int (*callback) (polyobj_t*, void*), void* parameters); + +int P_PolyobjLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* parameters); + +/** + * LineDefs and Polyobj LineDefs (note Polyobj LineDefs are iterated first). + * + * The validCount flags are used to avoid checking lines that are marked + * in multiple mapblocks, so increment validCount before the first call + * to GameMap_IterateCellLineDefs(), then make one or more calls to it. + */ +int P_AllLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* parameters); -int P_SubsectorsBoxIterator(const AABoxf* box, sector_t *sector, int (*callback) (subsector_t*, void*), void* paramaters); +int P_SubsectorsBoxIterator(const AABoxf* box, sector_t* sector, int (*callback) (subsector_t*, void*), void* parameters); int P_PathTraverse(float const from[2], float const to[2], int flags, traverser_t callback); -int P_PathTraverse2(float const from[2], float const to[2], int flags, traverser_t callback, void* paramaters); +int P_PathTraverse2(float const from[2], float const to[2], int flags, traverser_t callback, void* parameters); /** * Same as P_PathTraverse except 'from' and 'to' arguments are specified diff --git a/doomsday/engine/portable/include/r_data.h b/doomsday/engine/portable/include/r_data.h index 0d5383964f..bd3d30d56f 100644 --- a/doomsday/engine/portable/include/r_data.h +++ b/doomsday/engine/portable/include/r_data.h @@ -276,10 +276,8 @@ typedef struct { extern colorpaletteid_t defaultColorPalette; -extern nodeindex_t* linelinks; -extern nodepile_t* mobjNodes, *lineNodes; - extern int levelFullBright; + extern byte rendInfoRPolys; extern byte precacheMapMaterials, precacheSprites, precacheSkins; diff --git a/doomsday/engine/portable/src/gamemap.c b/doomsday/engine/portable/src/gamemap.c index 17e2589aaa..a43e0dc6eb 100644 --- a/doomsday/engine/portable/src/gamemap.c +++ b/doomsday/engine/portable/src/gamemap.c @@ -547,6 +547,15 @@ int GameMap_IterateCellBlockMobjs(GameMap* map, const GridmapBlock* blockCoords, blockmapCellMobjsIterator, (void*) &args); } +int GameMap_MobjsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (mobj_t*, void*), void* parameters) +{ + GridmapBlock blockCoords; + assert(map); + Blockmap_CellBlockCoords(map->mobjBlockmap, &blockCoords, box); + return GameMap_IterateCellBlockMobjs(map, &blockCoords, callback, parameters); +} + void GameMap_LinkLineDefInBlockmap(GameMap* map, linedef_t* lineDef) { vec2_t origin, cellSize, cell, from, to; @@ -767,6 +776,21 @@ int GameMap_IterateCellBlockSubsectors(GameMap* map, const GridmapBlock* blockCo blockmapCellSubsectorsIterator, (void*) &args); } +int GameMap_SubsectorsBoxIterator(GameMap* map, const AABoxf* box, sector_t* sector, + int (*callback) (subsector_t*, void*), void* parameters) +{ + static int localValidCount = 0; + GridmapBlock blockCoords; + assert(map); + + // This is only used here. + localValidCount++; + + Blockmap_CellBlockCoords(map->subsectorBlockmap, &blockCoords, box); + return GameMap_IterateCellBlockSubsectors(map, &blockCoords, sector, box, + localValidCount, callback, parameters); +} + void GameMap_LinkPolyobjInBlockmap(GameMap* map, polyobj_t* po) { Blockmap* blockmap; @@ -856,6 +880,15 @@ int GameMap_IterateCellBlockPolyobjs(GameMap* map, const GridmapBlock* blockCoor blockmapCellPolyobjsIterator, (void*) &args); } +int GameMap_PolyobjsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (struct polyobj_s*, void*), void* parameters) +{ + GridmapBlock blockCoords; + assert(map); + Blockmap_CellBlockCoords(map->polyobjBlockmap, &blockCoords, box); + return GameMap_IterateCellBlockPolyobjs(map, &blockCoords, callback, parameters); +} + typedef struct poiterparams_s { int (*func) (linedef_t*, void*); void* param; @@ -905,9 +938,46 @@ int GameMap_IterateCellBlockPolyobjLineDefs(GameMap* map, const GridmapBlock* bl blockmapCellPolyobjsIterator, (void*) &args); } +int GameMap_LineDefsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (linedef_t*, void*), void* parameters) +{ + GridmapBlock blockCoords; + assert(map); + Blockmap_CellBlockCoords(map->lineDefBlockmap, &blockCoords, box); + return GameMap_IterateCellBlockLineDefs(map, &blockCoords, callback, parameters); +} + +int GameMap_PolyobjLinesBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (linedef_t*, void*), void* parameters) +{ + GridmapBlock blockCoords; + assert(map); + Blockmap_CellBlockCoords(map->polyobjBlockmap, &blockCoords, box); + return GameMap_IterateCellBlockPolyobjLineDefs(map, &blockCoords, callback, parameters); +} + +/** + * LineDefs and Polyobj LineDefs (note Polyobj LineDefs are iterated first). + * + * The validCount flags are used to avoid checking lines that are marked + * in multiple mapblocks, so increment validCount before the first call + * to GameMap_IterateCellLineDefs(), then make one or more calls to it. + */ +int GameMap_AllLineDefsBoxIterator(GameMap* map, const AABoxf* box, + int (*callback) (linedef_t*, void*), void* parameters) +{ + assert(map); + if(map->numPolyObjs > 0) + { + int result = P_PolyobjLinesBoxIterator(box, callback, parameters); + if(result) return result; + } + return P_LinesBoxIterator(box, callback, parameters); +} + static int traverseCellPath2(Blockmap* bmap, uint const fromBlock[2], uint const toBlock[2], float const from[2], float const to[2], - int (*callback) (uint const block[2], void* paramaters), void* paramaters) + int (*callback) (uint const block[2], void* parameters), void* parameters) { int result = false; // Continue iteration. float intercept[2], delta[2], partial; @@ -969,7 +1039,7 @@ static int traverseCellPath2(Blockmap* bmap, uint const fromBlock[2], block[VY] = fromBlock[VY]; for(count = 0; count < 64; ++count) { - result = callback(block, paramaters); + result = callback(block, parameters); if(result) return result; // Early out. if(block[VX] == toBlock[VX] && block[VY] == toBlock[VY]) @@ -992,8 +1062,8 @@ static int traverseCellPath2(Blockmap* bmap, uint const fromBlock[2], } static int traverseCellPath(GameMap* map, Blockmap* bmap, float const from_[2], - float const to_[2], int (*callback) (uint const block[2], void* paramaters), - void* paramaters) + float const to_[2], int (*callback) (uint const block[2], void* parameters), + void* parameters) { // Constant terms implicitly defined by DOOM's original version of this // algorithm (we must honor these fudge factors for compatibility). @@ -1081,43 +1151,43 @@ static int traverseCellPath(GameMap* map, Blockmap* bmap, float const from_[2], V2_Subtract(from, from, min); V2_Subtract(to, to, min); - return traverseCellPath2(bmap, fromBlock, toBlock, from, to, callback, paramaters); + return traverseCellPath2(bmap, fromBlock, toBlock, from, to, callback, parameters); } typedef struct { int (*callback) (linedef_t*, void*); - void* paramaters; + void* parameters; } iteratepolyobjlinedefs_params_t; -static int iteratePolyobjLineDefs(polyobj_t* po, void* paramaters) +static int iteratePolyobjLineDefs(polyobj_t* po, void* parameters) { - const iteratepolyobjlinedefs_params_t* p = (iteratepolyobjlinedefs_params_t*)paramaters; - return Polyobj_LineIterator(po, p->callback, p->paramaters); + const iteratepolyobjlinedefs_params_t* p = (iteratepolyobjlinedefs_params_t*)parameters; + return Polyobj_LineIterator(po, p->callback, p->parameters); } -static int collectPolyobjLineDefIntercepts(uint const block[2], void* paramaters) +static int collectPolyobjLineDefIntercepts(uint const block[2], void* parameters) { - GameMap* map = (GameMap*)paramaters; + GameMap* map = (GameMap*)parameters; iteratepolyobjlinedefs_params_t iplParams; iplParams.callback = PIT_AddLineDefIntercepts; - iplParams.paramaters = NULL; + iplParams.parameters = NULL; return GameMap_IterateCellPolyobjs(map, block, iteratePolyobjLineDefs, (void*)&iplParams); } -static int collectLineDefIntercepts(uint const block[2], void* paramaters) +static int collectLineDefIntercepts(uint const block[2], void* parameters) { - GameMap* map = (GameMap*)paramaters; + GameMap* map = (GameMap*)parameters; return GameMap_IterateCellLineDefs(map, block, PIT_AddLineDefIntercepts, NULL); } -static int collectMobjIntercepts(uint const block[2], void* paramaters) +static int collectMobjIntercepts(uint const block[2], void* parameters) { - GameMap* map = (GameMap*)paramaters; + GameMap* map = (GameMap*)parameters; return GameMap_IterateCellMobjs(map, block, PIT_AddMobjIntercepts, NULL); } int GameMap_PathTraverse2(GameMap* map, float const from[2], float const to[2], - int flags, traverser_t callback, void* paramaters) + int flags, traverser_t callback, void* parameters) { assert(map); @@ -1140,28 +1210,28 @@ int GameMap_PathTraverse2(GameMap* map, float const from[2], float const to[2], } // Step #2: Process sorted intercepts. - return P_TraverseIntercepts(callback, paramaters); + return P_TraverseIntercepts(callback, parameters); } int GameMap_PathTraverse(GameMap* map, float const from[2], float const to[2], int flags, traverser_t callback) { - return GameMap_PathTraverse2(map, from, to, flags, callback, NULL/*no paramaters*/); + return GameMap_PathTraverse2(map, from, to, flags, callback, NULL/*no parameters*/); } int GameMap_PathXYTraverse2(GameMap* map, float fromX, float fromY, float toX, float toY, - int flags, traverser_t callback, void* paramaters) + int flags, traverser_t callback, void* parameters) { vec2_t from, to; V2_Set(from, fromX, fromY); V2_Set(to, toX, toY); - return GameMap_PathTraverse2(map, from, to, flags, callback, paramaters); + return GameMap_PathTraverse2(map, from, to, flags, callback, parameters); } int GameMap_PathXYTraverse(GameMap* map, float fromX, float fromY, float toX, float toY, int flags, traverser_t callback) { - return GameMap_PathXYTraverse2(map, fromX, fromY, toX, toY, flags, callback, NULL/*no paramaters*/); + return GameMap_PathXYTraverse2(map, fromX, fromY, toX, toY, flags, callback, NULL/*no parameters*/); } subsector_t* GameMap_SubsectorAtPoint(GameMap* map, float point_[2]) diff --git a/doomsday/engine/portable/src/p_data.c b/doomsday/engine/portable/src/p_data.c index d01c54ec61..3d8cc290f6 100644 --- a/doomsday/engine/portable/src/p_data.c +++ b/doomsday/engine/portable/src/p_data.c @@ -86,8 +86,6 @@ surfacelist_t* movingSurfaceList = NULL; surfacelist_t* decoratedSurfaceList = NULL; surfacelist_t* glowingSurfaceList = NULL; -nodepile_t* mobjNodes = NULL, *lineNodes = NULL; // All kinds of wacky links. - float mapGravity; GameMap* theMap = NULL; @@ -181,11 +179,6 @@ void P_SetCurrentMap(GameMap* map) decoratedSurfaceList = 0; glowingSurfaceList = 0; - - mobjNodes = 0; - lineNodes = 0; - linelinks = 0; - mapGravity = 0; theMap = map; @@ -208,10 +201,6 @@ void P_SetCurrentMap(GameMap* map) decoratedSurfaceList = &map->decoratedSurfaceList; glowingSurfaceList = &map->glowingSurfaceList; - mobjNodes = &map->mobjNodes; - lineNodes = &map->lineNodes; - linelinks = map->lineLinks; - mapGravity = map->globalGravity; theMap = map; diff --git a/doomsday/engine/portable/src/p_maputil.c b/doomsday/engine/portable/src/p_maputil.c index 5614d755d0..621018fc09 100644 --- a/doomsday/engine/portable/src/p_maputil.c +++ b/doomsday/engine/portable/src/p_maputil.c @@ -51,18 +51,13 @@ #define DO_LINKS(it, end) { \ for(it = linkstore; it < end; it++) \ { \ - result = func(*it, data); \ + result = callback(*it, parameters); \ if(result) break; \ } \ } // TYPES ------------------------------------------------------------------- -typedef struct { - mobj_t* mo; - AABoxf box; -} linelinker_data_t; - // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -552,7 +547,7 @@ boolean P_IsPointXYInSector(float x, float y, const sector_t* sector) * 2) If there is a node following us, set its sprev pointer to point * to the pointer that points back to it (our sprev, just modified). */ -boolean P_UnlinkFromSector(mobj_t* mo) +boolean P_UnlinkMobjFromSector(mobj_t* mo) { if(!IS_SECTOR_LINKED(mo)) return false; @@ -567,133 +562,142 @@ boolean P_UnlinkFromSector(mobj_t* mo) return true; } +/** + * Unlinks a mobj from everything it has been linked to. + * + * @param mo Ptr to the mobj to be unlinked. + * @return DDLINK_* flags denoting what the mobj was unlinked + * from (in case we need to re-link). + */ +int P_MobjUnlink(mobj_t* mo) +{ + int links = 0; + + if(P_UnlinkMobjFromSector(mo)) + links |= DDLINK_SECTOR; + if(P_UnlinkMobjFromBlockmap(mo)) + links |= DDLINK_BLOCKMAP; + if(!P_UnlinkMobjFromLineDefs(mo)) + links |= DDLINK_NOLINE; + + return links; +} + /** * Unlinks the mobj from all the lines it's been linked to. Can be called * without checking that the list does indeed contain lines. */ -boolean P_UnlinkFromLines(mobj_t* mo) +boolean GameMap_UnlinkMobjFromLineDefs(GameMap* map, mobj_t* mo) { - linknode_t* tn = mobjNodes->nodes; - nodeindex_t nix; + linknode_t* tn; + nodeindex_t nix; + assert(map); // Try unlinking from lines. - if(!mo->lineRoot) + if(!mo || !mo->lineRoot) return false; // A zero index means it's not linked. // Unlink from each line. + tn = map->mobjNodes.nodes; for(nix = tn[mo->lineRoot].next; nix != mo->lineRoot; nix = tn[nix].next) { // Data is the linenode index that corresponds this mobj. - NP_Unlink(lineNodes, tn[nix].data); + NP_Unlink((&map->lineNodes), tn[nix].data); // We don't need these nodes any more, mark them as unused. // Dismissing is a macro. - NP_Dismiss(lineNodes, tn[nix].data); - NP_Dismiss(mobjNodes, nix); + NP_Dismiss((&map->lineNodes), tn[nix].data); + NP_Dismiss((&map->mobjNodes), nix); } // The mobj no longer has a line ring. - NP_Dismiss(mobjNodes, mo->lineRoot); + NP_Dismiss((&map->mobjNodes), mo->lineRoot); mo->lineRoot = 0; return true; } /** - * \pre The mobj must be currently unlinked. + * @important Caller must ensure a mobj is linked only once to any given linedef. + * + * @param map GameMap instance. + * @param mo Mobj to be linked. + * @param lineDef LineDef to link the mobj to. */ -void P_LinkToBlockmap(mobj_t* mo) +void GameMap_LinkMobjToLineDef(GameMap* map, mobj_t* mo, linedef_t* lineDef) { - GameMap* map = theMap; - GameMap_LinkMobjInBlockmap(map, mo); -} + nodeindex_t nodeIndex; + int lineDefIndex; + assert(map); -boolean P_UnlinkFromBlockmap(mobj_t* mo) -{ - GameMap* map = theMap; - return GameMap_UnlinkMobjInBlockmap(map, mo); -} + if(!mo) return; -/** - * Unlinks a mobj from everything it has been linked to. - * - * @param mo Ptr to the mobj to be unlinked. - * @return DDLINK_* flags denoting what the mobj was unlinked - * from (in case we need to re-link). - */ -int P_MobjUnlink(mobj_t* mo) -{ - int links = 0; + lineDefIndex = GameMap_LineDefIndex(map, lineDef); + if(lineDefIndex < 0) return; - if(P_UnlinkFromSector(mo)) - links |= DDLINK_SECTOR; - if(P_UnlinkFromBlockmap(mo)) - links |= DDLINK_BLOCKMAP; - if(!P_UnlinkFromLines(mo)) - links |= DDLINK_NOLINE; + // Add a node to the mobj's ring. + nodeIndex = NP_New(&map->mobjNodes, lineDef); + NP_Link(&map->mobjNodes, nodeIndex, mo->lineRoot); - return links; + // Add a node to the line's ring. Also store the linenode's index + // into the mobjring's node, so unlinking is easy. + nodeIndex = map->mobjNodes.nodes[nodeIndex].data = NP_New(&map->lineNodes, mo); + NP_Link(&map->lineNodes, nodeIndex, map->lineLinks[lineDefIndex]); } +typedef struct { + GameMap* map; + mobj_t* mo; + AABoxf box; +} linelinker_data_t; + /** * The given line might cross the mobj. If necessary, link the mobj into * the line's mobj link ring. */ -int PIT_LinkToLines(linedef_t* ld, void* parm) +int PIT_LinkToLines(linedef_t* ld, void* parameters) { - linelinker_data_t* data = parm; - nodeindex_t nix; - - if(data->box.minX >= ld->aaBox.maxX || - data->box.minY >= ld->aaBox.maxY || - data->box.maxX <= ld->aaBox.minX || - data->box.maxY <= ld->aaBox.minY) - // Bounding boxes do not overlap. - return false; - - if(P_BoxOnLineSide(&data->box, ld) != -1) - // Line does not cross the mobj's bounding box. - return false; - - // One sided lines will not be linked to because a mobj - // can't legally cross one. - if(!ld->L_frontside || !ld->L_backside) - return false; + linelinker_data_t* p = parameters; + assert(p); - // No redundant nodes will be creates since this routine is - // called only once for each line. + // Do the bounding boxes intercept? + if(p->box.minX >= ld->aaBox.maxX || + p->box.minY >= ld->aaBox.maxY || + p->box.maxX <= ld->aaBox.minX || + p->box.maxY <= ld->aaBox.minY) return false; - // Add a node to the mobj's ring. - NP_Link(mobjNodes, nix = NP_New(mobjNodes, ld), data->mo->lineRoot); + // Line does not cross the mobj's bounding box? + if(P_BoxOnLineSide(&p->box, ld) != -1) return false; - // Add a node to the line's ring. Also store the linenode's index - // into the mobjring's node, so unlinking is easy. - NP_Link(lineNodes, mobjNodes->nodes[nix].data = - NP_New(lineNodes, data->mo), linelinks[GET_LINE_IDX(ld)]); + // One sided lines will not be linked to because a mobj can't legally cross one. + if(!ld->L_frontside || !ld->L_backside) return false; + GameMap_LinkMobjToLineDef(p->map, p->mo, ld); return false; } /** - * \pre The mobj must be currently unlinked. + * @important Caller must ensure that the mobj is currently unlinked. */ -void P_LinkToLines(mobj_t* mo) +void GameMap_LinkMobjToLineDefs(GameMap* map, mobj_t* mo) { - linelinker_data_t data; + linelinker_data_t p; vec2_t point; + assert(map); // Get a new root node. - mo->lineRoot = NP_New(mobjNodes, NP_ROOT_NODE); + mo->lineRoot = NP_New(&map->mobjNodes, NP_ROOT_NODE); // Set up a line iterator for doing the linking. - data.mo = mo; + p.map = map; + p.mo = mo; V2_Set(point, mo->pos[VX] - mo->radius, mo->pos[VY] - mo->radius); - V2_InitBox(data.box.arvec2, point); + V2_InitBox(p.box.arvec2, point); V2_Set(point, mo->pos[VX] + mo->radius, mo->pos[VY] + mo->radius); - V2_AddToBox(data.box.arvec2, point); + V2_AddToBox(p.box.arvec2, point); validCount++; - P_AllLinesBoxIterator(&data.box, PIT_LinkToLines, &data); + P_AllLinesBoxIterator(&p.box, PIT_LinkToLines, (void*)&p); } /** @@ -703,7 +707,6 @@ void P_LinkToLines(mobj_t* mo) */ void P_MobjLink(mobj_t* mo, byte flags) { - GameMap* map = theMap; sector_t* sec; // Link into the sector. @@ -714,7 +717,7 @@ void P_MobjLink(mobj_t* mo, byte flags) { // Unlink from the current sector, if any. if(mo->sPrev) - P_UnlinkFromSector(mo); + P_UnlinkMobjFromSector(mo); // Link the new mobj to the head of the list. // Prev pointers point to the pointer that points back to us. @@ -730,18 +733,18 @@ void P_MobjLink(mobj_t* mo, byte flags) if(flags & DDLINK_BLOCKMAP) { // Unlink from the old block, if any. - P_UnlinkFromBlockmap(mo); - P_LinkToBlockmap(mo); + P_UnlinkMobjFromBlockmap(mo); + P_LinkMobjInBlockmap(mo); } // Link into lines. if(!(flags & DDLINK_NOLINE)) { // Unlink from any existing lines. - P_UnlinkFromLines(mo); + P_UnlinkMobjFromLineDefs(mo); // Link to all contacted lines. - P_LinkToLines(mo); + P_LinkMobjToLineDefs(mo); } // If this is a player - perform additional tests to see if they have @@ -764,16 +767,17 @@ void P_MobjLink(mobj_t* mo, byte flags) * The callback function will be called once for each line that crosses * trough the object. This means all the lines will be two-sided. */ -int P_MobjLinesIterator(mobj_t* mo, - int (*func) (linedef_t*, void*), - void* data) +int GameMap_MobjLinesIterator(GameMap* map, mobj_t* mo, + int (*callback) (linedef_t*, void*), void* parameters) { - void* linkstore[MAXLINKED]; - void** end = linkstore, **it; - nodeindex_t nix; - linknode_t* tn = mobjNodes->nodes; + void* linkstore[MAXLINKED]; + void** end = linkstore, **it; + nodeindex_t nix; + linknode_t* tn; int result = false; + assert(map); + tn = map->mobjNodes.nodes; if(mo->lineRoot) { for(nix = tn[mo->lineRoot].next; nix != mo->lineRoot; @@ -791,17 +795,19 @@ int P_MobjLinesIterator(mobj_t* mo, * partly inside). This is not a 3D check; the mobj may actually reside * above or under the sector. */ -int P_MobjSectorsIterator(mobj_t* mo, - int (*func) (sector_t*, void*), - void* data) +int GameMap_MobjSectorsIterator(GameMap* map, mobj_t* mo, + int (*callback) (sector_t*, void*), void* parameters) { - void* linkstore[MAXLINKED]; - void** end = linkstore, **it; - nodeindex_t nix; - linknode_t* tn = mobjNodes->nodes; - linedef_t* ld; - sector_t* sec; + void* linkstore[MAXLINKED]; + void** end = linkstore, **it; + nodeindex_t nix; + linknode_t* tn; + linedef_t* ld; + sector_t* sec; int result = false; + assert(map); + + tn = map->mobjNodes.nodes; // Always process the mobj's own sector first. *end++ = sec = mo->subsector->sector; @@ -840,15 +846,18 @@ int P_MobjSectorsIterator(mobj_t* mo, return result; } -int P_LineMobjsIterator(linedef_t* line, - int (*func) (mobj_t*, void*), - void* data) +int GameMap_LineMobjsIterator(GameMap* map, linedef_t* lineDef, + int (*callback) (mobj_t*, void*), void* parameters) { - void* linkstore[MAXLINKED]; - void** end = linkstore, **it; - nodeindex_t root = linelinks[GET_LINE_IDX(line)], nix; - linknode_t* ln = lineNodes->nodes; + void* linkstore[MAXLINKED]; + void** end = linkstore, **it; + nodeindex_t root, nix; + linknode_t* ln; int result = false; + assert(map); + + root = map->lineLinks[GameMap_LineDefIndex(map, lineDef)], nix; + ln = map->lineNodes.nodes; for(nix = ln[root].next; nix != root; nix = ln[nix].next) *end++ = ln[nix].ptr; @@ -865,18 +874,20 @@ int P_LineMobjsIterator(linedef_t* line, * (Lovely name; actually this is a combination of SectorMobjs and * a bunch of LineMobjs iterations.) */ -int P_SectorTouchingMobjsIterator(sector_t* sector, - int (*func) (mobj_t*, void*), - void* data) +int GameMap_SectorTouchingMobjsIterator(GameMap* map, sector_t* sector, + int (*callback) (mobj_t*, void*), void* parameters) { - uint i; - void* linkstore[MAXLINKED]; - void** end = linkstore, **it; - mobj_t* mo; - linedef_t* li; - nodeindex_t root, nix; - linknode_t* ln = lineNodes->nodes; + uint i; + void* linkstore[MAXLINKED]; + void** end = linkstore, **it; + mobj_t* mo; + linedef_t* li; + nodeindex_t root, nix; + linknode_t* ln; int result = false; + assert(map); + + ln = map->lineNodes.nodes; // First process the mobjs that obviously are in the sector. for(mo = sector->mobjList; mo; mo = mo->sNext) @@ -894,7 +905,7 @@ int P_SectorTouchingMobjsIterator(sector_t* sector, li = sector->lineDefs[i]; // Iterate all mobjs on the line. - root = linelinks[GET_LINE_IDX(li)]; + root = map->lineLinks[GameMap_LineDefIndex(map, li)]; for(nix = ln[root].next; nix != root; nix = ln[nix].next) { mo = (mobj_t *) ln[nix].ptr; @@ -910,93 +921,6 @@ int P_SectorTouchingMobjsIterator(sector_t* sector, return result; } -int P_MobjsBoxIterator(const AABoxf* box, int (*func) (mobj_t*, void*), void* paramaters) -{ - if(theMap) - { - Blockmap* blockmap = theMap->mobjBlockmap; - GridmapBlock blockCoords; - Blockmap_CellBlockCoords(blockmap, &blockCoords, box); - return GameMap_IterateCellBlockMobjs(theMap, &blockCoords, func, paramaters); - } - return false; // Continue iteration. -} - -/** - * The validCount flags are used to avoid checking polys that are marked in - * multiple mapblocks, so increment validCount before the first call, then - * make one or more calls to it. - */ -int P_PolyobjsBoxIterator(const AABoxf* box, int (*callback) (struct polyobj_s*, void*), void* paramaters) -{ - if(theMap) - { - Blockmap* blockmap = theMap->polyobjBlockmap; - GridmapBlock blockCoords; - Blockmap_CellBlockCoords(blockmap, &blockCoords, box); - return GameMap_IterateCellBlockPolyobjs(theMap, &blockCoords, callback, paramaters); - } - return false; // Continue iteration. -} - -int P_LinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* paramaters) -{ - if(theMap) - { - Blockmap* blockmap = theMap->lineDefBlockmap; - GridmapBlock blockCoords; - Blockmap_CellBlockCoords(blockmap, &blockCoords, box); - return GameMap_IterateCellBlockLineDefs(theMap, &blockCoords, callback, paramaters); - } - return false; // Continue iteration. -} - -int P_PolyobjLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* paramaters) -{ - if(theMap) - { - Blockmap* blockmap = theMap->polyobjBlockmap; - GridmapBlock blockCoords; - Blockmap_CellBlockCoords(blockmap, &blockCoords, box); - return GameMap_IterateCellBlockPolyobjLineDefs(theMap, &blockCoords, callback, paramaters); - } - return false; // Continue iteration. -} - -int P_SubsectorsBoxIterator(const AABoxf* box, sector_t* sector, - int (*callback) (subsector_t*, void*), void* paramaters) -{ - if(theMap) - { - static int localValidCount = 0; - Blockmap* blockmap = theMap->subsectorBlockmap; - GridmapBlock blockCoords; - - // This is only used here. - localValidCount++; - - Blockmap_CellBlockCoords(blockmap, &blockCoords, box); - return GameMap_IterateCellBlockSubsectors(theMap, &blockCoords, sector, box, - localValidCount, callback, paramaters); - } - return false; -} - -/** - * The validCount flags are used to avoid checking lines that are marked - * in multiple mapblocks, so increment validCount before the first call - * to GameMap_IterateCellLineDefs(), then make one or more calls to it. - */ -int P_AllLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* paramaters) -{ - if(NUM_POLYOBJS > 0) - { - int result = P_PolyobjLinesBoxIterator(box, callback, paramaters); - if(result) return result; - } - return P_LinesBoxIterator(box, callback, paramaters); -} - /** * Looks for lines in the given block that intercept the given trace to add * to the intercepts list. @@ -1091,56 +1015,154 @@ int PIT_AddMobjIntercepts(mobj_t* mobj, void* paramaters) return false; } +void P_LinkMobjInBlockmap(mobj_t* mo) +{ + /// @fixme Do not assume mobj is from the current map. + if(!theMap) return; + GameMap_LinkMobjInBlockmap(theMap, mo); +} + +boolean P_UnlinkMobjFromBlockmap(mobj_t* mo) +{ + /// @fixme Do not assume mobj is from the current map. + if(!theMap) return false; + return GameMap_UnlinkMobjInBlockmap(theMap, mo); +} + +void P_LinkMobjToLineDefs(mobj_t* mo) +{ + /// @fixme Do not assume mobj is from the current map. + if(!theMap) return; + GameMap_LinkMobjToLineDefs(theMap, mo); +} + +boolean P_UnlinkMobjFromLineDefs(mobj_t* mo) +{ + /// @fixme Do not assume mobj is from the current map. + if(!theMap) return false; + return GameMap_UnlinkMobjFromLineDefs(theMap, mo); +} + +/** + * The callback function will be called once for each line that crosses + * trough the object. This means all the lines will be two-sided. + */ +int P_MobjLinesIterator(mobj_t* mo, int (*callback) (linedef_t*, void*), void* parameters) +{ + /// @fixme Do not assume mobj is in the current map. + return GameMap_MobjLinesIterator(theMap, mo, callback, parameters); +} + +/** + * Increment validCount before calling this routine. The callback function + * will be called once for each sector the mobj is touching (totally or + * partly inside). This is not a 3D check; the mobj may actually reside + * above or under the sector. + */ +int P_MobjSectorsIterator(mobj_t* mo, int (*callback) (sector_t*, void*), void* parameters) +{ + /// @fixme Do not assume mobj is in the current map. + return GameMap_MobjSectorsIterator(theMap, mo, callback, parameters); +} + +int P_LineMobjsIterator(linedef_t* lineDef, int (*callback) (mobj_t*, void*), void* parameters) +{ + /// @fixme Do not assume lineDef is in the current map. + return GameMap_LineMobjsIterator(theMap, lineDef, callback, parameters); +} + +/** + * Increment validCount before using this. 'func' is called for each mobj + * that is (even partly) inside the sector. This is not a 3D test, the + * mobjs may actually be above or under the sector. + * + * (Lovely name; actually this is a combination of SectorMobjs and + * a bunch of LineMobjs iterations.) + */ +int P_SectorTouchingMobjsIterator(sector_t* sector, int (*callback) (mobj_t*, void*), void* parameters) +{ + /// @fixme Do not assume sector is in the current map. + return GameMap_SectorTouchingMobjsIterator(theMap, sector, callback, parameters); +} + +/// @note Part of the Doomsday public API. +int P_MobjsBoxIterator(const AABoxf* box, int (*callback) (mobj_t*, void*), void* parameters) +{ + if(!theMap) return false; // Continue iteration. + return GameMap_MobjsBoxIterator(theMap, box, callback, parameters); +} + +/// @note Part of the Doomsday public API. +int P_PolyobjsBoxIterator(const AABoxf* box, int (*callback) (struct polyobj_s*, void*), void* parameters) +{ + if(!theMap) return false; // Continue iteration. + return GameMap_PolyobjsBoxIterator(theMap, box, callback, parameters); +} + +/// @note Part of the Doomsday public API. +int P_LinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* parameters) +{ + if(!theMap) return false; // Continue iteration. + return GameMap_LineDefsBoxIterator(theMap, box, callback, parameters); +} + +/// @note Part of the Doomsday public API. +int P_PolyobjLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* parameters) +{ + if(!theMap) return false; // Continue iteration. + return GameMap_PolyobjLinesBoxIterator(theMap, box, callback, parameters); +} + +/// @note Part of the Doomsday public API. +int P_SubsectorsBoxIterator(const AABoxf* box, sector_t* sector, + int (*callback) (subsector_t*, void*), void* parameters) +{ + if(!theMap) return false; // Continue iteration. + return GameMap_SubsectorsBoxIterator(theMap, box, sector, callback, parameters); +} + +/// @note Part of the Doomsday public API. +int P_AllLinesBoxIterator(const AABoxf* box, int (*callback) (linedef_t*, void*), void* parameters) +{ + if(!theMap) return false; // Continue iteration. + return GameMap_AllLineDefsBoxIterator(theMap, box, callback, parameters); +} + /// @note Part of the Doomsday public API. int P_PathTraverse2(float const from[2], float const to[2], int flags, traverser_t callback, void* paramaters) { - if(theMap) - { - return GameMap_PathTraverse2(theMap, from, to, flags, callback, paramaters); - } - return false; // Continue iteration. + if(!theMap) return false; // Continue iteration. + return GameMap_PathTraverse2(theMap, from, to, flags, callback, paramaters); } /// @note Part of the Doomsday public API. int P_PathTraverse(float const from[2], float const to[2], int flags, traverser_t callback) { - if(theMap) - { - return GameMap_PathTraverse(theMap, from, to, flags, callback); - } - return false; // Continue iteration. + if(!theMap) return false; // Continue iteration. + return GameMap_PathTraverse(theMap, from, to, flags, callback); } /// @note Part of the Doomsday public API. int P_PathXYTraverse2(float fromX, float fromY, float toX, float toY, int flags, traverser_t callback, void* paramaters) { - if(theMap) - { - return GameMap_PathXYTraverse2(theMap, fromX, fromY, toX, toY, flags, callback, paramaters); - } - return false; // Continue iteration. + if(!theMap) return false; // Continue iteration. + return GameMap_PathXYTraverse2(theMap, fromX, fromY, toX, toY, flags, callback, paramaters); } /// @note Part of the Doomsday public API. int P_PathXYTraverse(float fromX, float fromY, float toX, float toY, int flags, traverser_t callback) { - if(theMap) - { - return GameMap_PathXYTraverse(theMap, fromX, fromY, toX, toY, flags, callback); - } - return false; // Continue iteration. + if(!theMap) return false; // Continue iteration. + return GameMap_PathXYTraverse(theMap, fromX, fromY, toX, toY, flags, callback); } /// @note Part of the Doomsday public API. boolean P_CheckLineSight(const float from[3], const float to[3], float bottomSlope, float topSlope, int flags) { - if(theMap) - { - return GameMap_CheckLineSight(theMap, from, to, bottomSlope, topSlope, flags); - } - return true; // I guess? + if(!theMap) return false; // I guess? + return GameMap_CheckLineSight(theMap, from, to, bottomSlope, topSlope, flags); } diff --git a/doomsday/engine/portable/src/r_world.c b/doomsday/engine/portable/src/r_world.c index 3463a8bba0..8cfc777023 100644 --- a/doomsday/engine/portable/src/r_world.c +++ b/doomsday/engine/portable/src/r_world.c @@ -74,8 +74,6 @@ byte rendSkyLightAuto = true; boolean firstFrameAfterLoad; boolean ddMapSetup; -nodeindex_t* linelinks; // Indices to roots. - skyfix_t skyFix[2]; // PRIVATE DATA DEFINITIONS ------------------------------------------------