mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-01 00:12:27 +00:00
- 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)
This commit is contained in:
parent
edb4686a48
commit
537105b8cd
2 changed files with 25 additions and 27 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue