From 0d7bd368face5f2eaac658c89b12ff05b223a248 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 17 Apr 2016 15:46:04 +0200 Subject: [PATCH] - added some fudging to draw the outer linedefs of a portal area. This is needed so that polyportals get rendered correctly. For non-polyportals these will normally be outside the portal window and just be discarded. --- src/gl/scene/gl_bsp.cpp | 58 +++++++++++++++++++++++++++++++++------- src/gl/scene/gl_portal.h | 4 ++- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/gl/scene/gl_bsp.cpp b/src/gl/scene/gl_bsp.cpp index a32b8aaa0..bb7cbce4e 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/gl/scene/gl_bsp.cpp @@ -95,7 +95,7 @@ static void UnclipSubsector(subsector_t *sub) static subsector_t *currentsubsector; static sector_t *currentsector; -static void AddLine (seg_t *seg) +static void AddLine (seg_t *seg, bool portalclip) { #ifdef _DEBUG if (seg->linedef - lines == 38) @@ -108,7 +108,7 @@ static void AddLine (seg_t *seg) sector_t * backsector = NULL; sector_t bs; - if (GLRenderer->mCurrentPortal) + if (portalclip) { int clipres = GLRenderer->mCurrentPortal->ClipSeg(seg); if (clipres == GLPortal::PClip_InFront) return; @@ -215,7 +215,7 @@ static void PolySubsector(subsector_t * sub) { if (line->linedef) { - AddLine (line); + AddLine (line, GLRenderer->mCurrentPortal != NULL); } line++; } @@ -310,11 +310,11 @@ static inline void AddLines(subsector_t * sub, sector_t * sector) { if (seg->linedef == NULL) { - if (!(sub->flags & SSECF_DRAWN)) AddLine (seg); + if (!(sub->flags & SSECF_DRAWN)) AddLine (seg, GLRenderer->mCurrentPortal != NULL); } else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) { - AddLine (seg); + AddLine (seg, GLRenderer->mCurrentPortal != NULL); } seg++; } @@ -322,6 +322,40 @@ static inline void AddLines(subsector_t * sub, sector_t * sector) ClipWall.Unclock(); } +//========================================================================== +// +// Adds lines that lie directly on the portal boundary. +// Only two-sided lines will be handled here, and no polyobjects +// +//========================================================================== + +inline bool PointOnLine(const DVector2 &pos, const line_t *line) +{ + double v = (pos.Y - line->v1->fY()) * line->Delta().X + (line->v1->fX() - pos.X) * line->Delta().Y; + return fabs(v) <= EQUAL_EPSILON; +} + +static inline void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line) +{ + currentsector = sector; + currentsubsector = sub; + + ClipWall.Clock(); + int count = sub->numlines; + seg_t * seg = sub->firstline; + + while (count--) + { + if (seg->linedef != NULL && seg->PartnerSeg != NULL) + { + if (PointOnLine(seg->v1->fPos(), line) && PointOnLine(seg->v2->fPos(), line)) + AddLine(seg, false); + } + seg++; + } + ClipWall.Unclock(); +} + //========================================================================== // @@ -395,16 +429,20 @@ static void DoSubsector(subsector_t * sub) UnclipSubsector(sub); } + fakesector=gl_FakeFlat(sector, &fake, false); + if (GLRenderer->mCurrentPortal) { int clipres = GLRenderer->mCurrentPortal->ClipSubsector(sub); - if (clipres == GLPortal::PClip_InFront) return; + if (clipres == GLPortal::PClip_InFront) + { + line_t *line = GLRenderer->mCurrentPortal->ClipLine(); + // The subsector is out of range, but we still have to check lines that lie directly on the boundary and may expose their upper or lower parts. + if (line) AddSpecialPortalLines(sub, fakesector, line); + return; + } } - - - fakesector=gl_FakeFlat(sector, &fake, false); - if (sector->validcount != validcount) { GLRenderer->mVBO->CheckUpdate(sector); diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index d8c5da619..f62db377d 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -137,7 +137,7 @@ public: { PClip_InFront, PClip_Inside, - PClip_Behind + PClip_Behind, }; void RenderPortal(bool usestencil, bool doquery) @@ -165,6 +165,7 @@ public: virtual int ClipSeg(seg_t *seg) { return PClip_Inside; } virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; } virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; } + virtual line_t *ClipLine() { return NULL; } static void BeginScene(); static void StartFrame(); @@ -251,6 +252,7 @@ protected: virtual void DrawContents(); virtual void * GetSource() const { return glport; } virtual const char *GetName(); + virtual line_t *ClipLine() { return line(); } public: