mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 20:43:15 +00:00
- some optimization of FPathTraverse:
* we do not really need compatibility PointOnLineSide here. Unlike the movement code it'd only affect some extreme edge cases. * removed the special case for very short traces. This was a result of the original and very imprecise PointOnLine functions. Since those no longer get used here and floating point precision is a lot higher there is no need for this kind of treatment. * PointOnLine checks for the sides of an actor's bounding box don't need a full PointOnLineSide call, a simple coordinate comparison is fully sufficient, and this can easily be done in the existing switch/case block.
This commit is contained in:
parent
ad13a55f0d
commit
04b0a13bd3
1 changed files with 45 additions and 125 deletions
170
src/p_maputl.cpp
170
src/p_maputl.cpp
|
@ -65,21 +65,6 @@ int P_AproxDistance (int dx, int dy)
|
||||||
return (dx < dy) ? dx+dy-(dx>>1) : dx+dy-(dy>>1);
|
return (dx < dy) ? dx+dy-(dx>>1) : dx+dy-(dy>>1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// P_PointOnDivlineSideCompat
|
|
||||||
//
|
|
||||||
// Returns the fractional intercept point along the first divline
|
|
||||||
// with compatibility flag handling
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
inline int P_PointOnDivlineSideCompat(double x, double y, const divline_t *line)
|
|
||||||
{
|
|
||||||
return (i_compatflags2 & COMPATF2_POINTONLINE)
|
|
||||||
? P_VanillaPointOnDivlineSide(x, y, line) : P_PointOnDivlineSide(x, y, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// P_InterceptVector
|
// P_InterceptVector
|
||||||
|
@ -1168,20 +1153,8 @@ void FPathTraverse::AddLineIntercepts(int bx, int by)
|
||||||
double frac;
|
double frac;
|
||||||
divline_t dl;
|
divline_t dl;
|
||||||
|
|
||||||
// avoid precision problems with two routines
|
s1 = P_PointOnDivlineSide (ld->v1->fX(), ld->v1->fY(), &trace);
|
||||||
if ( trace.dx > 16
|
s2 = P_PointOnDivlineSide (ld->v2->fX(), ld->v2->fY(), &trace);
|
||||||
|| trace.dy > 16
|
|
||||||
|| trace.dx < -16
|
|
||||||
|| trace.dy < -16)
|
|
||||||
{
|
|
||||||
s1 = P_PointOnDivlineSideCompat (ld->v1->fX(), ld->v1->fY(), &trace);
|
|
||||||
s2 = P_PointOnDivlineSideCompat (ld->v2->fX(), ld->v2->fY(), &trace);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s1 = P_PointOnLineSide (trace.x, trace.y, ld);
|
|
||||||
s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s1 == s2) continue; // line isn't crossed
|
if (s1 == s2) continue; // line isn't crossed
|
||||||
|
|
||||||
|
@ -1232,81 +1205,82 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0: // Top edge
|
case 0: // Top edge
|
||||||
line.x = thing->X() + thing->radius;
|
|
||||||
line.y = thing->Y() + thing->radius;
|
line.y = thing->Y() + thing->radius;
|
||||||
|
if (trace.y < line.y) continue;
|
||||||
|
line.x = thing->X() + thing->radius;
|
||||||
line.dx = -thing->radius * 2;
|
line.dx = -thing->radius * 2;
|
||||||
line.dy = 0;
|
line.dy = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // Right edge
|
case 1: // Right edge
|
||||||
line.x = thing->X() + thing->radius;
|
line.x = thing->X() + thing->radius;
|
||||||
|
if (trace.x < line.x) continue;
|
||||||
line.y = thing->Y() - thing->radius;
|
line.y = thing->Y() - thing->radius;
|
||||||
line.dx = 0;
|
line.dx = 0;
|
||||||
line.dy = thing->radius * 2;
|
line.dy = thing->radius * 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // Bottom edge
|
case 2: // Bottom edge
|
||||||
line.x = thing->X() - thing->radius;
|
|
||||||
line.y = thing->Y() - thing->radius;
|
line.y = thing->Y() - thing->radius;
|
||||||
|
if (trace.y > line.y) continue;
|
||||||
|
line.x = thing->X() - thing->radius;
|
||||||
line.dx = thing->radius * 2;
|
line.dx = thing->radius * 2;
|
||||||
line.dy = 0;
|
line.dy = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // Left edge
|
case 3: // Left edge
|
||||||
line.x = thing->X() - thing->radius;
|
line.x = thing->X() - thing->radius;
|
||||||
|
if (trace.x > line.x) continue;
|
||||||
line.y = thing->Y() + thing->radius;
|
line.y = thing->Y() + thing->radius;
|
||||||
line.dx = 0;
|
line.dx = 0;
|
||||||
line.dy = thing->radius * -2;
|
line.dy = thing->radius * -2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Check if this side is facing the trace origin
|
// Check if this side is facing the trace origin
|
||||||
if (P_PointOnDivlineSide (trace.x, trace.y, &line) == 0)
|
numfronts++;
|
||||||
|
|
||||||
|
// If it is, see if the trace crosses it
|
||||||
|
if (P_PointOnDivlineSide (line.x, line.y, &trace) !=
|
||||||
|
P_PointOnDivlineSide (line.x + line.dx, line.y + line.dy, &trace))
|
||||||
{
|
{
|
||||||
numfronts++;
|
// It's a hit
|
||||||
|
double frac = P_InterceptVector (&trace, &line);
|
||||||
// If it is, see if the trace crosses it
|
if (frac < Startfrac)
|
||||||
if (P_PointOnDivlineSide (line.x, line.y, &trace) !=
|
{ // behind source
|
||||||
P_PointOnDivlineSide (line.x + line.dx, line.y + line.dy, &trace))
|
if (Startfrac > 0)
|
||||||
{
|
{
|
||||||
// It's a hit
|
// check if the trace starts within this actor
|
||||||
double frac = P_InterceptVector (&trace, &line);
|
switch (i)
|
||||||
if (frac < Startfrac)
|
|
||||||
{ // behind source
|
|
||||||
if (Startfrac > 0)
|
|
||||||
{
|
{
|
||||||
// check if the trace starts within this actor
|
case 0:
|
||||||
switch (i)
|
line.y -= 2 * thing->radius;
|
||||||
{
|
break;
|
||||||
case 0:
|
|
||||||
line.y -= 2 * thing->radius;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
line.x -= 2 * thing->radius;
|
line.x -= 2 * thing->radius;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
line.y += 2 * thing->radius;
|
line.y += 2 * thing->radius;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
line.x += 2 * thing->radius;
|
line.x += 2 * thing->radius;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
double frac2 = P_InterceptVector(&trace, &line);
|
|
||||||
if (frac2 >= Startfrac) goto addit;
|
|
||||||
}
|
}
|
||||||
continue;
|
double frac2 = P_InterceptVector(&trace, &line);
|
||||||
|
if (frac2 >= Startfrac) goto addit;
|
||||||
}
|
}
|
||||||
addit:
|
|
||||||
intercept_t newintercept;
|
|
||||||
newintercept.frac = frac;
|
|
||||||
newintercept.isaline = false;
|
|
||||||
newintercept.done = false;
|
|
||||||
newintercept.d.thing = thing;
|
|
||||||
intercepts.Push (newintercept);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
addit:
|
||||||
|
intercept_t newintercept;
|
||||||
|
newintercept.frac = frac;
|
||||||
|
newintercept.isaline = false;
|
||||||
|
newintercept.done = false;
|
||||||
|
newintercept.d.thing = thing;
|
||||||
|
intercepts.Push (newintercept);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1350,8 +1324,8 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
|
||||||
y2 = thing->Y() + thing->radius;
|
y2 = thing->Y() + thing->radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
s1 = P_PointOnDivlineSideCompat (x1, y1, &trace);
|
s1 = P_PointOnDivlineSide (x1, y1, &trace);
|
||||||
s2 = P_PointOnDivlineSideCompat (x2, y2, &trace);
|
s2 = P_PointOnDivlineSide (x2, y2, &trace);
|
||||||
|
|
||||||
if (s1 != s2)
|
if (s1 != s2)
|
||||||
{
|
{
|
||||||
|
@ -1894,60 +1868,6 @@ int P_VanillaPointOnLineSide(double x, double y, const line_t* line)
|
||||||
return 1; // back side
|
return 1; // back side
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// P_VanillaPointOnDivlineSide
|
|
||||||
// P_PointOnDivlineSideCompat() from the initial Doom source code release
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
int P_VanillaPointOnDivlineSide(double x, double y, const divline_t* line)
|
|
||||||
{
|
|
||||||
int dx;
|
|
||||||
int dy;
|
|
||||||
int left;
|
|
||||||
int right;
|
|
||||||
int ldx;
|
|
||||||
int ldy;
|
|
||||||
|
|
||||||
if (!line->dx)
|
|
||||||
{
|
|
||||||
if (x <= line->x)
|
|
||||||
return line->dy > 0;
|
|
||||||
|
|
||||||
return line->dy < 0;
|
|
||||||
}
|
|
||||||
if (!line->dy)
|
|
||||||
{
|
|
||||||
if (y <= line->y)
|
|
||||||
return line->dx < 0;
|
|
||||||
|
|
||||||
return line->dx > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is supposed to be compatible so the rest needs to be done
|
|
||||||
// with the same broken fixed point checks as the original
|
|
||||||
dx = FloatToFixed(x - line->x);
|
|
||||||
dy = FloatToFixed(y - line->y);
|
|
||||||
ldx = FloatToFixed(line->dx);
|
|
||||||
ldy = FloatToFixed(line->dy);
|
|
||||||
|
|
||||||
// try to quickly decide by looking at sign bits
|
|
||||||
if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
|
|
||||||
{
|
|
||||||
if ( (ldy ^ dx) & 0x80000000 )
|
|
||||||
return 1; // (left is negative)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
left = MulScale16( ldy>>8, dx>>8 );
|
|
||||||
right = MulScale16( dy>>8 , ldx>>8 );
|
|
||||||
|
|
||||||
if (right < left)
|
|
||||||
return 0; // front side
|
|
||||||
return 1; // back side
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Use buggy PointOnSide and fix actors that lie on
|
// Use buggy PointOnSide and fix actors that lie on
|
||||||
|
|
Loading…
Reference in a new issue