diff --git a/src/am_map.cpp b/src/am_map.cpp index ba7c301d8d..136d07421a 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2143,7 +2143,6 @@ void AM_showSS() { AM_drawSeg(sub->firstline + i, yellow); } - PO_LinkToSubsectors(); for (int i = 0; i numlines; seg_t * seg = sub->firstline; while (count--) { - angle_t startAngle = seg->v2->GetClipAngle(); - angle_t endAngle = seg->v1->GetClipAngle(); + angle_t startAngle = clipper.GetClipAngle(seg->v2); + angle_t endAngle = clipper.GetClipAngle(seg->v1); // Back side, i.e. backface culling - read: endAngle >= startAngle! if (startAngle-endAngle >= ANGLE_180) @@ -82,11 +77,7 @@ static void UnclipSubsector(subsector_t *sub) // //========================================================================== -// making these 2 variables global instead of passing them as function parameters is faster. -static subsector_t *currentsubsector; -static sector_t *currentsector; - -static void AddLine (seg_t *seg, bool portalclip) +void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip) { #ifdef _DEBUG if (seg->linedef->Index() == 38) @@ -95,7 +86,6 @@ static void AddLine (seg_t *seg, bool portalclip) } #endif - angle_t startAngle, endAngle; sector_t * backsector = NULL; sector_t bs; @@ -105,8 +95,8 @@ static void AddLine (seg_t *seg, bool portalclip) if (clipres == GLPortal::PClip_InFront) return; } - startAngle = seg->v2->GetClipAngle(); - endAngle = seg->v1->GetClipAngle(); + angle_t startAngle = clipper.GetClipAngle(seg->v2); + angle_t endAngle = clipper.GetClipAngle(seg->v1); // Back side, i.e. backface culling - read: endAngle >= startAngle! if (startAngle-endAnglenumlines; seg_t * line = sub->firstline; @@ -226,7 +216,7 @@ static void PolySubsector(subsector_t * sub) // //========================================================================== -static void RenderPolyBSPNode (void *node) +void GLSceneDrawer::RenderPolyBSPNode (void *node) { while (!((size_t)node & 1)) // Keep going until found a subsector { @@ -259,7 +249,7 @@ static void RenderPolyBSPNode (void *node) // //========================================================================== -static void AddPolyobjs(subsector_t *sub) +void GLSceneDrawer::AddPolyobjs(subsector_t *sub) { if (sub->BSP == NULL || sub->BSP->bDirty) { @@ -287,7 +277,7 @@ static void AddPolyobjs(subsector_t *sub) // //========================================================================== -static inline void AddLines(subsector_t * sub, sector_t * sector) +void GLSceneDrawer::AddLines(subsector_t * sub, sector_t * sector) { currentsector = sector; currentsubsector = sub; @@ -331,7 +321,7 @@ inline bool PointOnLine(const DVector2 &pos, const line_t *line) return fabs(v) <= EQUAL_EPSILON; } -static inline void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line) +void GLSceneDrawer::AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line) { currentsector = sector; currentsubsector = sub; @@ -359,9 +349,8 @@ static inline void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, l // //========================================================================== -static inline void RenderThings(subsector_t * sub, sector_t * sector) +void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector) { - SetupSprite.Clock(); sector_t * sec=sub->sector; // Handle all things in sector. @@ -414,7 +403,7 @@ static inline void RenderThings(subsector_t * sub, sector_t * sector) // //========================================================================== -static void DoSubsector(subsector_t * sub) +void GLSceneDrawer::DoSubsector(subsector_t * sub) { unsigned int i; sector_t * sector; @@ -559,7 +548,7 @@ static void DoSubsector(subsector_t * sub) // //========================================================================== -void gl_RenderBSPNode (void *node) +void GLSceneDrawer::RenderBSPNode (void *node) { if (numnodes == 0) { @@ -574,7 +563,7 @@ void gl_RenderBSPNode (void *node) int side = R_PointOnSide(viewx, viewy, bsp); // Recursively divide front space (toward the viewer). - gl_RenderBSPNode (bsp->children[side]); + RenderBSPNode (bsp->children[side]); // Possibly divide back space (away from the viewer). side ^= 1; diff --git a/src/gl/scene/gl_clipper.cpp b/src/gl/scene/gl_clipper.cpp index f1d79c7274..5f458dcecd 100644 --- a/src/gl/scene/gl_clipper.cpp +++ b/src/gl/scene/gl_clipper.cpp @@ -36,28 +36,12 @@ */ #include "gl/scene/gl_clipper.h" +#include "g_levellocals.h" - -ClipNode * ClipNode::freelist; -int Clipper::anglecache; - - -//----------------------------------------------------------------------------- -// -// Destructor -// -//----------------------------------------------------------------------------- - -Clipper::~Clipper() +Clipper::Clipper() { - Clear(); - while (ClipNode::freelist != NULL) - { - ClipNode * node = ClipNode::freelist; - ClipNode::freelist = node->next; - delete node; - } + starttime = I_MSTime(); } //----------------------------------------------------------------------------- @@ -78,7 +62,7 @@ void Clipper::RemoveRange(ClipNode * range) if (range->next) range->next->prev = range->prev; } - range->Free(); + Free(range); } //----------------------------------------------------------------------------- @@ -97,7 +81,7 @@ void Clipper::Clear() { temp = node; node = node->next; - temp->Free(); + Free(temp); } node = silhouette; @@ -105,12 +89,12 @@ void Clipper::Clear() { temp = node; node = node->next; - temp->Free(); + Free(temp); } cliphead = NULL; silhouette = NULL; - anglecache++; + starttime = I_MSTime(); } //----------------------------------------------------------------------------- @@ -126,7 +110,7 @@ void Clipper::SetSilhouette() while (node != NULL) { - ClipNode *snode = ClipNode::NewRange(node->start, node->end); + ClipNode *snode = NewRange(node->start, node->end); if (silhouette == NULL) silhouette = snode; snode->prev = last; if (last != NULL) last->next = snode; @@ -135,7 +119,6 @@ void Clipper::SetSilhouette() } } - //----------------------------------------------------------------------------- // // IsRangeVisible @@ -227,7 +210,7 @@ void Clipper::AddClipRange(angle_t start, angle_t end) //just add range node = cliphead; prevNode = NULL; - temp = ClipNode::NewRange(start, end); + temp = NewRange(start, end); while (node != NULL && node->start < end) { @@ -259,7 +242,7 @@ void Clipper::AddClipRange(angle_t start, angle_t end) } else { - temp = ClipNode::NewRange(start, end); + temp = NewRange(start, end); cliphead = temp; return; } @@ -343,7 +326,7 @@ void Clipper::DoRemoveClipRange(angle_t start, angle_t end) } else if (node->start < start && node->end > end) { - temp=ClipNode::NewRange(end, node->end); + temp = NewRange(end, node->end); node->end=start; temp->next=node->next; temp->prev=node; @@ -389,14 +372,6 @@ angle_t Clipper::AngleToPseudo(angle_t ang) // //----------------------------------------------------------------------------- -fixed_t viewx, viewy; - -void R_SetView() -{ - viewx = FLOAT2FIXED(ViewPos.X); - viewy = FLOAT2FIXED(ViewPos.Y); -} - angle_t R_PointToPseudoAngle(double x, double y) { double vecx = x - ViewPos.X; @@ -411,7 +386,7 @@ angle_t R_PointToPseudoAngle(double x, double y) double result = vecy / (fabs(vecx) + fabs(vecy)); if (vecx < 0) { - result = 2.f - result; + result = 2. - result; } return xs_Fix<30>::ToFix(result); } diff --git a/src/gl/scene/gl_clipper.h b/src/gl/scene/gl_clipper.h index 8da75080e8..9494a1243f 100644 --- a/src/gl/scene/gl_clipper.h +++ b/src/gl/scene/gl_clipper.h @@ -4,57 +4,41 @@ #include "doomtype.h" #include "xs_Float.h" #include "r_utility.h" +#include "memarena.h" + +angle_t R_PointToPseudoAngle(double x, double y); + +// Used to speed up angle calculations during clipping +inline angle_t vertex_t::GetClipAngle() +{ + return R_PointToPseudoAngle(p.X, p.Y); +} class ClipNode { friend class Clipper; - friend class ClipNodesFreer; ClipNode *prev, *next; angle_t start, end; - static ClipNode * freelist; bool operator== (const ClipNode &other) { return other.start == start && other.end == end; } - - void Free() - { - next=freelist; - freelist=this; - } - - static ClipNode * GetNew() - { - if (freelist) - { - ClipNode * p=freelist; - freelist=p->next; - return p; - } - else return new ClipNode; - } - - static ClipNode * NewRange(angle_t start, angle_t end) - { - ClipNode * c=GetNew(); - - c->start=start; - c->end=end; - c->next=c->prev=NULL; - return c; - } - }; class Clipper { - ClipNode * clipnodes; - ClipNode * cliphead; - ClipNode * silhouette; // will be preserved even when RemoveClipRange is called - bool blocked; + unsigned starttime; + TStaticArray anglecache; + FMemArena nodearena; + ClipNode * freelist = nullptr; + + ClipNode * clipnodes = nullptr; + ClipNode * cliphead = nullptr; + ClipNode * silhouette = nullptr; // will be preserved even when RemoveClipRange is called + bool blocked = false; static angle_t AngleToPseudo(angle_t ang); bool IsRangeVisible(angle_t startangle, angle_t endangle); @@ -65,18 +49,36 @@ class Clipper public: - static int anglecache; - - Clipper() - { - blocked = false; - clipnodes=cliphead=NULL; - } - - ~Clipper(); + Clipper(); void Clear(); + void Free(ClipNode *node) + { + node->next = freelist; + freelist = node; + } + + ClipNode * GetNew() + { + if (freelist) + { + ClipNode * p = freelist; + freelist = p->next; + return p; + } + else return (ClipNode*)nodearena.Alloc(sizeof(ClipNode)); + } + + ClipNode * NewRange(angle_t start, angle_t end) + { + ClipNode * c = GetNew(); + + c->start = start; + c->end = end; + c->next = c->prev = NULL; + return c; + } void SetSilhouette(); @@ -142,18 +144,13 @@ public: } bool CheckBox(const float *bspcoord); + + // Used to speed up angle calculations during clipping + inline angle_t GetClipAngle(vertex_t *v) + { + return v->angletime == starttime ? v->viewangle : (v->angletime = starttime, v->viewangle = R_PointToPseudoAngle(v->p.X, v->p.Y)); + } + }; - -extern Clipper clipper; - -angle_t R_PointToPseudoAngle(double x, double y); -void R_SetView(); - -// Used to speed up angle calculations during clipping -inline angle_t vertex_t::GetClipAngle() -{ - return angletime == Clipper::anglecache? viewangle : (angletime = Clipper::anglecache, viewangle = R_PointToPseudoAngle(p.X, p.Y)); -} - #endif \ No newline at end of file diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 4a16b03ebd..ed8993df83 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -51,6 +51,7 @@ #include "gl/scene/gl_clipper.h" #include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_portal.h" +#include "gl/scene/gl_scenedrawer.h" #include "gl/shaders/gl_shader.h" #include "gl/stereo3d/scoped_color_mask.h" #include "gl/textures/gl_material.h" @@ -74,6 +75,7 @@ EXTERN_CVAR(Int, r_mirror_recursions) extern bool r_showviewer; +GLSceneDrawer *GLPortal::drawer; TArray GLPortal::portals; TArray GLPortal::planestack; int GLPortal::recursion; @@ -310,12 +312,12 @@ inline void GLPortal::ClearClipper() { DAngle angleOffset = deltaangle(savedAngle, ViewAngle); - clipper.Clear(); + drawer->clipper.Clear(); static int call=0; // Set the clipper to the minimal visible area - clipper.SafeAddClipRange(0,0xffffffff); + drawer->clipper.SafeAddClipRange(0,0xffffffff); for (unsigned int i = 0; i < lines.Size(); i++) { DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - savedViewPos).Angle() + angleOffset; @@ -323,16 +325,16 @@ inline void GLPortal::ClearClipper() if (deltaangle(endAngle, startAngle) < 0) { - clipper.SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); + drawer->clipper.SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); } } // and finally clip it to the visible area angle_t a1 = GLRenderer->FrustumAngle(); - if (a1 < ANGLE_180) clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1); + if (a1 < ANGLE_180) drawer->clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1); // lock the parts that have just been clipped out. - clipper.SetSilhouette(); + drawer->clipper.SetSilhouette(); } //----------------------------------------------------------------------------- @@ -754,8 +756,8 @@ void GLSectorStackPortal::DrawContents() subsector_t *sub = R_PointInSubsector(ViewPos); if (!(gl_drawinfo->ss_renderflags[sub - ::subsectors] & SSRF_SEEN)) { - clipper.SafeAddClipRange(0, ANGLE_MAX); - clipper.SetBlocked(true); + drawer->clipper.SafeAddClipRange(0, ANGLE_MAX); + drawer->clipper.SetBlocked(true); } GLRenderer->DrawScene(DM_PORTAL); @@ -969,14 +971,14 @@ void GLMirrorPortal::DrawContents() MirrorFlag++; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); - clipper.Clear(); + drawer->clipper.Clear(); angle_t af = GLRenderer->FrustumAngle(); - if (afclipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs()+af, ViewAngle.BAMs()-af); angle_t a2 = linedef->v1->GetClipAngle(); angle_t a1 = linedef->v2->GetClipAngle(); - clipper.SafeAddClipRange(a1,a2); + drawer->clipper.SafeAddClipRange(a1,a2); gl_RenderState.SetClipLine(linedef); gl_RenderState.EnableClipLine(true); diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index a49f03563c..96804dfefd 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -77,6 +77,7 @@ extern UniqueList UniqueHorizons; extern UniqueList UniquePlaneMirrors; extern UniqueList UniqueLineToLines; struct GLEEHorizonPortal; +class GLSceneDrawer; class GLPortal { @@ -90,6 +91,7 @@ protected: static int renderdepth; public: + static GLSceneDrawer *drawer; static int PlaneMirrorMode; static int inupperstack; static int instack[2]; diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index d2a24812e7..2dcb8e7642 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -60,6 +60,7 @@ #include "gl/scene/gl_clipper.h" #include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_portal.h" +#include "gl/scene/gl_scenedrawer.h" #include "gl/shaders/gl_shader.h" #include "gl/stereo3d/gl_stereo3d.h" #include "gl/stereo3d/scoped_view_shifter.h" @@ -267,22 +268,25 @@ void FGLRenderer::SetupView(float vx, float vy, float vz, DAngle va, bool mirror // //----------------------------------------------------------------------------- -void FGLRenderer::CreateScene() +void GLSceneDrawer::CreateScene() { + angle_t a1 = GLRenderer->FrustumAngle(); + InitClipper(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1); + GLPortal::drawer = this; // NOTE THAT THIS DOES NOT WORK YET!!! (only good to let it compile without further changes.) + // reset the portal manager GLPortal::StartFrame(); - PO_LinkToSubsectors(); ProcessAll.Clock(); // clip the scene and fill the drawlists for(unsigned i=0;iglportal = NULL; - gl_spriteindex=0; + GLRenderer->gl_spriteindex=0; Bsp.Clock(); GLRenderer->mVBO->Map(); - R_SetView(); + SetView(); validcount++; // used for processing sidedefs only once by the renderer. - gl_RenderBSPNode (nodes + numnodes - 1); + RenderBSPNode (nodes + numnodes - 1); if (GLRenderer->mCurrentPortal != NULL) GLRenderer->mCurrentPortal->RenderAttached(); Bsp.Unclock(); @@ -497,15 +501,17 @@ void FGLRenderer::DrawScene(int drawmode) ssao_portals_available--; } + GLSceneDrawer drawer; + if (camera != nullptr) { ActorRenderFlags savedflags = camera->renderflags; - CreateScene(); + drawer.CreateScene(); camera->renderflags = savedflags; } else { - CreateScene(); + drawer.CreateScene(); } GLRenderer->mClipPortal = NULL; // this must be reset before any portal recursion takes place. @@ -854,10 +860,6 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo SetViewMatrix(ViewPos.X, ViewPos.Y, ViewPos.Z, false, false); gl_RenderState.ApplyMatrices(); - clipper.Clear(); - angle_t a1 = FrustumAngle(); - clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1); - ProcessScene(toscreen); if (mainview && toscreen) EndDrawScene(lviewsector); // do not call this for camera textures. if (mainview && FGLRenderBuffers::IsEnabled()) diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h new file mode 100644 index 0000000000..b97cddab1b --- /dev/null +++ b/src/gl/scene/gl_scenedrawer.h @@ -0,0 +1,40 @@ +#pragma once + +#include "r_defs.h" +#include "m_fixed.h" +#include "gl_clipper.h" + +class GLSceneDrawer +{ + fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster. + + subsector_t *currentsubsector; // used by the line processing code. + sector_t *currentsector; + + void UnclipSubsector(subsector_t *sub); + void AddLine (seg_t *seg, bool portalclip); + void PolySubsector(subsector_t * sub); + void RenderPolyBSPNode (void *node); + void AddPolyobjs(subsector_t *sub); + void AddLines(subsector_t * sub, sector_t * sector); + void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line); + void RenderThings(subsector_t * sub, sector_t * sector); + void DoSubsector(subsector_t * sub); + void RenderBSPNode(void *node); + +public: + Clipper clipper; + + void CreateScene(); + + void InitClipper(angle_t a1, angle_t a2) + { + clipper.SafeAddClipRangeRealAngles(a1, a2); + } + + void SetView() + { + viewx = FLOAT2FIXED(ViewPos.X); + viewy = FLOAT2FIXED(ViewPos.Y); + } +}; diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 9ea78cf3b0..7b71e0da39 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -684,6 +684,8 @@ void R_SetupFrame (AActor *actor) I_Error ("Tried to render from a NULL actor."); } + PO_LinkToSubsectors(); + player_t *player = actor->player; unsigned int newblend; InterpolationViewer *iview; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index f7b8c9c88a..c6df043ce7 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -143,9 +143,6 @@ namespace swrenderer // [RH] Setup particles for this frame P_FindParticleSubsectors(); - // Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function - PO_LinkToSubsectors(); - ActorRenderFlags savedflags = camera->renderflags; // Never draw the player unless in chasecam mode if (!r_showviewer)