diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index 6fe591527..01f157a93 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -287,6 +287,23 @@ bool PolyCull::GetAnglesForLine(double x1, double y1, double x2, double y2, angl return !IsSegmentCulled(angle1, angle2); } +void PolyCull::MarkViewFrustum() +{ + // Clips things outside the viewing frustum. + auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + auto &viewwindow = PolyRenderer::Instance()->Viewwindow; + double tilt = fabs(viewpoint.Angles.Pitch.Degrees); + if (tilt > 46.0) // If the pitch is larger than this you can look all around + return; + + double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(viewwindow.WidescreenRatio) / 90.0; + angle_t a1 = DAngle(floatangle).BAMs(); + if (a1 < ANGLE_180) + { + MarkSegmentCulled(AngleToPseudo(viewpoint.Angles.Yaw.BAMs() + a1), AngleToPseudo(viewpoint.Angles.Yaw.BAMs() - a1)); + } +} + //----------------------------------------------------------------------------- // // ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the @@ -320,3 +337,16 @@ angle_t PolyCull::PointToPseudoAngle(double x, double y) return xs_Fix<30>::ToFix(result); } } + +angle_t PolyCull::AngleToPseudo(angle_t ang) +{ + double vecx = cos(ang * M_PI / ANGLE_180); + double vecy = sin(ang * M_PI / ANGLE_180); + + double result = vecy / (fabs(vecx) + fabs(vecy)); + if (vecx < 0) + { + result = 2.f - result; + } + return xs_Fix<30>::ToFix(result); +} diff --git a/src/polyrenderer/scene/poly_cull.h b/src/polyrenderer/scene/poly_cull.h index d217de7ef..d0430501d 100644 --- a/src/polyrenderer/scene/poly_cull.h +++ b/src/polyrenderer/scene/poly_cull.h @@ -35,6 +35,7 @@ public: void MarkSegmentCulled(angle_t angle1, angle_t angle2); bool IsSegmentCulled(angle_t angle1, angle_t angle2) const; void InvertSegments(); + void MarkViewFrustum(); std::vector PvsSectors; double MaxCeilingHeight = 0.0; @@ -64,4 +65,5 @@ private: Vec4f PortalClipPlane; static angle_t PointToPseudoAngle(double x, double y); + static angle_t AngleToPseudo(angle_t ang); }; diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 176341e97..f3a0b2887 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -73,6 +73,7 @@ void RenderPolyScene::Render(int portalDepth) ClearBuffers(); if (!PortalSegmentsAdded) Cull.ClearSolidSegments(); + Cull.MarkViewFrustum(); Cull.CullScene(WorldToClip, PortalPlane); Cull.ClearSolidSegments(); RenderSectors(); @@ -124,6 +125,8 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub) } } + RenderMemory &memory = PolyRenderer::Instance()->FrameMemory; + bool mainBSP = ((unsigned int)(sub->Index()) < level.subsectors.Size()); if (mainBSP) { @@ -131,7 +134,7 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub) for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext) { particle_t *particle = Particles + i; - TranslucentObjects.push_back({ particle, sub, subsectorDepth }); + TranslucentObjects.push_back(memory.NewObject(particle, sub, subsectorDepth)); } } @@ -146,7 +149,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, const DVe subsector_t *sub = &level.subsectors[0]; auto it = SubsectorDepths.find(sub); if (it != SubsectorDepths.end()) - TranslucentObjects.push_back({ thing, sub, it->second, sortDistance, 0.0f, 1.0f }); + TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, 0.0f, 1.0f)); } else { @@ -187,7 +190,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, DVector2 auto it = SubsectorDepths.find(sub); if (it != SubsectorDepths.end()) - TranslucentObjects.push_back({ thing, sub, it->second, sortDistance, (float)t1, (float)t2 }); + TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, (float)t1, (float)t2)); } void RenderPolyScene::RenderLine(subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) @@ -347,29 +350,29 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) } } - std::stable_sort(TranslucentObjects.begin(), TranslucentObjects.end()); + std::stable_sort(TranslucentObjects.begin(), TranslucentObjects.end(), [](auto a, auto b) { return *a < *b; }); for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it) { - auto &obj = *it; - if (obj.particle) + PolyTranslucentObject *obj = *it; + if (obj->particle) { RenderPolyParticle spr; - spr.Render(WorldToClip, PortalPlane, obj.particle, obj.sub, obj.subsectorDepth, StencilValue + 1); + spr.Render(WorldToClip, PortalPlane, obj->particle, obj->sub, obj->subsectorDepth, StencilValue + 1); } - else if (!obj.thing) + else if (!obj->thing) { - obj.wall.Render(WorldToClip, PortalPlane, Cull); + obj->wall.Render(WorldToClip, PortalPlane, Cull); } - else if ((obj.thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) + else if ((obj->thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) { RenderPolyWallSprite wallspr; - wallspr.Render(WorldToClip, PortalPlane, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1); + wallspr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, obj->subsectorDepth, StencilValue + 1); } else { RenderPolySprite spr; - spr.Render(WorldToClip, PortalPlane, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1, obj.SpriteLeft, obj.SpriteRight); + spr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, obj->subsectorDepth, StencilValue + 1, obj->SpriteLeft, obj->SpriteRight); } } } diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index ba6fd5eea..77c7925c0 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -97,7 +97,7 @@ private: uint32_t NextSubsectorDepth = 0; std::set SeenSectors; std::unordered_map SubsectorDepths; - std::vector TranslucentObjects; + std::vector TranslucentObjects; std::vector> SectorPortals; std::vector> LinePortals; diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 078b10e0d..abbfd15f8 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -37,7 +37,7 @@ EXTERN_CVAR(Bool, r_drawmirrors) -bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals) +bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals) { PolyDrawLinePortal *polyportal = nullptr; if (line->backsector == nullptr && line->linedef && line->sidedef == line->linedef->sidedef[0] && (line->linedef->special == Line_Mirror && r_drawmirrors)) @@ -153,7 +153,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipP FTexture *midtex = TexMan(line->sidedef->GetTexture(side_t::mid), true); if (midtex && midtex->UseType != FTexture::TEX_Null) - translucentWallsOutput.push_back({ wall }); + translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(wall)); if (polyportal) { @@ -165,7 +165,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipP return polyportal != nullptr; } -void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput) +void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput) { double frontceilz1 = fakeFloor->top.plane->ZatPoint(line->v1); double frontfloorz1 = fakeFloor->bottom.plane->ZatPoint(line->v1); diff --git a/src/polyrenderer/scene/poly_wall.h b/src/polyrenderer/scene/poly_wall.h index 014110a40..a435201b2 100644 --- a/src/polyrenderer/scene/poly_wall.h +++ b/src/polyrenderer/scene/poly_wall.h @@ -32,8 +32,8 @@ class Vec4f; class RenderPolyWall { public: - static bool RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals); - static void Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); + static bool RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals); + static void Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2); void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull);