Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Refactor: Moved BSP window effect detection back into de::Bsp::Partit…
…ioner

As BSP window effects are now modelled using the objects of the
built BSP tree, it is no longer necessary to keep references to
the window effect sectors within LineDef. This intermediary info
is now stored in the partitioner's LineDefInfo record and then
discarded once partitioning is completed.
  • Loading branch information
danij-deng committed Sep 9, 2012
1 parent 9a5a4eb commit c1a9965
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 250 deletions.
6 changes: 5 additions & 1 deletion doomsday/engine/portable/include/map/bsp/linedefinfo.h
Expand Up @@ -42,6 +42,7 @@ namespace bsp {
*/
struct LineDefInfo
{
/// @todo Refactor me away.
enum Flag
{
Twosided = 0x1, ///< Line is marked two-sided.
Expand All @@ -54,7 +55,10 @@ struct LineDefInfo
/// @todo Refactor me away.
int validCount;

LineDefInfo() : flags(0), validCount(0)
/// If the line is used for a window effect, this is the sector on the back side.
Sector* windowEffect;

LineDefInfo() : flags(0), validCount(0), windowEffect(0)
{}

LineDefInfo& configure(LineDef& line, coord_t distEpsilon = 0.0001)
Expand Down
9 changes: 8 additions & 1 deletion doomsday/engine/portable/include/map/bsp/vertexinfo.h
Expand Up @@ -29,6 +29,7 @@
#define LIBDENG_BSP_VERTEXINFO

#include <list>
#include "map/bsp/partitioner.h"
#include "map/bsp/hedgetip.h"

namespace de {
Expand All @@ -43,12 +44,18 @@ class VertexInfo
public:
typedef std::list<HEdgeTip> HEdgeTips;

VertexInfo() : oneSidedOwnerCount(0), twoSidedOwnerCount(0), tips(0) {}

// Total number of one and two-sided line owners.
uint oneSidedOwnerCount;
uint twoSidedOwnerCount;

/**
* Add a new HEdgeTip to the set in it's rightful place according to an
* anti-clockwise (increasing angle) order.
*/
HEdgeTip& addHEdgeTip(coord_t angle, HEdge* front = 0, HEdge* back = 0,
coord_t angleEpsilon = 0.0001)
coord_t angleEpsilon = ANG_EPSILON)
{
HEdgeTips::reverse_iterator after;

Expand Down
16 changes: 3 additions & 13 deletions doomsday/engine/portable/include/mapdata.hs
Expand Up @@ -447,21 +447,11 @@ internal
(l)->L_frontsector == (l)->L_backsector)

// Internal flags:
#define LF_POLYOBJ 0x1 // Line is part of a polyobject.
#define LF_POLYOBJ 0x1 ///< Line is part of a polyobject.
#define LF_BSPWINDOW 0x2 ///< Line produced a BSP window. @todo Refactor away.
end

internal
typedef struct mlinedef_s {
// Linedef index. Always valid after loading & pruning of zero
// length lines has occurred.
int index;

// One-sided linedef used for a special effect (windows).
// The value refers to the opposite sector on the back side.
/// @todo This reference is now only used during map conversion - we can use a temporary LUT.
struct sector_s* windowEffect;
} mlinedef_t;

/**
* @defgroup sideSectionFlags Side Section Flags
* @ingroup map
Expand Down Expand Up @@ -501,7 +491,7 @@ struct LineDef
DOUBLE coord_t length /// Accurate length.
- AABoxd aaBox
- boolean[DDMAXPLAYERS] mapped /// Whether the line has been mapped by each player yet.
- mlinedef_t buildData
- int origIndex; /// Original index in the archived map.
end

internal
Expand Down
16 changes: 3 additions & 13 deletions doomsday/engine/portable/include/p_maptypes.h
Expand Up @@ -425,18 +425,8 @@ typedef struct sidedef_s {
(l)->L_frontsector == (l)->L_backsector)

// Internal flags:
#define LF_POLYOBJ 0x1 // Line is part of a polyobject.

typedef struct mlinedef_s {
// Linedef index. Always valid after loading & pruning of zero
// length lines has occurred.
int index;

// One-sided linedef used for a special effect (windows).
// The value refers to the opposite sector on the back side.
/// @todo This reference is now only used during map conversion - we can use a temporary LUT.
struct sector_s* windowEffect;
} mlinedef_t;
#define LF_POLYOBJ 0x1 ///< Line is part of a polyobject.
#define LF_BSPWINDOW 0x2 ///< Line produced a BSP window. @todo Refactor away.

/**
* @defgroup sideSectionFlags Side Section Flags
Expand Down Expand Up @@ -470,7 +460,7 @@ typedef struct linedef_s {
coord_t length; /// Accurate length.
AABoxd aaBox;
boolean mapped[DDMAXPLAYERS]; /// Whether the line has been mapped by each player yet.
mlinedef_t buildData;
int origIndex; /// Original index in the archived map.
} LineDef;

#define RIGHT 0
Expand Down
21 changes: 17 additions & 4 deletions doomsday/engine/portable/include/vertex.h
Expand Up @@ -30,20 +30,33 @@
extern "C" {
#endif

/**
* Count the total number of linedef "owners" of this vertex. An owner in
* this context is any linedef whose start or end vertex is this.
*
* @pre Vertex linedef owner rings must have already been calculated.
* @pre @a oneSided and/or @a twoSided must have already been initialized.
*
* @param vtx Vertex instance.
* @param oneSided Total number of one-sided lines is written here. Can be @a NULL.
* @param twoSided Total number of two-sided lines is written here. Can be @a NULL.
*/
void Vertex_CountLineOwners(Vertex* vtx, uint* oneSided, uint* twoSided);

/**
* Get a property value, selected by DMU_* name.
*
* @param vertex Vertex instance.
* @param args Property arguments.
* @param vertex Vertex instance.
* @param args Property arguments.
* @return Always @c 0 (can be used as an iterator).
*/
int Vertex_GetProperty(const Vertex* vertex, setargs_t* args);

/**
* Update a property value, selected by DMU_* name.
*
* @param vertex Vertex instance.
* @param args Property arguments.
* @param vertex Vertex instance.
* @param args Property arguments.
* @return Always @c 0 (can be used as an iterator).
*/
int Vertex_SetProperty(Vertex* vertex, const setargs_t* args);
Expand Down
201 changes: 4 additions & 197 deletions doomsday/engine/portable/src/edit_map.c
Expand Up @@ -92,7 +92,7 @@ static LineDef* createLine(void)
map->lineDefs[map->numLineDefs-1] = line;
map->lineDefs[map->numLineDefs] = NULL;

line->buildData.index = map->numLineDefs; // 1-based index, 0 = NIL.
line->origIndex = map->numLineDefs; // 1-based index, 0 = NIL.
return line;
}

Expand Down Expand Up @@ -1050,7 +1050,7 @@ static void hardenVertexOwnerRings(GameMap* dest, editmap_t* src)
p = v->lineOwners;
while(p)
{
p->lineDef = &dest->lineDefs[p->lineDef->buildData.index - 1];
p->lineDef = &dest->lineDefs[p->lineDef->origIndex - 1];
p = p->LO_next;
}

Expand Down Expand Up @@ -1132,9 +1132,6 @@ static void hardenLinedefs(GameMap* dest, editmap_t* src)
destL->L_backsidedef = (srcL->L_backsidedef?
&dest->sideDefs[srcL->L_backsidedef->buildData.index - 1] : NULL);

if(srcL->buildData.windowEffect)
destL->buildData.windowEffect = &dest->sectors[srcL->buildData.windowEffect->buildData.index - 1];

if(destL->L_frontsidedef)
destL->L_frontsidedef->line = destL;
if(destL->L_backsidedef)
Expand Down Expand Up @@ -1255,7 +1252,7 @@ static void hardenPolyobjs(GameMap* dest, editmap_t* src)
destP->lines = Z_Malloc(sizeof(*destP->lines) * (destP->lineCount+1), PU_MAP, 0);
for(j = 0; j < destP->lineCount; ++j)
{
LineDef* line = &dest->lineDefs[srcP->lines[j]->buildData.index - 1];
LineDef* line = &dest->lineDefs[srcP->lines[j]->origIndex - 1];
HEdge* hedge = &hedges[j];

// This line belongs to a polyobj.
Expand All @@ -1280,194 +1277,6 @@ static void hardenPolyobjs(GameMap* dest, editmap_t* src)
dest->polyObjs[i] = NULL; // Terminate.
}

/**
* @par Algorithm
* Cast a line horizontally or vertically and see what we hit.
* (OUCH, we have to iterate over all linedefs!).
*/
static void testForWindowEffect(editmap_t* map, LineDef* l)
{
// Smallest distance between two points before being considered equal.
#define DIST_EPSILON (1.0 / 128.0)

uint i;
double mX, mY, dX, dY;
boolean castHoriz;
double backDist = DDMAXFLOAT;
Sector* backOpen = NULL;
double frontDist = DDMAXFLOAT;
Sector* frontOpen = NULL;
LineDef* frontLine = NULL, *backLine = NULL;

mX = (l->L_v1origin[VX] + l->L_v2origin[VX]) / 2.0;
mY = (l->L_v1origin[VY] + l->L_v2origin[VY]) / 2.0;

dX = l->L_v2origin[VX] - l->L_v1origin[VX];
dY = l->L_v2origin[VY] - l->L_v1origin[VY];

castHoriz = (fabs(dX) < fabs(dY)? true : false);

for(i = 0; i < map->numLineDefs; ++i)
{
LineDef* n = map->lineDefs[i];
double dist;
boolean isFront;
Sector* hitSector;
double dX2, dY2;

if(n == l || LINE_SELFREF(n) /*|| n->buildData.overlap || n->length <= 0*/)
continue;
if(n->inFlags & LF_POLYOBJ)
continue;

dX2 = n->L_v2origin[VX] - n->L_v1origin[VX];
dY2 = n->L_v2origin[VY] - n->L_v1origin[VY];

if(castHoriz)
{
// Horizontal.
if(fabs(dY2) < DIST_EPSILON)
continue;

if((MAX_OF(n->L_v1origin[VY], n->L_v2origin[VY]) < mY - DIST_EPSILON) ||
(MIN_OF(n->L_v1origin[VY], n->L_v2origin[VY]) > mY + DIST_EPSILON))
continue;

dist = (n->L_v1origin[VX] +
(mY - n->L_v1origin[VY]) * dX2 / dY2) - mX;

isFront = (((dY > 0) != (dist > 0)) ? true : false);

dist = fabs(dist);
if(dist < DIST_EPSILON)
continue; // Too close (overlapping lines ?)

hitSector = n->L_sector((dY > 0) ^ (dY2 > 0) ^ !isFront);
}
else
{ // Vertical.
if(fabs(dX2) < DIST_EPSILON)
continue;

if((MAX_OF(n->L_v1origin[VX], n->L_v2origin[VX]) < mX - DIST_EPSILON) ||
(MIN_OF(n->L_v1origin[VX], n->L_v2origin[VX]) > mX + DIST_EPSILON))
continue;

dist = (n->L_v1origin[VY] +
(mX - n->L_v1origin[VX]) * dY2 / dX2) - mY;

isFront = (((dX > 0) == (dist > 0)) ? true : false);

dist = fabs(dist);

hitSector = n->L_sector((dX > 0) ^ (dX2 > 0) ^ !isFront);
}

if(dist < DIST_EPSILON) // Too close (overlapping lines ?)
continue;

if(isFront)
{
if(dist < frontDist)
{
frontDist = dist;
frontOpen = hitSector;
frontLine = n;
}
}
else
{
if(dist < backDist)
{
backDist = dist;
backOpen = hitSector;
backLine = n;
}
}
}

/*
DEBUG_Message(("back line: %d back dist: %1.1f back_open: %s\n",
(backLine? backLine->buildData.index : -1), backDist,
(backOpen? "OPEN" : "CLOSED")));
DEBUG_Message(("front line: %d front dist: %1.1f front_open: %s\n",
(frontLine? frontLine->buildData.index : -1), frontDist,
(frontOpen? "OPEN" : "CLOSED")));
*/

if(backOpen && frontOpen && l->L_frontsector == backOpen)
{
VERBOSE( Con_Message("Linedef #%d seems to be a One-Sided Window "
"(back faces sector #%d).\n", l->buildData.index - 1,
backOpen->buildData.index - 1) );

l->buildData.windowEffect = frontOpen;
}

#undef DIST_EPSILON
}

static void countVertexLineOwners(Vertex* vtx, uint* oneSided, uint* twoSided)
{
lineowner_t* p;

p = vtx->lineOwners;
while(p)
{
if(!p->lineDef->L_frontsidedef || !p->lineDef->L_backsidedef)
(*oneSided)++;
else
(*twoSided)++;

p = p->LO_next;
}
}

/**
* @par Algorithm
* Scan the linedef list looking for possible candidates, checking for
* an odd number of one-sided linedefs connected to a single vertex. This idea
* courtesy of Graham Jackson.
*/
void MPE_DetectWindowEffects(editmap_t* map)
{
uint i, oneSiders, twoSiders;

for(i = 0; i < map->numLineDefs; ++i)
{
LineDef* l = map->lineDefs[i];

if((l->L_frontsidedef && l->L_backsidedef) || !l->L_frontsidedef /*|| l->length <= 0 ||
l->buildData.overlap*/)
continue;
if(l->inFlags & LF_POLYOBJ)
continue;

oneSiders = twoSiders = 0;
countVertexLineOwners(l->v[0], &oneSiders, &twoSiders);

if((oneSiders % 2) == 1 && (oneSiders + twoSiders) > 1)
{
//DEBUG_Message(("Warning: LineDef #%d start vertex %d has odd number of one-siders\n",
// i, l->buildData.v[0]->index));

testForWindowEffect(map, l);
continue;
}

oneSiders = twoSiders = 0;
countVertexLineOwners(l->v[1], &oneSiders, &twoSiders);

if((oneSiders % 2) == 1 && (oneSiders + twoSiders) > 1)
{
//DEBUG_Message(("Warning: LineDef #%d end vertex %d has odd number of one-siders\n",
// i, l->buildData.v[1]->index));

testForWindowEffect(map, l);
}
}
}

#if 0 /* Currently unused. */
/**
* @return The "lowest" vertex (normally the left-most, but if the line is vertical,
Expand Down Expand Up @@ -1801,8 +1610,6 @@ boolean MPE_End(void)

buildVertexOwnerRings(map);

MPE_DetectWindowEffects(map);

/**
* Harden most of the map data so that we can construct some of the more
* intricate data structures early on (and thus make use of them during
Expand Down Expand Up @@ -2217,7 +2024,7 @@ uint MPE_LinedefCreate(uint v1, uint v2, uint frontSector, uint backSector,
if(!front || !back)
l->flags |= DDLF_BLOCKING;

return l->buildData.index;
return l->origIndex;
}

uint MPE_PlaneCreate(uint sector, coord_t height, const ddstring_t* materialUri, float matOffsetX,
Expand Down

0 comments on commit c1a9965

Please sign in to comment.