- floatified portals.cpp and most of p_maputl.cpp.

This commit is contained in:
Christoph Oelckers 2016-03-31 16:52:25 +02:00
commit 9412ce45d6
25 changed files with 427 additions and 848 deletions

View file

@ -46,8 +46,8 @@
#include "po_man.h"
static AActor *RoughBlockCheck (AActor *mo, int index, void *);
static int R_PointOnSideSlow(fixed_t x, fixed_t y, node_t *node);
sector_t *P_PointInSectorBuggy(fixed_t x, fixed_t y);
sector_t *P_PointInSectorBuggy(double x, double y);
int P_VanillaPointOnDivlineSide(double x, double y, const divline_t* line);
//==========================================================================
@ -58,13 +58,28 @@ sector_t *P_PointInSectorBuggy(fixed_t x, fixed_t y);
//
//==========================================================================
fixed_t P_AproxDistance (fixed_t dx, fixed_t dy)
int P_AproxDistance (int dx, int dy)
{
dx = abs(dx);
dy = abs(dy);
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
@ -96,69 +111,6 @@ double P_InterceptVector(const divline_t *v2, const divline_t *v1)
return num / den;
}
fixed_t P_InterceptVector (const fdivline_t *v2, const fdivline_t *v1)
{
#if 0 // [RH] Use 64 bit ints, so long divlines don't overflow
SQWORD den = ( ((SQWORD)v1->dy*v2->dx - (SQWORD)v1->dx*v2->dy) >> FRACBITS );
if (den == 0)
return 0; // parallel
SQWORD num = ((SQWORD)(v1->fixX() - v2->fixX())*v1->dy + (SQWORD)(v2->fixY() - v1->fixY())*v1->dx);
return (fixed_t)(num / den);
#elif 0 // This is the original Doom version
fixed_t frac;
fixed_t num;
fixed_t den;
den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
if (den == 0)
return 0;
// I_Error ("P_InterceptVector: parallel");
num =
FixedMul ( (v1->fixX() - v2->fixX())>>8 ,v1->dy )
+FixedMul ( (v2->fixY() - v1->fixY())>>8, v1->dx );
frac = FixedDiv (num , den);
return frac;
#else // optimized version of the float debug version. A lot faster on modern systens.
double frac;
double num;
double den;
// There's no need to divide by FRACUNIT here.
// At the end both num and den will contain a factor
// 1/(FRACUNIT*FRACUNIT) so they'll cancel each other out.
double v1x = (double)v1->x;
double v1y = (double)v1->y;
double v1dx = (double)v1->dx;
double v1dy = (double)v1->dy;
double v2x = (double)v2->x;
double v2y = (double)v2->y;
double v2dx = (double)v2->dx;
double v2dy = (double)v2->dy;
den = v1dy*v2dx - v1dx*v2dy;
if (den == 0)
return 0; // parallel
num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;
frac = num / den;
return FLOAT2FIXED(frac);
#endif
}
//==========================================================================
//
// P_LineOpening
@ -374,7 +326,7 @@ void AActor::UnlinkFromWorld ()
bool AActor::FixMapthingPos()
{
sector_t *secstart = P_PointInSectorBuggy(_f_X(), _f_Y());
sector_t *secstart = P_PointInSectorBuggy(X(), Y());
int blockx = GetBlockX(X());
int blocky = GetBlockY(Y());
@ -472,12 +424,12 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector)
}
else
{
sector = P_PointInSectorBuggy(_f_X(), _f_Y());
sector = P_PointInSectorBuggy(X(), Y());
}
}
Sector = sector;
subsector = R_PointInSubsector(_f_X(), _f_Y()); // this is from the rendering nodes, not the gameplay nodes!
subsector = R_PointInSubsector(Pos()); // this is from the rendering nodes, not the gameplay nodes!
if (!(flags & MF_NOSECTOR))
{
@ -515,7 +467,7 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector)
{
FPortalGroupArray check(FPortalGroupArray::PGA_NoSectorPortals);
P_CollectConnectedGroups(Sector->PortalGroup, _f_Pos(), _f_Top(), _f_radius(), check);
P_CollectConnectedGroups(Sector->PortalGroup, Pos(), Top(), radius, check);
for (int i = -1; i < (int)check.Size(); i++)
{
@ -756,28 +708,26 @@ line_t *FBlockLinesIterator::Next()
//
//===========================================================================
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius)
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, double checkradius)
: checklist(check)
{
checkpoint = origin->_f_Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->_f_Top(), checkradius, checklist);
checkpoint.z = checkradius == -1? origin->_f_radius() : checkradius;
checkpoint = origin->Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
checkpoint.Z = checkradius == -1? origin->radius : checkradius;
basegroup = origin->Sector->PortalGroup;
startsector = origin->Sector;
Reset();
}
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, sector_t *newsec)
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, double checkx, double checky, double checkz, double checkh, double checkradius, sector_t *newsec)
: checklist(check)
{
checkpoint.x = checkx;
checkpoint.y = checky;
checkpoint.z = checkz;
checkpoint = { checkx, checky, checkz };
if (newsec == NULL) newsec = P_PointInSector(checkx, checky);
startsector = newsec;
basegroup = newsec->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.z = checkradius;
checkpoint.Z = checkradius;
Reset();
}
@ -787,7 +737,7 @@ FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, fix
//
//===========================================================================
bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
bool FMultiBlockLinesIterator::GoUp(double x, double y)
{
if (continueup)
{
@ -808,7 +758,7 @@ bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
//
//===========================================================================
bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
bool FMultiBlockLinesIterator::GoDown(double x, double y)
{
if (continuedown)
{
@ -835,10 +785,8 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
if (line != NULL)
{
item->line = line;
item->position.x = offset.x;
item->position.y = offset.y;
// same as above in floating point. This is here so that this stuff can be converted piece by piece.
item->Position = { FIXED2DBL(item->position.x), FIXED2DBL(item->position.y), FIXED2DBL(item->position.z) };
item->Position.X = offset.X;
item->Position.Y = offset.Y;
item->portalflags = portalflags;
return true;
}
@ -848,19 +796,19 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
if (portalflags == FFCF_NOFLOOR && nextflags != FPortalGroupArray::UPPER)
{
// if this is the last upper portal in the list, check if we need to go further up to find the real ceiling.
if (GoUp(offset.x, offset.y)) return Next(item);
if (GoUp(offset.X, offset.Y)) return Next(item);
}
else if (portalflags == FFCF_NOCEILING && nextflags != FPortalGroupArray::LOWER)
{
// if this is the last lower portal in the list, check if we need to go further down to find the real floor.
if (GoDown(offset.x, offset.y)) return Next(item);
if (GoDown(offset.X, offset.Y)) return Next(item);
}
if (onlast)
{
cursector = startsector;
// We reached the end of the list. Check if we still need to check up- and downwards.
if (GoUp(checkpoint.x, checkpoint.y) ||
GoDown(checkpoint.x, checkpoint.y))
if (GoUp(checkpoint.X, checkpoint.Y) ||
GoDown(checkpoint.X, checkpoint.Y))
{
return Next(item);
}
@ -894,11 +842,11 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
void FMultiBlockLinesIterator::startIteratorForGroup(int group)
{
offset = Displacements._f_getOffset(basegroup, group);
offset.x += checkpoint.x;
offset.y += checkpoint.y;
cursector = group == startsector->PortalGroup ? startsector : P_PointInSector(offset.x, offset.y);
bbox.setBox(FIXED2FLOAT(offset.x), FIXED2FLOAT(offset.y), FIXED2FLOAT(checkpoint.z));
offset = Displacements.getOffset(basegroup, group);
offset.X += checkpoint.X;
offset.Y += checkpoint.Y;
cursector = group == startsector->PortalGroup ? startsector : P_PointInSector(offset);
bbox.setBox(offset.X, offset.Y, checkpoint.Z);
blockIterator.init(bbox);
}
@ -1025,14 +973,14 @@ AActor *FBlockThingsIterator::Next(bool centeronly)
if (centeronly)
{
// Block boundaries for compatibility mode
fixed_t blockleft = (curx << MAPBLOCKSHIFT) + FLOAT2FIXED(bmaporgx);
fixed_t blockright = blockleft + MAPBLOCKSIZE;
fixed_t blockbottom = (cury << MAPBLOCKSHIFT) + FLOAT2FIXED(bmaporgy);
fixed_t blocktop = blockbottom + MAPBLOCKSIZE;
double blockleft = (curx * MAPBLOCKUNITS) + bmaporgx;
double blockright = blockleft + MAPBLOCKUNITS;
double blockbottom = (cury * MAPBLOCKUNITS) + bmaporgy;
double blocktop = blockbottom + MAPBLOCKUNITS;
// only return actors with the center in this block
if (me->_f_X() >= blockleft && me->_f_X() < blockright &&
me->_f_Y() >= blockbottom && me->_f_Y() < blocktop)
if (me->X() >= blockleft && me->X() < blockright &&
me->Y() >= blockbottom && me->Y() < blocktop)
{
return me;
}
@ -1093,26 +1041,26 @@ AActor *FBlockThingsIterator::Next(bool centeronly)
//
//===========================================================================
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius, bool ignorerestricted)
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, double checkradius, bool ignorerestricted)
: checklist(check)
{
checkpoint = origin->_f_Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->_f_Top(), checkradius, checklist);
checkpoint.z = checkradius == -1? origin->_f_radius() : checkradius;
checkpoint = origin->Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
checkpoint.Z = checkradius == -1? origin->radius : checkradius;
basegroup = origin->Sector->PortalGroup;
Reset();
}
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted, sector_t *newsec)
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec)
: checklist(check)
{
checkpoint.x = checkx;
checkpoint.y = checky;
checkpoint.z = checkz;
checkpoint.X = checkx;
checkpoint.Y = checky;
checkpoint.Z = checkz;
if (newsec == NULL) newsec = P_PointInSector(checkx, checky);
basegroup = newsec->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.z = checkradius;
checkpoint.Z = checkradius;
Reset();
}
@ -1128,11 +1076,8 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
if (thing != NULL)
{
item->thing = thing;
item->position = checkpoint + Displacements._f_getOffset(basegroup, thing->Sector->PortalGroup);
item->Position = checkpoint + Displacements.getOffset(basegroup, thing->Sector->PortalGroup);
item->portalflags = portalflags;
// same as above in floating point. This is here so that this stuff can be converted piece by piece.
item->Position = { FIXED2DBL(item->position.x), FIXED2DBL(item->position.y), FIXED2DBL(item->position.z) };
return true;
}
bool onlast = unsigned(index + 1) >= checklist.Size();
@ -1170,10 +1115,10 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
void FMultiBlockThingsIterator::startIteratorForGroup(int group)
{
fixedvec2 offset = Displacements._f_getOffset(basegroup, group);
offset.x += checkpoint.x;
offset.y += checkpoint.y;
bbox.setBox(FIXED2FLOAT(offset.x), FIXED2FLOAT(offset.y), FIXED2FLOAT(checkpoint.z));
DVector2 offset = Displacements.getOffset(basegroup, group);
offset.X += checkpoint.X;
offset.Y += checkpoint.Y;
bbox.setBox(offset.X, offset.Y, checkpoint.Z);
blockIterator.init(bbox);
}
@ -1220,17 +1165,17 @@ void FPathTraverse::AddLineIntercepts(int bx, int by)
{
int s1;
int s2;
fixed_t frac;
fdivline_t dl;
double frac;
divline_t dl;
// avoid precision problems with two routines
if ( trace.dx > FRACUNIT*16
|| trace.dy > FRACUNIT*16
|| trace.dx < -FRACUNIT*16
|| trace.dy < -FRACUNIT*16)
if ( trace.dx > 16
|| trace.dy > 16
|| trace.dx < -16
|| trace.dy < -16)
{
s1 = P_PointOnDivlineSide (ld->v1->fixX(), ld->v1->fixY(), &trace);
s2 = P_PointOnDivlineSide (ld->v2->fixX(), ld->v2->fixY(), &trace);
s1 = P_PointOnDivlineSideCompat (ld->v1->fX(), ld->v1->fY(), &trace);
s2 = P_PointOnDivlineSideCompat (ld->v2->fX(), ld->v2->fY(), &trace);
}
else
{
@ -1244,7 +1189,7 @@ void FPathTraverse::AddLineIntercepts(int bx, int by)
P_MakeDivline (ld, &dl);
frac = P_InterceptVector (&trace, &dl);
if (frac < startfrac || frac > FRACUNIT) continue; // behind source or beyond end point
if (frac < Startfrac || frac > 1.) continue; // behind source or beyond end point
intercept_t newintercept;
@ -1271,7 +1216,7 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
while ((thing = it.Next(compatible)))
{
int numfronts = 0;
fdivline_t line;
divline_t line;
int i;
@ -1287,69 +1232,69 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
switch (i)
{
case 0: // Top edge
line.x = thing->_f_X() + thing->_f_radius();
line.y = thing->_f_Y() + thing->_f_radius();
line.dx = -thing->_f_radius() * 2;
line.x = thing->X() + thing->radius;
line.y = thing->Y() + thing->radius;
line.dx = -thing->radius * 2;
line.dy = 0;
break;
case 1: // Right edge
line.x = thing->_f_X() + thing->_f_radius();
line.y = thing->_f_Y() - thing->_f_radius();
line.x = thing->X() + thing->radius;
line.y = thing->Y() - thing->radius;
line.dx = 0;
line.dy = thing->_f_radius() * 2;
line.dy = thing->radius * 2;
break;
case 2: // Bottom edge
line.x = thing->_f_X() - thing->_f_radius();
line.y = thing->_f_Y() - thing->_f_radius();
line.dx = thing->_f_radius() * 2;
line.x = thing->X() - thing->radius;
line.y = thing->Y() - thing->radius;
line.dx = thing->radius * 2;
line.dy = 0;
break;
case 3: // Left edge
line.x = thing->_f_X() - thing->_f_radius();
line.y = thing->_f_Y() + thing->_f_radius();
line.x = thing->X() - thing->radius;
line.y = thing->Y() + thing->radius;
line.dx = 0;
line.dy = thing->_f_radius() * -2;
line.dy = thing->radius * -2;
break;
}
// Check if this side is facing the trace origin
if (P_PointOnDivlineSidePrecise (trace.x, trace.y, &line) == 0)
if (P_PointOnDivlineSide (trace.x, trace.y, &line) == 0)
{
numfronts++;
// If it is, see if the trace crosses it
if (P_PointOnDivlineSidePrecise (line.x, line.y, &trace) !=
P_PointOnDivlineSidePrecise (line.x + line.dx, line.y + line.dy, &trace))
if (P_PointOnDivlineSide (line.x, line.y, &trace) !=
P_PointOnDivlineSide (line.x + line.dx, line.y + line.dy, &trace))
{
// It's a hit
fixed_t frac = P_InterceptVector (&trace, &line);
if (frac < startfrac)
double frac = P_InterceptVector (&trace, &line);
if (frac < Startfrac)
{ // behind source
if (startfrac > 0)
if (Startfrac > 0)
{
// check if the trace starts within this actor
switch (i)
{
case 0:
line.y -= 2 * thing->_f_radius();
line.y -= 2 * thing->radius;
break;
case 1:
line.x -= 2 * thing->_f_radius();
line.x -= 2 * thing->radius;
break;
case 2:
line.y += 2 * thing->_f_radius();
line.y += 2 * thing->radius;
break;
case 3:
line.x += 2 * thing->_f_radius();
line.x += 2 * thing->radius;
break;
}
fixed_t frac2 = P_InterceptVector(&trace, &line);
if (frac2 >= startfrac) goto addit;
double frac2 = P_InterceptVector(&trace, &line);
if (frac2 >= Startfrac) goto addit;
}
continue;
}
@ -1380,33 +1325,33 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
else
{
// Old code for compatibility purposes
fixed_t x1, y1, x2, y2;
double x1, y1, x2, y2;
int s1, s2;
fdivline_t dl;
fixed_t frac;
divline_t dl;
double frac;
bool tracepositive = (trace.dx ^ trace.dy)>0;
bool tracepositive = (trace.dx * trace.dy)>0;
// check a corner to corner crossection for hit
if (tracepositive)
{
x1 = thing->_f_X() - thing->_f_radius();
y1 = thing->_f_Y() + thing->_f_radius();
x1 = thing->X() - thing->radius;
y1 = thing->Y() + thing->radius;
x2 = thing->_f_X() + thing->_f_radius();
y2 = thing->_f_Y() - thing->_f_radius();
x2 = thing->X() + thing->radius;
y2 = thing->Y() - thing->radius;
}
else
{
x1 = thing->_f_X() - thing->_f_radius();
y1 = thing->_f_Y() - thing->_f_radius();
x1 = thing->X() - thing->radius;
y1 = thing->Y() - thing->radius;
x2 = thing->_f_X() + thing->_f_radius();
y2 = thing->_f_Y() + thing->_f_radius();
x2 = thing->X() + thing->radius;
y2 = thing->Y() + thing->radius;
}
s1 = P_PointOnDivlineSide (x1, y1, &trace);
s2 = P_PointOnDivlineSide (x2, y2, &trace);
s1 = P_PointOnDivlineSideCompat (x1, y1, &trace);
s2 = P_PointOnDivlineSideCompat (x2, y2, &trace);
if (s1 != s2)
{
@ -1417,7 +1362,7 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
frac = P_InterceptVector (&trace, &dl);
if (frac >= startfrac)
if (frac >= Startfrac)
{
intercept_t newintercept;
newintercept.frac = frac;
@ -1442,7 +1387,7 @@ intercept_t *FPathTraverse::Next()
{
intercept_t *in = NULL;
fixed_t dist = FIXED_MAX;
double dist = FIXED_MAX;
for (unsigned scanpos = intercept_index; scanpos < intercepts.Size (); scanpos++)
{
intercept_t *scan = &intercepts[scanpos];
@ -1450,11 +1395,10 @@ intercept_t *FPathTraverse::Next()
{
dist = scan->frac;
in = scan;
in->Frac = FIXED2FLOAT(in->frac);
}
}
if (dist > FRACUNIT || in == NULL) return NULL; // checked everything in range
if (dist > 1. || in == NULL) return NULL; // checked everything in range
in->done = true;
return in;
}
@ -1466,19 +1410,12 @@ intercept_t *FPathTraverse::Next()
//
//===========================================================================
void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, fixed_t startfrac)
void FPathTraverse::init(double x1, double y1, double x2, double y2, int flags, double startfrac)
{
fixed_t xt1, xt2;
fixed_t yt1, yt2;
long long _x1, _x2, _y1, _y2;
fixed_t xstep;
fixed_t ystep;
fixed_t partialx, partialy;
fixed_t xintercept;
fixed_t yintercept;
double xt1, yt1, xt2, yt2;
double xstep, ystep;
double partialx, partialy;
double xintercept, yintercept;
int mapx;
int mapy;
@ -1502,8 +1439,8 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
}
if (startfrac > 0)
{
fixed_t startdx = FixedMul(trace.dx, startfrac);
fixed_t startdy = FixedMul(trace.dy, startfrac);
double startdx = trace.dx * startfrac;
double startdy = trace.dy * startfrac;
x1 += startdx;
y1 += startdy;
@ -1514,110 +1451,95 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
validcount++;
intercept_index = intercepts.Size();
this->startfrac = startfrac;
fixed_t _f_bmaporgx = FLOAT2FIXED(bmaporgx);
fixed_t _f_bmaporgy = FLOAT2FIXED(bmaporgy);
if ( ((x1-_f_bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
x1 += FRACUNIT; // don't side exactly on a line
if ( ((y1-_f_bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
y1 += FRACUNIT; // don't side exactly on a line
_x1 = (long long)x1 - _f_bmaporgx;
_y1 = (long long)y1 - _f_bmaporgy;
x1 -= _f_bmaporgx;
y1 -= _f_bmaporgy;
xt1 = int(_x1 >> MAPBLOCKSHIFT);
yt1 = int(_y1 >> MAPBLOCKSHIFT);
Startfrac = startfrac;
if (flags & PT_DELTA)
{
_x2 = _x1 + x2;
_y2 = _y1 + y2;
xt2 = int(_x2 >> MAPBLOCKSHIFT);
yt2 = int(_y2 >> MAPBLOCKSHIFT);
x2 = (int)_x2;
y2 = (int)_y2;
}
else
{
_x2 = (long long)x2 - _f_bmaporgx;
_y2 = (long long)y2 - _f_bmaporgy;
x2 -= _f_bmaporgx;
y2 -= _f_bmaporgy;
xt2 = int(_x2 >> MAPBLOCKSHIFT);
yt2 = int(_y2 >> MAPBLOCKSHIFT);
x2 += x1;
y2 += y2;
}
if (xt2 > xt1)
x1 -= bmaporgx;
y1 -= bmaporgy;
xt1 = x1 / MAPBLOCKUNITS;
yt1 = y1 / MAPBLOCKUNITS;
x2 -= bmaporgx;
y2 -= bmaporgy;
xt2 = x2 / MAPBLOCKUNITS;
yt2 = y2 / MAPBLOCKUNITS;
mapx = int(xt1);
mapy = int(yt1);
int mapex = int(xt2);
int mapey = int(yt2);
if (mapex > mapx)
{
mapxstep = 1;
partialx = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
ystep = FixedDiv (y2-y1,abs(x2-x1));
partialx = xs_CeilToInt(xt1) - xt1;
ystep = (y2 - y1) / fabs(x2 - x1);
}
else if (xt2 < xt1)
else if (mapex < mapx)
{
mapxstep = -1;
partialx = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
ystep = FixedDiv (y2-y1,abs(x2-x1));
partialx = xt1 - xs_FloorToInt(xt1);
ystep = (y2 - y1) / fabs(x2 - x1);
}
else
{
mapxstep = 0;
partialx = FRACUNIT;
ystep = 256*FRACUNIT;
}
yintercept = int(_y1>>MAPBTOFRAC) + FixedMul (partialx, ystep);
partialx = 1.;
ystep = 256;
}
yintercept = yt1 + partialx * ystep;
if (yt2 > yt1)
if (mapey > mapy)
{
mapystep = 1;
partialy = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
xstep = FixedDiv (x2-x1,abs(y2-y1));
partialy = xs_CeilToInt(yt1) - yt1;
xstep = (x2 - x1) / fabs(y2 - y1);
}
else if (yt2 < yt1)
else if (mapey < mapy)
{
mapystep = -1;
partialy = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
xstep = FixedDiv (x2-x1,abs(y2-y1));
partialy = yt1 - xs_FloorToInt(yt1);
xstep = (x2 - x1) / fabs(y2 - y1);
}
else
{
mapystep = 0;
partialy = FRACUNIT;
xstep = 256*FRACUNIT;
}
xintercept = int(_x1>>MAPBTOFRAC) + FixedMul (partialy, xstep);
partialy = 1;
xstep = 256;
}
xintercept = xt1 + partialy * xstep;
// [RH] Fix for traces that pass only through blockmap corners. In that case,
// xintercept and yintercept can both be set ahead of mapx and mapy, so the
// for loop would never advance anywhere.
if (abs(xstep) == FRACUNIT && abs(ystep) == FRACUNIT)
if (fabs(xstep) == 1. && fabs(ystep) == 1.)
{
if (ystep < 0)
{
partialx = FRACUNIT - partialx;
partialx = 1. - partialx;
}
if (xstep < 0)
{
partialy = FRACUNIT - partialy;
partialy = 1. - partialy;
}
if (partialx == partialy)
{
xintercept = xt1 << FRACBITS;
yintercept = yt1 << FRACBITS;
xintercept = xt1;
yintercept = yt1;
}
}
// Step through map blocks.
// Count is present to prevent a round off error
// from skipping the break statement.
mapx = xt1;
mapy = yt1;
bool compatible = (flags & PT_COMPATIBLE) && (i_compatflags & COMPATF_HITSCAN);
@ -1641,7 +1563,7 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
}
// [RH] Handle corner cases properly instead of pretending they don't exist.
switch ((((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx))
switch (((int(yintercept) == mapy) << 1) | (int(xintercept) == mapx))
{
case 0: // neither xintercept nor yintercept match!
count = 100; // Stop traversing, because somebody screwed up.
@ -1687,10 +1609,6 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
break;
}
}
ftrace.dx = FIXED2DBL(trace.dx);
ftrace.dy = FIXED2DBL(trace.dy);
ftrace.x = FIXED2DBL(trace.x);
ftrace.y = FIXED2DBL(trace.y);
}
//===========================================================================
@ -1704,10 +1622,10 @@ int FPathTraverse::PortalRelocate(intercept_t *in, int flags, DVector3 *optpos)
if (!in->isaline || !in->d.line->isLinePortal()) return false;
if (P_PointOnLineSidePrecise(trace.x, trace.y, in->d.line) == 1) return false;
fixed_t hitx = trace.x;
fixed_t hity = trace.y;
fixed_t endx = trace.x + trace.dx;
fixed_t endy = trace.y + trace.dy;
double hitx = trace.x;
double hity = trace.y;
double endx = trace.x + trace.dx;
double endy = trace.y + trace.dy;
P_TranslatePortalXY(in->d.line, hitx, hity);
P_TranslatePortalXY(in->d.line, endx, endy);
@ -1873,7 +1791,7 @@ static AActor *RoughBlockCheck (AActor *mo, int index, void *param)
//
//==========================================================================
static int R_PointOnSideSlow(fixed_t x, fixed_t y, node_t *node)
static int R_PointOnSideSlow(double x, double y, node_t *node)
{
// [RH] This might have been faster than two multiplies and an
// add on a 386/486, but it certainly isn't on anything newer than that.
@ -1897,8 +1815,8 @@ static int R_PointOnSideSlow(fixed_t x, fixed_t y, node_t *node)
return node->dx > 0;
}
dx = (x - node->x);
dy = (y - node->y);
dx = (FloatToFixed(x) - node->x);
dy = (FloatToFixed(y) - node->y);
// Try to quickly decide by looking at sign bits.
if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000)
@ -1973,16 +1891,18 @@ int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line)
//===========================================================================
//
// P_VanillaPointOnDivlineSide
// P_PointOnDivlineSide() from the initial Doom source code release
// P_PointOnDivlineSideCompat() from the initial Doom source code release
//
//===========================================================================
int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const fdivline_t* line)
int P_VanillaPointOnDivlineSide(double x, double y, const divline_t* line)
{
fixed_t dx;
fixed_t dy;
fixed_t left;
fixed_t right;
int dx;
int dy;
int left;
int right;
int ldx;
int ldy;
if (!line->dx)
{
@ -1999,26 +1919,37 @@ int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const fdivline_t* line)
return line->dx > 0;
}
dx = (x - line->x);
dy = (y - line->y);
// 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 ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
{
if ( (line->dy ^ dx) & 0x80000000 )
if ( (ldy ^ dx) & 0x80000000 )
return 1; // (left is negative)
return 0;
}
left = FixedMul ( line->dy>>8, dx>>8 );
right = FixedMul ( dy>>8 , line->dx>>8 );
left = MulScale16( ldy>>8, dx>>8 );
right = MulScale16( dy>>8 , ldx>>8 );
if (right < left)
return 0; // front side
return 1; // back side
}
sector_t *P_PointInSectorBuggy(fixed_t x, fixed_t y)
//==========================================================================
//
// Use buggy PointOnSide and fix actors that lie on
// lines to compensate for some IWAD maps.
//
//==========================================================================
sector_t *P_PointInSectorBuggy(double x, double y)
{
// single subsector is a special case
if (numgamenodes == 0)