From c21037fb03c82b2c2ba56651d332d4ec8917b10a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 24 Mar 2017 02:11:24 +0100 Subject: [PATCH] - fix sky sector portals --- src/polyrenderer/scene/poly_cull.cpp | 3 +- src/polyrenderer/scene/poly_plane.cpp | 153 ++++++++++++++------------ src/polyrenderer/scene/poly_scene.cpp | 17 ++- 3 files changed, 97 insertions(+), 76 deletions(-) diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index 45efb604b..c8fd1f5d1 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -110,7 +110,8 @@ void PolyCull::InvertSegments() angle_t cur = 0; for (const auto &segment : TempInvertSolidSegments) { - MarkSegmentCulled(cur, segment.Start - 1); + if (segment.Start != 0 || segment.End != ANGLE_MAX) + MarkSegmentCulled(cur, segment.Start - 1); cur = segment.End + 1; } if (cur != 0) diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 63e1bb325..ee762742e 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -157,75 +157,7 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const Vec4f &c void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - std::vector portalSegments; - FSectorPortal *portal = nullptr;// sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); bool foggy = false; - PolyDrawSectorPortal *polyportal = nullptr; - if (portal && (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into - portal = nullptr; - if (portal) - { - for (auto &p : sectorPortals) - { - if (p->Portal == portal) // To do: what other criteria do we need to check for? - { - polyportal = p.get(); - break; - } - } - if (!polyportal) - { - sectorPortals.push_back(std::make_unique(portal, ceiling)); - polyportal = sectorPortals.back().get(); - } - - // Calculate portal clipping - - DVector2 v; - bool inside = true; - double vdist = 1.0e10; - - portalSegments.reserve(sub->numlines); - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - - DVector2 pt1 = line->v1->fPos() - viewpoint.Pos; - DVector2 pt2 = line->v2->fPos() - viewpoint.Pos; - if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) - inside = false; - - double dist = pt1.LengthSquared(); - if (dist < vdist) - { - v = line->v1->fPos(); - vdist = dist; - } - dist = pt2.LengthSquared(); - if (dist < vdist) - { - v = line->v2->fPos(); - vdist = dist; - } - - angle_t angle1, angle2; - if (cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) - portalSegments.push_back({ angle1, angle2 }); - } - - if (inside) - { - polyportal->PortalPlane = Vec4f(0.0f, 0.0f, 0.0f, 1.0f); - } - else if(polyportal->PortalPlane == Vec4f(0.0f) || Vec4f::dot(polyportal->PortalPlane, Vec4f((float)v.X, (float)v.Y, 0.0f, 1.0f)) > 0.0f) - { - DVector2 planePos = v; - DVector2 planeNormal = v - viewpoint.Pos; - planeNormal.MakeUnit(); - double planeD = -(planeNormal | (planePos + planeNormal * 0.001)); - polyportal->PortalPlane = Vec4f((float)planeNormal.X, (float)planeNormal.Y, 0.0f, (float)planeD); - } - } sector_t *fakesector = sub->sector->heightsec; if (fakesector && (fakesector == sub->sector || (fakesector->MoreFlags & SECF_IGNOREHEIGHTSEC) == SECF_IGNOREHEIGHTSEC)) @@ -304,6 +236,89 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan bool isSky = picnum == skyflatnum; + std::vector portalSegments; + FSectorPortal *portal = sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); + PolyDrawSectorPortal *polyportal = nullptr; + if (portal && (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into + portal = nullptr; + + if (portal) + { + for (auto &p : sectorPortals) + { + if (p->Portal == portal) // To do: what other criteria do we need to check for? + { + polyportal = p.get(); + break; + } + } + if (!polyportal) + { + sectorPortals.push_back(std::make_unique(portal, ceiling)); + polyportal = sectorPortals.back().get(); + } + + // Calculate portal clipping + + if (!isSky) + { + DVector2 v; + bool inside = true; + double vdist = 1.0e10; + + portalSegments.reserve(sub->numlines); + for (uint32_t i = 0; i < sub->numlines; i++) + { + seg_t *line = &sub->firstline[i]; + + DVector2 pt1 = line->v1->fPos() - viewpoint.Pos; + DVector2 pt2 = line->v2->fPos() - viewpoint.Pos; + bool backside = pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0; + if (backside) + inside = false; + + double dist = pt1.LengthSquared(); + if (dist < vdist) + { + v = line->v1->fPos(); + vdist = dist; + } + dist = pt2.LengthSquared(); + if (dist < vdist) + { + v = line->v2->fPos(); + vdist = dist; + } + + if (!backside) + { + angle_t angle1, angle2; + if (cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) + portalSegments.push_back({ angle1, angle2 }); + } + else + { + angle_t angle1, angle2; + if (cull.GetAnglesForLine(line->v2->fX(), line->v2->fY(), line->v1->fX(), line->v1->fY(), angle1, angle2)) + portalSegments.push_back({ angle1, angle2 }); + } + } + + if (inside) + { + polyportal->PortalPlane = Vec4f(0.0f, 0.0f, 0.0f, 1.0f); + } + else if(polyportal->PortalPlane == Vec4f(0.0f) || Vec4f::dot(polyportal->PortalPlane, Vec4f((float)v.X, (float)v.Y, 0.0f, 1.0f)) > 0.0f) + { + DVector2 planePos = v; + DVector2 planeNormal = v - viewpoint.Pos; + planeNormal.MakeUnit(); + double planeD = -(planeNormal | (planePos + planeNormal * 0.001)); + polyportal->PortalPlane = Vec4f((float)planeNormal.X, (float)planeNormal.Y, 0.0f, (float)planeD); + } + } + } + UVTransform transform(ceiling ? frontsector->planes[sector_t::ceiling].xform : frontsector->planes[sector_t::floor].xform, tex); PolyCameraLight *cameraLight = PolyCameraLight::Instance(); @@ -371,7 +386,6 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan { args.stencilwritevalue = polyportal->StencilValue; polyportal->Shape.push_back({ args.vinput, args.vcount, args.ccw, subsectorDepth }); - polyportal->Segments.insert(polyportal->Segments.end(), portalSegments.begin(), portalSegments.end()); } else { @@ -453,7 +467,6 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan if (portal) { polyportal->Shape.push_back({ args.vinput, args.vcount, args.ccw, subsectorDepth }); - polyportal->Segments.insert(polyportal->Segments.end(), portalSegments.begin(), portalSegments.end()); } } } diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index c70ef0195..176341e97 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -52,13 +52,20 @@ void RenderPolyScene::SetViewpoint(const TriMatrix &worldToClip, const Vec4f &po void RenderPolyScene::SetPortalSegments(const std::vector &segments) { - Cull.ClearSolidSegments(); - for (const auto &segment : segments) + if (!segments.empty()) { - Cull.MarkSegmentCulled(segment.Start, segment.End); + Cull.ClearSolidSegments(); + for (const auto &segment : segments) + { + Cull.MarkSegmentCulled(segment.Start, segment.End); + } + Cull.InvertSegments(); + PortalSegmentsAdded = true; + } + else + { + PortalSegmentsAdded = false; } - Cull.InvertSegments(); - PortalSegmentsAdded = true; } void RenderPolyScene::Render(int portalDepth)