From 537105b8cdd79c1f0db06964936a8c8619e6b141 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 31 Jul 2010 04:53:49 +0000 Subject: [PATCH] - Same as last ZDBSP change: Do not count the segs in a separate pass in CreateNode(). With this, I can't think of any other simplifications I can make to speed up polyobject splitting. In my totally unscientific timedemo test, using the nodebuilder to sort polyobjects inside their subsectors amounted to just 0.1 ms longer per frame (a difference of 321.3 vs 334.9 fps). I think that's acceptable. (For comparison, the unsimplified nodebuilder was about 0.05 ms slower per frame, or 315.8 vs 334.9 fps. Is that considered a 33% speedup?) SVN r2479 (polyobjects) --- src/nodebuild.cpp | 45 ++++++++++++++++++++++----------------------- src/nodebuild.h | 7 +++---- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index e29a64ff72..a51cc854ab 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -124,35 +124,38 @@ void FNodeBuilder::BuildTree () C_InitTicker ("Building BSP", FRACUNIT); HackSeg = DWORD_MAX; HackMate = DWORD_MAX; - CreateNode (0, bbox); + CreateNode (0, Segs.Size(), bbox); CreateSubsectorsForReal (); C_InitTicker (NULL, 0); } -int FNodeBuilder::CreateNode (DWORD set, fixed_t bbox[4]) +int FNodeBuilder::CreateNode (DWORD set, unsigned int count, fixed_t bbox[4]) { node_t node; - int skip, count, selstat; + int skip, selstat; DWORD splitseg; - count = CountSegs (set); - skip = count / MaxSegs; + skip = int(count / MaxSegs); + // When building GL nodes, count may not be an exact count of the number of segs + // in the set. That's okay, because we just use it to get a skip count, so an + // estimate is fine. if ((selstat = SelectSplitter (set, node, splitseg, skip, true)) > 0 || (skip > 0 && (selstat = SelectSplitter (set, node, splitseg, 1, true)) > 0) || (selstat < 0 && (SelectSplitter (set, node, splitseg, skip, false) > 0 || (skip > 0 && SelectSplitter (set, node, splitseg, 1, false)))) || - CheckSubsector (set, node, splitseg, count)) + CheckSubsector (set, node, splitseg)) { // Create a normal node DWORD set1, set2; + unsigned int count1, count2; - SplitSegs (set, node, splitseg, set1, set2); + SplitSegs (set, node, splitseg, set1, set2, count1, count2); D(PrintSet (1, set1)); D(Printf (PRINT_LOG, "(%d,%d) delta (%d,%d) from seg %d\n", node.x>>16, node.y>>16, node.dx>>16, node.dy>>16, splitseg)); D(PrintSet (2, set2)); - node.intchildren[0] = CreateNode (set1, node.bbox[0]); - node.intchildren[1] = CreateNode (set2, node.bbox[1]); + node.intchildren[0] = CreateNode (set1, count1, node.bbox[0]); + node.intchildren[1] = CreateNode (set2, count2, node.bbox[1]); bbox[BOXTOP] = MAX (node.bbox[0][BOXTOP], node.bbox[1][BOXTOP]); bbox[BOXBOTTOM] = MIN (node.bbox[0][BOXBOTTOM], node.bbox[1][BOXBOTTOM]); bbox[BOXLEFT] = MIN (node.bbox[0][BOXLEFT], node.bbox[1][BOXLEFT]); @@ -306,24 +309,12 @@ int STACK_ARGS FNodeBuilder::SortSegs (const void *a, const void *b) } } -int FNodeBuilder::CountSegs (DWORD set) const -{ - int count = 0; - - while (set != DWORD_MAX) - { - count++; - set = Segs[set].next; - } - return count; -} - // Given a set of segs, checks to make sure they all belong to a single // sector. If so, false is returned, and they become a subsector. If not, // a splitter is synthesized, and true is returned to continue processing // down this branch of the tree. -bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int setsize) +bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg) { sector_t *sec; DWORD seg; @@ -768,8 +759,10 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) return score; } -void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1) +void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1, unsigned int &count0, unsigned int &count1) { + unsigned int _count0 = 0; + unsigned int _count1 = 0; outset0 = DWORD_MAX; outset1 = DWORD_MAX; @@ -802,11 +795,13 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou case 0: // seg is entirely in front seg->next = outset0; outset0 = set; + _count0++; break; case 1: // seg is entirely in back seg->next = outset1; outset1 = set; + _count1++; break; default: // seg needs to be split @@ -842,6 +837,8 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou outset0 = seg2; Segs[set].next = outset1; outset1 = set; + _count0++; + _count1++; // Also split the seg on the back side if (Segs[set].partner != DWORD_MAX) @@ -914,6 +911,8 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou { AddMinisegs (node, splitseg, outset0, outset1); } + count0 = _count0; + count1 = _count1; } void FNodeBuilder::SetNodeFromSeg (node_t &node, const FPrivSeg *pseg) const diff --git a/src/nodebuild.h b/src/nodebuild.h index 423aa09962..d1ed2cb15b 100644 --- a/src/nodebuild.h +++ b/src/nodebuild.h @@ -255,16 +255,15 @@ private: bool GetPolyExtents (int polynum, fixed_t bbox[4]); int MarkLoop (DWORD firstseg, int loopnum); void AddSegToBBox (fixed_t bbox[4], const FPrivSeg *seg); - int CreateNode (DWORD set, fixed_t bbox[4]); + int CreateNode (DWORD set, unsigned int count, fixed_t bbox[4]); int CreateSubsector (DWORD set, fixed_t bbox[4]); void CreateSubsectorsForReal (); - bool CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int setsize); + bool CheckSubsector (DWORD set, node_t &node, DWORD &splitseg); bool CheckSubsectorOverlappingSegs (DWORD set, node_t &node, DWORD &splitseg); bool ShoveSegBehind (DWORD set, node_t &node, DWORD seg, DWORD mate); int SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int step, bool nosplit); - void SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1); + void SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1, unsigned int &count0, unsigned int &count1); DWORD SplitSeg (DWORD segnum, int splitvert, int v1InFront); int Heuristic (node_t &node, DWORD set, bool honorNoSplit); - int CountSegs (DWORD set) const; // Returns: // 0 = seg is in front