Skip to content

Commit

Permalink
Map Renderer: Updated wall drawer to handle revised "window" constructs
Browse files Browse the repository at this point in the history
This change addresses a critical error with these map constructs, as
seen in Hexen's first map the Winnowing Hall.

Fakeradio glitches with these map constructs have also been addressed
which now look correct from both sides of the window.
  • Loading branch information
danij-deng committed Apr 20, 2012
1 parent d2aa5e8 commit 33e5c87
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 118 deletions.
15 changes: 6 additions & 9 deletions doomsday/engine/portable/src/r_world.c
Expand Up @@ -950,17 +950,14 @@ LineDef *R_FindLineNeighbor(const Sector *sector, const LineDef *line,
return R_FindLineNeighbor(sector, line, cown, antiClockwise, diff);
}

LineDef* R_FindSolidLineNeighbor(const Sector* sector,
const LineDef* line,
const lineowner_t* own,
boolean antiClockwise, binangle_t* diff)
LineDef* R_FindSolidLineNeighbor(const Sector* sector, const LineDef* line,
const lineowner_t* own, boolean antiClockwise, binangle_t* diff)
{
lineowner_t* cown = own->link[!antiClockwise];
LineDef* other = cown->lineDef;
int side;
lineowner_t* cown = own->link[!antiClockwise];
LineDef* other = cown->lineDef;
int side;

if(other == line)
return NULL;
if(other == line) return NULL;

if(diff) *diff += (antiClockwise? cown->angle : own->angle);

Expand Down
47 changes: 24 additions & 23 deletions doomsday/engine/portable/src/rend_fakeradio.c
Expand Up @@ -148,19 +148,19 @@ static void scanNeighbor(boolean scanTop, const LineDef* line, uint side,
{
#define SEP (10)

LineDef* iter;
lineowner_t* own;
binangle_t diff = 0;
float lengthDelta = 0, gap = 0;
float iFFloor, iFCeil;
float iBFloor, iBCeil;
int scanSecSide = side;
Sector* startSector = line->L_sector(side);
Sector* scanSector;
boolean clockwise = toLeft;
boolean stopScan = false;
boolean closed;
float fCeil, fFloor;
LineDef* iter;
lineowner_t* own;
binangle_t diff = 0;
coord_t lengthDelta = 0, gap = 0;
coord_t iFFloor, iFCeil;
coord_t iBFloor, iBCeil;
int scanSecSide = side;
Sector* startSector = line->L_sector(side);
Sector* scanSector;
boolean clockwise = toLeft;
boolean stopScan = false;
boolean closed;
coord_t fCeil, fFloor;

fFloor = line->L_sector(side)->SP_floorvisheight;
fCeil = line->L_sector(side)->SP_ceilvisheight;
Expand Down Expand Up @@ -365,17 +365,15 @@ static void scanNeighbor(boolean scanTop, const LineDef* line, uint side,
}

static void scanNeighbors(shadowcorner_t top[2], shadowcorner_t bottom[2],
const LineDef* line, uint side,
edgespan_t spans[2], boolean toLeft)
const LineDef* line, uint side, edgespan_t spans[2], boolean toLeft)
{
uint i;
edge_t edges[2], *edge; // {bottom, top}
edgespan_t* span;
shadowcorner_t* corner;
float fCeil, fFloor;
uint i;
edge_t edges[2], *edge; // {bottom, top}
edgespan_t* span;
shadowcorner_t* corner;
coord_t fCeil, fFloor;

if(LINE_SELFREF(line))
return;
if(LINE_SELFREF(line)) return;

fFloor = line->L_sector(side)->SP_floorvisheight;
fCeil = line->L_sector(side)->SP_ceilvisheight;
Expand Down Expand Up @@ -510,7 +508,9 @@ static void scanEdges(shadowcorner_t topCorners[2],
}
}
else
{
sideCorners[i].corner = 0;
}

scanNeighbors(topCorners, bottomCorners, line, sid, spans, !i);
}
Expand Down Expand Up @@ -1378,7 +1378,8 @@ static void processEdgeShadow(const BspLeaf* bspLeaf, const LineDef* lineDef,
if(neighbor != lineDef && !neighbor->L_backside &&
neighbor->buildData.windowEffect &&
neighbor->L_frontsector != bspLeaf->sector)
{ // A one-way window, edgeOpen side.
{
// A one-way window, edgeOpen side.
sideOpen[i] = 1;
}
else if(!(neighbor == lineDef || !neighbor->L_backside))
Expand Down
166 changes: 80 additions & 86 deletions doomsday/engine/portable/src/rend_main.c
Expand Up @@ -713,7 +713,7 @@ void Rend_AddMaskedPoly(const rvertex_t* rvertices, const ColorRawf* rcolors,

// Choose an appropriate variant.
/// @fixme Can result in multiple variants being prepared.
/// This decision should be made earlier (in rendSegSection()).
/// This decision should be made earlier (in rendHEdgeSection()).
material = Materials_ChooseVariant(MaterialVariant_GeneralCase(material),
mapSurfaceMaterialSpec(wrapS, wrapT), true, true);
}
Expand Down Expand Up @@ -1503,7 +1503,15 @@ static boolean doRenderSeg(HEdge* hedge,
radioParams.segOffset = &hedge->offset;
radioParams.segLength = &hedge->length;
radioParams.frontSec = hedge->sector;
radioParams.backSec = (!isTwosidedMiddle? HEDGE_BACK_SECTOR(hedge) : NULL);

if(!isTwosidedMiddle && !(hedge->twin && !HEDGE_SIDEDEF(hedge->twin)))
{
radioParams.backSec = HEDGE_BACK_SECTOR(hedge);
}
else
{
radioParams.backSec = NULL;
}

/// @kludge Revert the vertex coords as they may have been changed
/// due to height divisions.
Expand Down Expand Up @@ -1715,13 +1723,10 @@ static void Rend_RenderPlane(BspLeaf* bspLeaf, planetype_t type, coord_t height,
}
}

static boolean rendSegSection(BspLeaf* bspLeaf, HEdge* hedge,
sidedefsection_t section, Surface* surface,
coord_t const from[2], coord_t const to[2],
coord_t bottom, coord_t top,
float const texOffset[2],
Sector* frontsec, boolean softSurface,
boolean addDLights, boolean addMobjShadows, short sideFlags)
static boolean rendHEdgeSection(HEdge* hedge, BspLeaf* bspLeaf, sidedefsection_t section,
Surface* surface, coord_t const from[2], coord_t const to[2], coord_t bottom, coord_t top,
float const texOffset[2], Sector* frontsec, boolean softSurface, boolean addDLights,
boolean addMobjShadows, short sideFlags)
{
boolean solidSeg = true;
float alpha;
Expand Down Expand Up @@ -1933,68 +1938,64 @@ static boolean rendSegSection(BspLeaf* bspLeaf, HEdge* hedge,
return solidSeg;
}

/**
* Renders the given single-sided hedge into the world.
*/
static boolean Rend_RenderSeg(BspLeaf* bspLeaf, HEdge* hedge)
static void reportLineDefDrawn(LineDef* line)
{
boolean solidSeg = true;
SideDef* side;
LineDef* ldef;
coord_t ffloor, fceil;
boolean backSide;
Sector* frontsec;
int pid;
if(!line) return;

side = HEDGE_SIDEDEF(hedge);
if(!side) return false; // A one-way window?
// Already been here?
pid = viewPlayer - ddPlayers;
if(line->mapped[pid]) return;

frontsec = bspLeaf->sector;
backSide = hedge->side;
ldef = hedge->lineDef;
// Mark as drawn.
line->mapped[pid] = true;

pid = viewPlayer - ddPlayers;
if(!ldef->mapped[pid])
// Send a status report.
if(gx.HandleMapObjectStatusReport)
{
ldef->mapped[pid] = true; // This line is now seen in the map.

// Send a status report.
if(gx.HandleMapObjectStatusReport)
gx.HandleMapObjectStatusReport(DMUSC_LINE_FIRSTRENDERED,
GET_LINE_IDX(ldef),
DMU_LINEDEF, &pid);
gx.HandleMapObjectStatusReport(DMUSC_LINE_FIRSTRENDERED, GET_LINE_IDX(line), DMU_LINEDEF, &pid);
}
}

ffloor = bspLeaf->sector->SP_floorvisheight;
fceil = bspLeaf->sector->SP_ceilvisheight;

// Create the wall sections.
/**
* @param hedge HEdge to draw wall surfaces for.
* @param bspLeaf BSP leaf from which to derive plane heights. May not be the
* same as the leaf linked to the half-edge itself (in the case
* of polyobject half-edges).
*/
static boolean Rend_RenderHEdge(HEdge* hedge, BspLeaf* bspLeaf)
{
SideDef* side = HEDGE_SIDEDEF(hedge);
coord_t ffloor, fceil;
Surface* surface;
float texOffset[2];
boolean solid;

// Middle section.
if(side->SW_middleinflags & SUIF_PVIS)
{
float texOffset[2];
Surface* surface = &side->SW_middlesurface;
assert(side);
if(!(side->SW_middleinflags & SUIF_PVIS)) return false;

texOffset[0] = (float)(surface->visOffset[0] + hedge->offset);
texOffset[1] = (float)(surface->visOffset[1]);
// Only a "middle" section.
assert(bspLeaf);
ffloor = bspLeaf->sector->SP_floorvisheight;
fceil = bspLeaf->sector->SP_ceilvisheight;
surface = &side->SW_middlesurface;

if(ldef->flags & DDLF_DONTPEGBOTTOM)
texOffset[1] += -(fceil - ffloor);
texOffset[0] = surface->visOffset[0] + (float)(hedge->offset);
texOffset[1] = surface->visOffset[1];
if(hedge->lineDef->flags & DDLF_DONTPEGBOTTOM)
texOffset[1] += -(fceil - ffloor);

Rend_RadioUpdateLinedef(hedge->lineDef, hedge->side);
Rend_RadioUpdateLinedef(hedge->lineDef, hedge->side);

solidSeg = rendSegSection(bspLeaf, hedge, SS_MIDDLE, &side->SW_middlesurface,
hedge->HE_v1origin, hedge->HE_v2origin, ffloor, fceil,
texOffset,
/*temp >*/ frontsec, /*< temp*/
false, true, true, side->flags);
}
solid = rendHEdgeSection(hedge, bspLeaf, SS_MIDDLE, &side->SW_middlesurface,
hedge->HE_v1origin, hedge->HE_v2origin, ffloor, fceil,
texOffset,
/*temp >*/ bspLeaf->sector, /*< temp*/
false, true, true, side->flags);

if(P_IsInVoid(viewPlayer))
solidSeg = false;
reportLineDefDrawn(hedge->lineDef);

return solidSeg;
return solid;
}

boolean R_FindBottomTop(LineDef* lineDef, int side, sidedefsection_t section,
Expand Down Expand Up @@ -2115,9 +2116,8 @@ boolean R_FindBottomTop(LineDef* lineDef, int side, sidedefsection_t section,
/**
* Render wall sections for a HEdge belonging to a two-sided LineDef.
*/
static boolean Rend_RenderSegTwosided(BspLeaf* bspLeaf, HEdge* hedge)
static boolean Rend_RenderHEdgeTwosided(HEdge* hedge, BspLeaf* bspLeaf)
{
int pid = viewPlayer - ddPlayers;
coord_t bottom, top;
float texOffset[2];
Sector* frontSec, *backSec;
Expand All @@ -2132,16 +2132,7 @@ static boolean Rend_RenderSegTwosided(BspLeaf* bspLeaf, HEdge* hedge)
backSec = backSide->sector;
line = hedge->lineDef;

if(!line->mapped[pid])
{
line->mapped[pid] = true; // This line is now seen in the map.

// Send a status report.
if(gx.HandleMapObjectStatusReport)
gx.HandleMapObjectStatusReport(DMUSC_LINE_FIRSTRENDERED,
GET_LINE_IDX(line),
DMU_LINEDEF, &pid);
}
reportLineDefDrawn(line);

if(backSec == frontSec &&
!frontSide->SW_topmaterial && !frontSide->SW_bottommaterial &&
Expand Down Expand Up @@ -2179,12 +2170,12 @@ static boolean Rend_RenderSegTwosided(BspLeaf* bspLeaf, HEdge* hedge)
LINE_SELFREF(line)? true : false,
&bottom, &top, texOffset))
{
solidSeg = rendSegSection(bspLeaf, hedge, SS_MIDDLE, suf,
hedge->HE_v1origin, hedge->HE_v2origin, bottom, top, texOffset,
frontSec,
(((viewPlayer->shared.flags & (DDPF_NOCLIP|DDPF_CAMERA)) ||
!(line->flags & DDLF_BLOCKING))? true : false),
true, false, frontSide->flags);
solidSeg = rendHEdgeSection(hedge, bspLeaf, SS_MIDDLE, suf,
hedge->HE_v1origin, hedge->HE_v2origin, bottom, top, texOffset,
frontSec,
(((viewPlayer->shared.flags & (DDPF_NOCLIP|DDPF_CAMERA)) ||
!(line->flags & DDLF_BLOCKING))? true : false),
true, false, frontSide->flags);
if(solidSeg)
{
coord_t xbottom, xtop;
Expand Down Expand Up @@ -2225,9 +2216,9 @@ static boolean Rend_RenderSegTwosided(BspLeaf* bspLeaf, HEdge* hedge)
LINE_SELFREF(line)? true : false,
&bottom, &top, texOffset))
{
rendSegSection(bspLeaf, hedge, SS_TOP, suf,
hedge->HE_v1origin, hedge->HE_v2origin, bottom, top, texOffset,
frontSec, false, true, true, frontSide->flags);
rendHEdgeSection(hedge, bspLeaf, SS_TOP, suf,
hedge->HE_v1origin, hedge->HE_v2origin, bottom, top, texOffset,
frontSec, false, true, true, frontSide->flags);
}
}

Expand All @@ -2245,9 +2236,9 @@ static boolean Rend_RenderSegTwosided(BspLeaf* bspLeaf, HEdge* hedge)
LINE_SELFREF(line)? true : false,
&bottom, &top, texOffset))
{
rendSegSection(bspLeaf, hedge, SS_BOTTOM, suf,
hedge->HE_v1origin, hedge->HE_v2origin, bottom, top, texOffset,
frontSec, false, true, true, frontSide->flags);
rendHEdgeSection(hedge, bspLeaf, SS_BOTTOM, suf,
hedge->HE_v1origin, hedge->HE_v2origin, bottom, top, texOffset,
frontSec, false, true, true, frontSide->flags);
}
}

Expand Down Expand Up @@ -2773,16 +2764,19 @@ static void Rend_RenderBspLeaf(BspLeaf* bspLeaf)
do
{
if(hedge->lineDef && // "minisegs" have no linedefs.
!(hedge->lineDef->inFlags & LF_POLYOBJ) && // Not handled here.
HEDGE_SIDEDEF(hedge) && // "windows" have no sidedef.
(hedge->frameFlags & HEDGEINF_FACINGFRONT))
{
boolean solid;
if(!hedge->sector || !HEDGE_BACK_SECTOR(hedge))
solid = Rend_RenderSeg(bspLeaf, hedge);

if(!hedge->sector || !HEDGE_BACK_SECTOR(hedge) ||
(hedge->twin && !HEDGE_SIDEDEF(hedge->twin)) /* front side of a "window" */)
solid = Rend_RenderHEdge(hedge, bspLeaf);
else
solid = Rend_RenderSegTwosided(bspLeaf, hedge);
solid = Rend_RenderHEdgeTwosided(hedge, bspLeaf);

if(solid)
// When the viewer is in the void no wall is "solid".
if(solid && !P_IsInVoid(viewPlayer))
{
C_AddViewRelSeg(hedge->HE_v1origin[VX], hedge->HE_v1origin[VY],
hedge->HE_v2origin[VX], hedge->HE_v2origin[VY]);
Expand All @@ -2804,7 +2798,7 @@ static void Rend_RenderBspLeaf(BspLeaf* bspLeaf)
// Let's first check which way this hedge is facing.
if(hedge->frameFlags & HEDGEINF_FACINGFRONT)
{
boolean solid = Rend_RenderSeg(bspLeaf, hedge);
boolean solid = Rend_RenderHEdge(hedge, bspLeaf);
if(solid)
{
C_AddViewRelSeg(hedge->HE_v1origin[VX], hedge->HE_v1origin[VY],
Expand Down

0 comments on commit 33e5c87

Please sign in to comment.