Skip to content

Commit

Permalink
Moved algorithm for REJECT building to map/reject.cpp/h
Browse files Browse the repository at this point in the history
I'm tired of moving this presently unused code around, so its now in
it's own source files. It will be updated and brought into use very
soon, however.
  • Loading branch information
danij-deng committed Apr 6, 2013
1 parent 1cae59f commit 080745d
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 124 deletions.
2 changes: 2 additions & 0 deletions doomsday/client/client.pro
Expand Up @@ -267,6 +267,7 @@ DENG_HEADERS += \
include/map/polyobj.h \
include/map/propertyvalue.h \
include/map/r_world.h \
include/map/reject.h \
include/map/sector.h \
include/map/sidedef.h \
include/map/surface.h \
Expand Down Expand Up @@ -548,6 +549,7 @@ SOURCES += \
src/map/polyobj.cpp \
src/map/propertyvalue.cpp \
src/map/r_world.cpp \
src/map/reject.cpp \
src/map/sector.cpp \
src/map/sidedef.cpp \
src/map/surface.cpp \
Expand Down
77 changes: 77 additions & 0 deletions doomsday/client/include/map/reject.h
@@ -0,0 +1,77 @@
/** @file map/reject.h World Map, Reject LUT building.
*
* @authors Copyright © 2007-2013 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2000-2007 Andrew Apted <ajapted@gmail.com>
* @authors Copyright © 1998-2000 Colin Reed <cph@moria.org.uk>
* @authors Copyright © 1998-2000 Lee Killough <killough@rsn.hp.com>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#ifndef DENG_MAP_REJECT_H
#define DENG_MAP_REJECT_H

#if 0 // Needs updating
class GameMap;

/**
* The REJECT resource is a LUT that provides the results of trivial
* line-of-sight tests between sectors. This is done with a matrix of sector
* pairs i.e. if a monster in sector 4 can see the player in sector 2; the
* inverse should be true.
*
* Note however, some PWADS have carefully constructed REJECT data to create
* special effects. For example it is possible to make a player completely
* invissible in certain sectors.
*
* The format of the table is a simple matrix of boolean values, a (true)
* value indicates that it is impossible for mobjs in sector A to see mobjs
* in sector B (and vice-versa). A (false) value indicates that a
* line-of-sight MIGHT be possible and a more accurate (thus more expensive)
* calculation will have to be made.
*
* The table itself is constructed as follows:
*
* X = sector num player is in
* Y = sector num monster is in
*
* X
*
* 0 1 2 3 4 ->
* 0 1 - 1 - -
* Y 1 - - 1 - -
* 2 1 1 - - 1
* 3 - - - 1 -
* \|/
*
* These results are read left-to-right, top-to-bottom and are packed into
* bytes (each byte represents eight results). As are all lumps in WAD the
* data is in little-endian order.
*
* Thus the size of a valid REJECT lump can be calculated as:
*
* ceiling(numSectors^2)
*
* For now we only do very basic reject processing, limited to determining
* all isolated sector groups (islands that are surrounded by void space).
*
* @note Algorithm:
* Initially all sectors are in individual groups. Next, we scan the line
* list. For each 2-sectored line, merge the two sector groups into one.
*/
byte *BuildRejectForMap(GameMap const &map);
#endif

#endif // DENG_MAP_REJECT_H
124 changes: 0 additions & 124 deletions doomsday/client/src/edit_map.cpp
Expand Up @@ -969,130 +969,6 @@ void MPE_DetectOverlappingLines(GameMap *map)

VERBOSE( Con_Message("Detected %lu overlapping linedefs.", (unsigned long) numOverlaps) )
}

/**
* The REJECT resource is a LUT that provides the results of trivial
* line-of-sight tests between sectors. This is done with a matrix of sector
* pairs i.e. if a monster in sector 4 can see the player in sector 2; the
* inverse should be true.
*
* Note however, some PWADS have carefully constructed REJECT data to create
* special effects. For example it is possible to make a player completely
* invissible in certain sectors.
*
* The format of the table is a simple matrix of boolean values, a (true)
* value indicates that it is impossible for mobjs in sector A to see mobjs
* in sector B (and vice-versa). A (false) value indicates that a
* line-of-sight MIGHT be possible and a more accurate (thus more expensive)
* calculation will have to be made.
*
* The table itself is constructed as follows:
*
* X = sector num player is in
* Y = sector num monster is in
*
* X
*
* 0 1 2 3 4 ->
* 0 1 - 1 - -
* Y 1 - - 1 - -
* 2 1 1 - - 1
* 3 - - - 1 -
* \|/
*
* These results are read left-to-right, top-to-bottom and are packed into
* bytes (each byte represents eight results). As are all lumps in WAD the
* data is in little-endian order.
*
* Thus the size of a valid REJECT lump can be calculated as:
*
* ceiling(numSectors^2)
*
* For now we only do very basic reject processing, limited to determining
* all isolated sector groups (islands that are surrounded by void space).
*
* @note Algorithm:
* Initially all sectors are in individual groups. Next, we scan the linedef
* list. For each 2-sectored line, merge the two sector groups into one.
*/
static void buildReject(GameMap *map)
{
int *secGroups = M_Malloc(sizeof(int) * numSectors);
int group = 0;

for(uint i = 0; i < map->sectorCount(); ++i)
{
Sector &sector = map->sectors[i];
secGroups[i] = group++;
sector.rejNext = sector.rejPrev = &sector;
}

for(uint i = 0; i < map->lineCount(); ++i)
{
LineDef *line = &map->lines[i];

if(!line->hasFrontSideDef() || !line->hasBackSideDef())
continue;

Sector *sec1 = line->frontSectorPtr();
Sector *sec2 = line->backSectorPtr();

if(!sec1 || !sec2 || sec1 == sec2)
continue;

// Already in the same group?
if(secGroups[sec1->index] == secGroups[sec2->index])
continue;

// Swap sectors so that the smallest group is added to the biggest
// group. This is based on the assumption that sector numbers in
// wads will generally increase over the set of linedefs, and so
// (by swapping) we'll tend to add small groups into larger
// groups, thereby minimising the updates to 'rej_group' fields
// that is required when merging.
Sector *p = 0;
if(secGroups[sec1->index] > secGroups[sec2->index])
{
p = sec1;
sec1 = sec2;
sec2 = p;
}

// Update the group numbers in the second group
secGroups[sec2->index] = secGroups[sec1->index];
for(p = sec2->rejNext; p != sec2; p = p->rejNext)
{
secGroups[p->index] = secGroups[sec1->index];
}

// Merge 'em baby...
sec1->rejNext->rejPrev = sec2;
sec2->rejNext->rejPrev = sec1;

p = sec1->rejNext;
sec1->rejNext = sec2->rejNext;
sec2->rejNext = p;
}

size_t rejectSize = (map->sectorCount() * map->sectorCount() + 7) / 8;
byte *matrix = Z_Calloc(rejectSize, PU_MAPSTATIC, 0);

for(int view = 0; view < map->sectorCount(); ++view)
for(int target = 0; target < view; ++target)
{
if(secGroups[view] == secGroups[target])
continue;

// For symmetry, do two bits at a time.
int p1 = view * map->sectorCount() + target;
int p2 = target * map->sectorCount() + view;

matrix[p1 >> 3] |= (1 << (p1 & 7));
matrix[p2 >> 3] |= (1 << (p2 & 7));
}

M_Free(secGroups);
}
#endif

GameMap *MPE_GetLastBuiltMap()
Expand Down
114 changes: 114 additions & 0 deletions doomsday/client/src/map/reject.cpp
@@ -0,0 +1,114 @@
/** @file map/reject.cpp World Map, Reject LUT building.
*
* @authors Copyright © 2007-2013 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2000-2007 Andrew Apted <ajapted@gmail.com>
* @authors Copyright © 1998-2000 Colin Reed <cph@moria.org.uk>
* @authors Copyright © 1998-2000 Lee Killough <killough@rsn.hp.com>
*
* Based on glBSP 2.24 (in turn, based on BSP 2.3).
* @see http://sourceforge.net/projects/glbsp/
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#if 0 // Needs updating.
#include <cmath>

#include "de_base.h"
#include "map/gamemap.h"

using namespace de;

void BuildRejectForMap(GameMap const &map)
{
int *secGroups = M_Malloc(sizeof(int) * map.sectorCount());
int group = 0;

for(uint i = 0; i < map.sectorCount(); ++i)
{
Sector &sector = map.sectors[i];
secGroups[i] = group++;
sector.rejNext = sector.rejPrev = &sector;
}

for(uint i = 0; i < map.lineCount(); ++i)
{
LineDef *line = &map.lines[i];

if(!line->hasFrontSideDef() || !line->hasBackSideDef())
continue;

Sector *sec1 = line->frontSectorPtr();
Sector *sec2 = line->backSectorPtr();

if(!sec1 || !sec2 || sec1 == sec2)
continue;

// Already in the same group?
if(secGroups[sec1->index] == secGroups[sec2->index])
continue;

// Swap sectors so that the smallest group is added to the biggest
// group. This is based on the assumption that sector numbers in
// wads will generally increase over the set of linedefs, and so
// (by swapping) we'll tend to add small groups into larger
// groups, thereby minimising the updates to 'rej_group' fields
// that is required when merging.
Sector *p = 0;
if(secGroups[sec1->index] > secGroups[sec2->index])
{
p = sec1;
sec1 = sec2;
sec2 = p;
}

// Update the group numbers in the second group
secGroups[sec2->index] = secGroups[sec1->index];
for(p = sec2->rejNext; p != sec2; p = p->rejNext)
{
secGroups[p->index] = secGroups[sec1->index];
}

// Merge 'em baby...
sec1->rejNext->rejPrev = sec2;
sec2->rejNext->rejPrev = sec1;

p = sec1->rejNext;
sec1->rejNext = sec2->rejNext;
sec2->rejNext = p;
}

size_t rejectSize = (map.sectorCount() * map.sectorCount() + 7) / 8;
byte *matrix = Z_Calloc(rejectSize, PU_MAPSTATIC, 0);

for(int view = 0; view < map.sectorCount(); ++view)
for(int target = 0; target < view; ++target)
{
if(secGroups[view] == secGroups[target])
continue;

// For symmetry, do two bits at a time.
int p1 = view * map.sectorCount() + target;
int p2 = target * map.sectorCount() + view;

matrix[p1 >> 3] |= (1 << (p1 & 7));
matrix[p2 >> 3] |= (1 << (p2 & 7));
}

M_Free(secGroups);

return matrix;
}
#endif
2 changes: 2 additions & 0 deletions doomsday/server/server.pro
Expand Up @@ -219,6 +219,7 @@ DENG_HEADERS += \
$$SRC/include/map/polyobj.h \
$$SRC/include/map/propertyvalue.h \
$$SRC/include/map/r_world.h \
$$SRC/include/map/reject.h \
$$SRC/include/map/sector.h \
$$SRC/include/map/sidedef.h \
$$SRC/include/map/surface.h \
Expand Down Expand Up @@ -391,6 +392,7 @@ SOURCES += \
$$SRC/src/map/polyobj.cpp \
$$SRC/src/map/propertyvalue.cpp \
$$SRC/src/map/r_world.cpp \
$$SRC/src/map/reject.cpp \
$$SRC/src/map/sector.cpp \
$$SRC/src/map/sidedef.cpp \
$$SRC/src/map/surface.cpp \
Expand Down

0 comments on commit 080745d

Please sign in to comment.