mirror of
https://github.com/ZDoom/zdbsp.git
synced 2025-02-14 16:11:56 +00:00
- Changed FEventTree into a regular binary tree, since there just aren't enough
nodes inserted into it to make a red-black tree worthwhile. - Added more checks at the start of ClassifyLine so that it has a better chance of avoiding the more complicated checking, and it seems to have paid off with a reasonably modest performance boost. SVN r169 (trunk)
This commit is contained in:
parent
738eabc6be
commit
cf0d73b128
5 changed files with 28 additions and 236 deletions
4
main.cpp
4
main.cpp
|
@ -507,12 +507,14 @@ static bool CheckInOutNames ()
|
|||
|
||||
angle_t PointToAngle (fixed_t x, fixed_t y)
|
||||
{
|
||||
const double rad2bam = double(1<<30) / M_PI;
|
||||
double ang = atan2 (double(y), double(x));
|
||||
const double rad2bam = double(1<<30) / M_PI;
|
||||
#if 0
|
||||
if (ang < 0.0)
|
||||
{
|
||||
ang = 2*M_PI+ang;
|
||||
}
|
||||
#endif
|
||||
return angle_t(ang * rad2bam) << 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -713,8 +713,13 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
|
|||
return score;
|
||||
}
|
||||
|
||||
// Returns:
|
||||
// 0 = seg is in front
|
||||
// 1 = seg is in back
|
||||
// -1 = seg cuts the node
|
||||
int FNodeBuilder::ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2)
|
||||
{
|
||||
#define FAR_ENOUGH 17179869184.f // 4<<32
|
||||
const FPrivVert *v1 = &Vertices[seg->v1];
|
||||
const FPrivVert *v2 = &Vertices[seg->v2];
|
||||
|
||||
|
@ -727,21 +732,33 @@ int FNodeBuilder::ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1,
|
|||
double d_yv1 = double(v1->y);
|
||||
double d_yv2 = double(v2->y);
|
||||
|
||||
double s_num1 = (d_y1 - d_yv1)*d_dx - (d_x1 - d_xv1) * d_dy;
|
||||
double s_num2 = (d_y1 - d_yv2)*d_dx - (d_x1 - d_xv2) * d_dy;
|
||||
double s_num1 = (d_y1 - d_yv1) * d_dx - (d_x1 - d_xv1) * d_dy;
|
||||
double s_num2 = (d_y1 - d_yv2) * d_dx - (d_x1 - d_xv2) * d_dy;
|
||||
|
||||
if (s_num1 <= -17179869184.0 && s_num2 <= -17179869184.0)
|
||||
if (s_num1 <= -FAR_ENOUGH && s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev1 = sidev2 = 1;
|
||||
return 1;
|
||||
}
|
||||
if (s_num1 >= 17179869184.0 && s_num2 >= 17179869184.0)
|
||||
if (s_num1 >= FAR_ENOUGH && s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev1 = sidev2 = -1;
|
||||
return 0;
|
||||
}
|
||||
if (s_num1 <= -FAR_ENOUGH && s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev1 = 1;
|
||||
sidev2 = -1;
|
||||
return -1;
|
||||
}
|
||||
if (s_num1 >= FAR_ENOUGH && s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev1 = -1;
|
||||
sidev2 = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int near = (fabs(s_num1) < 17179869184.0) | ((fabs(s_num2) < 17179869184.0) << 1);
|
||||
int near = (fabs(s_num1) < FAR_ENOUGH) | ((fabs(s_num2) < FAR_ENOUGH) << 1);
|
||||
if (near)
|
||||
{
|
||||
double l = 1.0 / (d_dx*d_dx + d_dy*d_dy);
|
||||
|
@ -1133,7 +1150,7 @@ int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int dy)
|
|||
|
||||
double s_num = (d_y1-d_y)*d_dx - (d_x1-d_x)*d_dy;
|
||||
|
||||
if (fabs(s_num) < 17179869184.0) // 4<<32
|
||||
if (fabs(s_num) < 17179869184.f) // 4<<32
|
||||
{
|
||||
// Either the point is very near the line, or the segment defining
|
||||
// the line is very short: Do a more expensive test to determine
|
||||
|
|
|
@ -11,7 +11,6 @@ struct FEventInfo
|
|||
struct FEvent
|
||||
{
|
||||
FEvent *Parent, *Left, *Right;
|
||||
enum { RED, BLACK } Color;
|
||||
double Distance;
|
||||
FEventInfo Info;
|
||||
};
|
||||
|
@ -28,7 +27,6 @@ public:
|
|||
|
||||
FEvent *GetNewNode ();
|
||||
void Insert (FEvent *event);
|
||||
void Delete (FEvent *event);
|
||||
FEvent *FindEvent (double distance) const;
|
||||
void DeleteAll ();
|
||||
|
||||
|
@ -39,9 +37,6 @@ private:
|
|||
FEvent *Root;
|
||||
FEvent *Spare;
|
||||
|
||||
void LeftRotate (FEvent *event);
|
||||
void RightRotate (FEvent *event);
|
||||
void DeleteFixUp (FEvent *event);
|
||||
void DeletionTraverser (FEvent *event);
|
||||
FEvent *Successor (FEvent *event) const;
|
||||
FEvent *Predecessor (FEvent *event) const;
|
||||
|
|
|
@ -27,7 +27,6 @@ FEventTree::FEventTree ()
|
|||
: Root (&Nil), Spare (NULL)
|
||||
{
|
||||
memset (&Nil, 0, sizeof(Nil));
|
||||
Nil.Color = FEvent::BLACK;
|
||||
}
|
||||
|
||||
FEventTree::~FEventTree ()
|
||||
|
@ -61,56 +60,6 @@ void FEventTree::DeletionTraverser (FEvent *node)
|
|||
}
|
||||
}
|
||||
|
||||
void FEventTree::LeftRotate (FEvent *x)
|
||||
{
|
||||
FEvent *y = x->Right;
|
||||
x->Right = y->Left;
|
||||
if (y->Left != &Nil)
|
||||
{
|
||||
y->Left->Parent = x;
|
||||
}
|
||||
y->Parent = x->Parent;
|
||||
if (x->Parent == &Nil)
|
||||
{
|
||||
Root = y;
|
||||
}
|
||||
else if (x == x->Parent->Left)
|
||||
{
|
||||
x->Parent->Left = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
x->Parent->Right = y;
|
||||
}
|
||||
y->Left = x;
|
||||
x->Parent = y;
|
||||
}
|
||||
|
||||
void FEventTree::RightRotate (FEvent *x)
|
||||
{
|
||||
FEvent *y = x->Left;
|
||||
x->Left = y->Right;
|
||||
if (y->Right != &Nil)
|
||||
{
|
||||
y->Right->Parent = x;
|
||||
}
|
||||
y->Parent = x->Parent;
|
||||
if (x->Parent == &Nil)
|
||||
{
|
||||
Root = y;
|
||||
}
|
||||
else if (x == x->Parent->Left)
|
||||
{
|
||||
x->Parent->Left = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
x->Parent->Right = y;
|
||||
}
|
||||
y->Right = x;
|
||||
x->Parent = y;
|
||||
}
|
||||
|
||||
FEvent *FEventTree::GetNewNode ()
|
||||
{
|
||||
FEvent *node;
|
||||
|
@ -159,176 +108,6 @@ void FEventTree::Insert (FEvent *z)
|
|||
}
|
||||
z->Left = &Nil;
|
||||
z->Right = &Nil;
|
||||
// printf ("Inserted distance %g, vertex %d, seg %d\n",
|
||||
// sqrt(z->Distance/4294967296.0), z->Info.Vertex, z->Info.FrontSeg);
|
||||
|
||||
z->Color = FEvent::RED;
|
||||
while (z != Root && z->Parent->Color == FEvent::RED)
|
||||
{
|
||||
if (z->Parent == z->Parent->Parent->Left)
|
||||
{
|
||||
y = z->Parent->Parent->Right;
|
||||
if (y->Color == FEvent::RED)
|
||||
{
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
y->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
z = z->Parent->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z == z->Parent->Right)
|
||||
{
|
||||
z = z->Parent;
|
||||
LeftRotate (z);
|
||||
}
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
RightRotate (z->Parent->Parent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y = z->Parent->Parent->Left;
|
||||
if (y->Color == FEvent::RED)
|
||||
{
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
y->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
z = z->Parent->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z == z->Parent->Left)
|
||||
{
|
||||
z = z->Parent;
|
||||
RightRotate (z);
|
||||
}
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
LeftRotate (z->Parent->Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
Root->Color = FEvent::BLACK;
|
||||
}
|
||||
|
||||
void FEventTree::Delete (FEvent *z)
|
||||
{
|
||||
FEvent *x, *y;
|
||||
|
||||
if (z->Left == &Nil || z->Right == &Nil)
|
||||
{
|
||||
y = z;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = Successor (z);
|
||||
}
|
||||
if (y->Left != &Nil)
|
||||
{
|
||||
x = y->Left;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y->Right;
|
||||
}
|
||||
x->Parent = y->Parent;
|
||||
if (y->Parent == &Nil)
|
||||
{
|
||||
Root = x;
|
||||
}
|
||||
else if (y == y->Parent->Left)
|
||||
{
|
||||
y->Parent->Left = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->Parent->Right = x;
|
||||
}
|
||||
if (y != z)
|
||||
{
|
||||
z->Distance = y->Distance;
|
||||
z->Info = y->Info;
|
||||
}
|
||||
if (y->Color == FEvent::BLACK)
|
||||
{
|
||||
DeleteFixUp (x);
|
||||
}
|
||||
|
||||
y->Left = Spare;
|
||||
Spare = y;
|
||||
}
|
||||
|
||||
void FEventTree::DeleteFixUp (FEvent *x)
|
||||
{
|
||||
FEvent *w;
|
||||
|
||||
while (x != Root && x->Color == FEvent::BLACK)
|
||||
{
|
||||
if (x == x->Parent->Left)
|
||||
{
|
||||
w = x->Parent->Right;
|
||||
if (w->Color == FEvent::RED)
|
||||
{
|
||||
w->Color = FEvent::BLACK;
|
||||
x->Parent->Color = FEvent::RED;
|
||||
LeftRotate (x->Parent);
|
||||
w = x->Parent->Right;
|
||||
}
|
||||
if (w->Left->Color == FEvent::BLACK && w->Right->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Color = FEvent::RED;
|
||||
x = x->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->Right->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Left->Color = FEvent::BLACK;
|
||||
w->Color = FEvent::RED;
|
||||
RightRotate (w);
|
||||
w = x->Parent->Right;
|
||||
}
|
||||
w->Color = x->Parent->Color;
|
||||
x->Parent->Color = FEvent::BLACK;
|
||||
w->Right->Color = FEvent::BLACK;
|
||||
LeftRotate (x->Parent);
|
||||
x = Root;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
w = x->Parent->Left;
|
||||
if (w->Color == FEvent::RED)
|
||||
{
|
||||
w->Color = FEvent::BLACK;
|
||||
x->Parent->Color = FEvent::RED;
|
||||
RightRotate (x->Parent);
|
||||
w = x->Parent->Left;
|
||||
}
|
||||
if (w->Right->Color == FEvent::BLACK && w->Left->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Color = FEvent::RED;
|
||||
x = x->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->Left->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Right->Color = FEvent::BLACK;
|
||||
w->Color = FEvent::RED;
|
||||
LeftRotate (w);
|
||||
w = x->Parent->Left;
|
||||
}
|
||||
w->Color = x->Parent->Color;
|
||||
x->Parent->Color = FEvent::BLACK;
|
||||
w->Left->Color = FEvent::BLACK;
|
||||
RightRotate (x->Parent);
|
||||
x = Root;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FEvent *FEventTree::Successor (FEvent *event) const
|
||||
|
@ -420,7 +199,7 @@ void FEventTree::PrintTree (const FEvent *event) const
|
|||
{
|
||||
PrintTree (event->Left);
|
||||
}
|
||||
printf (" Color %s, distance %g, vertex %d, seg %u\n", event->Color ? "BLACK" : " RED ",
|
||||
printf (" Distance %g, vertex %d, seg %u\n",
|
||||
sqrt(event->Distance/4294967296.0), event->Info.Vertex, event->Info.FrontSeg);
|
||||
if (event->Right != &Nil)
|
||||
{
|
||||
|
|
|
@ -236,8 +236,7 @@ void FNodeBuilder::GroupSegPlanes ()
|
|||
|
||||
D(printf ("%d planes from %d segs\n", planenum, Segs.Size()));
|
||||
|
||||
planenum = (planenum+7)/8;
|
||||
PlaneChecked.Reserve (planenum);
|
||||
PlaneChecked.Reserve ((planenum + 7) / 8);
|
||||
}
|
||||
|
||||
// Find "loops" of segs surrounding polyobject's origin. Note that a polyobject's origin
|
||||
|
|
Loading…
Reference in a new issue