From 29880026a6dfdc06184d2c505fed36650bd24a6e Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Tue, 16 Dec 2014 21:31:21 +0200 Subject: [PATCH] Fixed sprite clipping with drawsegs (removed unnecessary portal check) --- src/r_main.cpp | 53 +++++++++++++++++++++++++----------------------- src/r_plane.cpp | 16 +++++++++++++-- src/r_segs.cpp | 22 ++++++++++++++++---- src/r_things.cpp | 6 ++++-- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 55cde3d9b..676b59ac3 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -625,32 +625,27 @@ void R_HighlightPortal (PortalDrawseg* pds) // I believe it won't break. if it does, blame me. :( BYTE color = (BYTE)BestColor((DWORD *)GPalette.BaseColors, 255, 0, 0, 0, 255); - RenderTarget->DrawLine(pds->x1, pds->ceilingclip[0], pds->x1, pds->floorclip[0], color, 0); - RenderTarget->DrawLine(pds->x2, pds->ceilingclip[pds->ceilingclip.Size()-1], pds->x2, pds->floorclip[pds->floorclip.Size()-1], color, 0); BYTE* pixels = RenderTarget->GetBuffer(); // top edge - for (int x = pds->x1+1; x < pds->x2; x++) + for (int x = pds->x1; x <= pds->x2; x++) { if (x < 0 || x >= RenderTarget->GetWidth()) continue; int p = x - pds->x1; - int Ytop = pds->ceilingclip[p]; int Ybottom = pds->floorclip[p]; + if (x == pds->x1 || x == pds->x2) + { + RenderTarget->DrawLine(x, Ytop, x, Ybottom, color, 0); + continue; + } + int YtopPrev = pds->ceilingclip[p-1]; int YbottomPrev = pds->floorclip[p-1]; - if (Ytop < 0) Ytop = 0; - if (Ybottom >= RenderTarget->GetHeight()) - Ybottom = RenderTarget->GetHeight()-1; - - if (YtopPrev < 0) YtopPrev = 0; - if (YbottomPrev >= RenderTarget->GetHeight()) - YbottomPrev = RenderTarget->GetHeight()-1; - if (abs(Ytop-YtopPrev) > 1) RenderTarget->DrawLine(x, YtopPrev, x, Ytop, color, 0); else *(pixels + Ytop * RenderTarget->GetPitch() + x) = color; @@ -678,10 +673,6 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) BYTE *dest = RenderTarget->GetBuffer() + x + Ytop * spacing; - if (Ytop < 0) Ytop = 0; - if (Ybottom >= RenderTarget->GetHeight()) - Ybottom = RenderTarget->GetHeight()-1; - for (int y = Ytop; y <= Ybottom; y++) { *dest = color; @@ -698,6 +689,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) angle_t startang = viewangle; fixed_t startx = viewx; fixed_t starty = viewy; + fixed_t startz = viewz; CurrentPortalUniq++; @@ -758,17 +750,11 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) CurrentPortal = pds; R_ClearPlanes (false); - R_ClearClipSegs (pds->x1, pds->x2 + 1); // todo: check if this "+1" is actually needed - - // some portals have height differences, account for this here - R_3D_EnterSkybox(); // push 3D floor height map - - memcpy (ceilingclip + pds->x1, &pds->ceilingclip[0], pds->ceilingclip.Size()*sizeof(*ceilingclip)); - memcpy (floorclip + pds->x1, &pds->floorclip[0], pds->floorclip.Size()*sizeof(*floorclip)); + R_ClearClipSegs (pds->x1, pds->x2+1); // todo: check if this "+1" is actually needed WindowLeft = pds->x1; WindowRight = pds->x2; - + // RF_XFLIP should be removed before calling the root function int prevmf = MirrorFlags; if (pds->mirror) @@ -778,6 +764,13 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) else MirrorFlags |= RF_XFLIP; } + // some portals have height differences, account for this here + R_3D_EnterSkybox(); // push 3D floor height map + + // first pass, set clipping + memcpy (ceilingclip + pds->x1, &pds->ceilingclip[0], pds->len*sizeof(*ceilingclip)); + memcpy (floorclip + pds->x1, &pds->floorclip[0], pds->len*sizeof(*floorclip)); + R_RenderBSPNode (nodes + numnodes - 1); R_3D_ResetClip(); // reset clips (floor/ceiling) @@ -786,6 +779,8 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) R_DrawSkyBoxes (); PlaneCycles.Unclock(); + fixed_t vzp = viewz; + int prevuniq = CurrentPortalUniq; // depth check is in another place right now unsigned int portalsAtEnd = WallPortals.Size (); @@ -793,6 +788,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) { R_EnterPortal (&WallPortals[portalsAtStart], depth + 1); } + int prevuniq2 = CurrentPortalUniq; CurrentPortalUniq = prevuniq; NetUpdate(); @@ -803,16 +799,19 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) NetUpdate(); + R_3D_LeaveSkybox(); // pop 3D floor height map + CurrentPortalUniq = prevuniq2; + // draw a red line around a portal if it's being highlighted if (r_highlight_portals) R_HighlightPortal(pds); - R_3D_LeaveSkybox(); // pop 3D floor height map CurrentPortal = prevpds; MirrorFlags = prevmf; viewangle = startang; viewx = startx; viewy = starty; + viewz = startz; } //========================================================================== @@ -897,6 +896,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) WindowRight = viewwidth - 1; MirrorFlags = 0; CurrentPortal = NULL; + CurrentPortalUniq = 0; r_dontmaplines = dontmaplines; @@ -937,6 +937,9 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) R_EnterPortal(&WallPortals[i], 0); } + CurrentPortal = NULL; + CurrentPortalUniq = 0; + NetUpdate (); MaskedCycles.Clock(); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index a19a2f677..ea2678e96 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -689,7 +689,10 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl sky == check->sky && CurrentPortalUniq == check->CurrentPortalUniq && MirrorFlags == check->MirrorFlags && - CurrentSkybox == check->CurrentSkybox + CurrentSkybox == check->CurrentSkybox && + viewx == check->viewx && + viewy == check->viewy && + viewz == check->viewz ) { return check; @@ -1064,22 +1067,31 @@ void R_DrawHeightPlanes(fixed_t height) ds_color = 3; + fixed_t oViewX = viewx, oViewY = viewy, oViewZ = viewz; + angle_t oViewAngle = viewangle; + for (i = 0; i < MAXVISPLANES; i++) { for (pl = visplanes[i]; pl; pl = pl->next) { // kg3D - draw only correct planes - if(pl->CurrentSkybox != CurrentSkybox) + if(pl->CurrentSkybox != CurrentSkybox || pl->CurrentPortalUniq != CurrentPortalUniq) continue; if(pl->sky < 0 && pl->height.Zat0() == height) { viewx = pl->viewx; viewy = pl->viewy; + viewz = pl->viewz; viewangle = pl->viewangle; MirrorFlags = pl->MirrorFlags; R_DrawSinglePlane (pl, pl->sky & 0x7FFFFFFF, pl->Additive, true); } } } + + viewx = oViewX; + viewy = oViewY; + viewz = oViewZ; + viewangle = oViewAngle; } diff --git a/src/r_segs.cpp b/src/r_segs.cpp index b97a6d4d1..d4eb657c3 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2591,10 +2591,24 @@ void R_StoreWallRange (int start, int stop) pds.dst = curline->linedef->portal_dst; pds.x1 = ds_p->x1; pds.x2 = ds_p->x2; - pds.ceilingclip.Resize((pds.x2-pds.x1)+1); - memcpy(&pds.ceilingclip[0], openings + ds_p->sprtopclip, pds.ceilingclip.Size()*sizeof(*openings)); - pds.floorclip.Resize((pds.x2-pds.x1)+1); - memcpy(&pds.floorclip[0], openings + ds_p->sprbottomclip, pds.floorclip.Size()*sizeof(*openings)); + pds.len = (pds.x2 - pds.x1) + 1; + pds.ceilingclip.Resize(pds.len); + memcpy(&pds.ceilingclip[0], openings + ds_p->sprtopclip, pds.len*sizeof(*openings)); + pds.floorclip.Resize(pds.len); + memcpy(&pds.floorclip[0], openings + ds_p->sprbottomclip, pds.len*sizeof(*openings)); + + for (int i = 0; i < (pds.x2-pds.x1)+1; i++) + { + if (pds.ceilingclip[i] < 0) + pds.ceilingclip[i] = 0; + if (pds.ceilingclip[i] >= RenderTarget->GetHeight()) + pds.ceilingclip[i] = RenderTarget->GetHeight()-1; + if (pds.floorclip[i] < 0) + pds.floorclip[i] = 0; + if (pds.floorclip[i] >= RenderTarget->GetHeight()) + pds.floorclip[i] = RenderTarget->GetHeight()-1; + } + pds.mirror = curline->linedef->portal_mirror; WallPortals.Push(pds); } diff --git a/src/r_things.cpp b/src/r_things.cpp index 353961d81..03539eeb6 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2121,8 +2121,10 @@ void R_DrawSprite (vissprite_t *spr) for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough { // [ZZ] portal handling here - if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) - continue; + //if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) + // continue; + // [ZZ] WARNING: uncommenting the two above lines, totally breaks sprite clipping + // kg3D - no clipping on fake segs if (ds->fake) continue; // determine if the drawseg obscures the sprite