Merge branch 'portal-fix' into 'next'

Some fixes for portals

Specifically the following things are fixed in this branch:

* a memory leak resulting from not clearing away clipping-related arrays each tic you view a portal
* a very specific crash to do with portals sometimes (unintentionally) using a hack on drawsegs that don't actually belong to them ...which results in a crash if the drawsegs in question have midtextures. I reported it on the MB a year ago, with a test map included there: https://mb.srb2.org/showthread.php?t=38199&page=4#79
* another specific crash to do with mirrored (horizontally flipped) sprites that are scaled, particularly when you cover up the left edge of them via portals at the least. Needs more testing to be absolutely sure this is fixed, and is also reproducable in the test map linked in the post above

May be fine to merge changes into master too, I don't really know exactly

See merge request !42
This commit is contained in:
Inuyasha 2016-03-31 20:19:58 -04:00
commit 31cec9dfee
6 changed files with 21 additions and 14 deletions

View file

@ -26,6 +26,7 @@ side_t *sidedef;
line_t *linedef; line_t *linedef;
sector_t *frontsector; sector_t *frontsector;
sector_t *backsector; sector_t *backsector;
boolean portalline; // is curline a portal seg?
// very ugly realloc() of drawsegs at run-time, I upped it to 512 // very ugly realloc() of drawsegs at run-time, I upped it to 512
// instead of 256.. and someone managed to send me a level with // instead of 256.. and someone managed to send me a level with
@ -378,6 +379,7 @@ static void R_AddLine(seg_t *line)
return; return;
curline = line; curline = line;
portalline = false;
// OPTIMIZE: quickly reject orthogonal back sides. // OPTIMIZE: quickly reject orthogonal back sides.
angle1 = R_PointToAngle(line->v1->x, line->v1->y); angle1 = R_PointToAngle(line->v1->x, line->v1->y);
@ -431,7 +433,7 @@ static void R_AddLine(seg_t *line)
backsector = line->backsector; backsector = line->backsector;
// Portal line // Portal line
if (line->linedef->special == 40 && P_PointOnLineSide(viewx, viewy, line->linedef) == 0) if (line->linedef->special == 40 && line->side == 0)
{ {
if (portalrender < cv_maxportals.value) if (portalrender < cv_maxportals.value)
{ {

View file

@ -23,6 +23,7 @@ extern side_t *sidedef;
extern line_t *linedef; extern line_t *linedef;
extern sector_t *frontsector; extern sector_t *frontsector;
extern sector_t *backsector; extern sector_t *backsector;
extern boolean portalline; // is curline a portal seg?
// drawsegs are allocated on the fly... see r_segs.c // drawsegs are allocated on the fly... see r_segs.c

View file

@ -667,6 +667,8 @@ typedef struct drawseg_s
INT32 numthicksides; INT32 numthicksides;
fixed_t frontscale[MAXVIDWIDTH]; fixed_t frontscale[MAXVIDWIDTH];
UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping
#ifdef ESLOPE #ifdef ESLOPE
fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures

View file

@ -91,7 +91,6 @@ typedef struct portal_pair
INT16 *ceilingclip; INT16 *ceilingclip;
INT16 *floorclip; INT16 *floorclip;
fixed_t *frontscale; fixed_t *frontscale;
size_t seg;
} portal_pair; } portal_pair;
portal_pair *portal_base, *portal_cap; portal_pair *portal_base, *portal_cap;
line_t *portalclipline; line_t *portalclipline;
@ -1230,7 +1229,7 @@ void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2)
portal->start = x1; portal->start = x1;
portal->end = x2; portal->end = x2;
portal->seg = ds_p-drawsegs; portalline = true; // this tells R_StoreWallRange that curline is a portal seg
portal->viewx = viewx; portal->viewx = viewx;
portal->viewy = viewy; portal->viewy = viewy;
@ -1344,14 +1343,6 @@ void R_RenderPlayerView(player_t *player)
validcount++; validcount++;
if (portal->seg)
{
// Push the portal's old drawseg out of the way so it isn't interfering with sprite clipping. -Red
drawseg_t *seg = drawsegs+portal->seg;
seg->scale1 = 0;
seg->scale2 = 0;
}
R_RenderBSPNode((INT32)numnodes - 1); R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites(); R_ClipSprites();
//R_DrawPlanes(); //R_DrawPlanes();
@ -1360,6 +1351,9 @@ void R_RenderPlayerView(player_t *player)
// okay done. free it. // okay done. free it.
portalcullsector = NULL; // Just in case... portalcullsector = NULL; // Just in case...
portal_base = portal->next; portal_base = portal->next;
Z_Free(portal->ceilingclip);
Z_Free(portal->floorclip);
Z_Free(portal->frontscale);
Z_Free(portal); Z_Free(portal);
} }
// END PORTAL RENDERING // END PORTAL RENDERING

View file

@ -2887,6 +2887,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
R_RenderSegLoop(); R_RenderSegLoop();
colfunc = wallcolfunc; colfunc = wallcolfunc;
if (portalline) // if curline is a portal, set portalrender for drawseg
ds_p->portalpass = portalrender+1;
else
ds_p->portalpass = 0;
// save sprite clipping info // save sprite clipping info
if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
{ {

View file

@ -834,10 +834,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
dc_texturemid = FixedDiv(dc_texturemid,this_scale); dc_texturemid = FixedDiv(dc_texturemid,this_scale);
//Oh lordy, mercy me. Don't freak out if sprites go offscreen! //Oh lordy, mercy me. Don't freak out if sprites go offscreen!
if (vis->xiscale > 0) /*if (vis->xiscale > 0)
frac = FixedDiv(frac, this_scale); frac = FixedDiv(frac, this_scale);
else if (vis->x1 <= 0) else if (vis->x1 <= 0)
frac = (vis->x1 - vis->x2) * vis->xiscale; frac = (vis->x1 - vis->x2) * vis->xiscale;*/
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
//dc_hires = 1; //dc_hires = 1;
@ -1301,7 +1301,7 @@ static void R_ProjectSprite(mobj_t *thing)
} }
if (vis->x1 > x1) if (vis->x1 > x1)
vis->startfrac += vis->xiscale*(vis->x1-x1); vis->startfrac += FixedDiv(vis->xiscale, this_scale)*(vis->x1-x1);
//Fab: lumppat is the lump number of the patch to use, this is different //Fab: lumppat is the lump number of the patch to use, this is different
// than lumpid for sprites-in-pwad : the graphics are patched // than lumpid for sprites-in-pwad : the graphics are patched
@ -2053,6 +2053,9 @@ void R_ClipSprites(void)
continue; continue;
} }
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;