Fall back to old algorithm when on the line

This commit is contained in:
Gustaf Alhäll 2024-12-15 13:24:54 +01:00
parent a90f495b42
commit 3c39edc1ef
2 changed files with 60 additions and 2 deletions

View file

@ -246,6 +246,55 @@ static void FlipCam2_OnChange(void)
SendWeaponPref2();
}
//
// R_PointOnSide
// Traverse BSP (sub) tree,
// check point against partition plane.
// Returns side 0 (front) or 1 (back).
//
// killough 5/2/98: reformatted
//
INT32 R_OldPointOnSide(fixed_t x, fixed_t y, node_t *restrict node)
{
if (!node->dx)
return x <= node->x ? node->dy > 0 : node->dy < 0;
if (!node->dy)
return y <= node->y ? node->dx < 0 : node->dx > 0;
fixed_t dx = (x >> 1) - (node->x >> 1);
fixed_t dy = (y >> 1) - (node->y >> 1);
// Try to quickly decide by looking at sign bits.
// also use a mask to avoid branch prediction
INT32 mask = (node->dy ^ node->dx ^ dx ^ dy) >> 31;
return (mask & ((node->dy ^ dx) < 0)) | // (left is negative)
(~mask & (FixedMul(dy, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, dx)));
}
// killough 5/2/98: reformatted
INT32 R_OldPointOnSegSide(fixed_t x, fixed_t y, seg_t *line)
{
fixed_t lx = line->v1->x;
fixed_t ly = line->v1->y;
fixed_t ldx = line->v2->x - lx;
fixed_t ldy = line->v2->y - ly;
if (!ldx)
return x <= lx ? ldy > 0 : ldy < 0;
if (!ldy)
return y <= ly ? ldx < 0 : ldx > 0;
fixed_t dx = (x >> 1) - (lx >> 1);
fixed_t dy = (y >> 1) - (ly >> 1);
// Try to quickly decide by looking at sign bits.
if ((ldy ^ ldx ^ dx ^ dy) < 0)
return (ldy ^ dx) < 0; // (left is negative)
return FixedMul(dy, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, dx);
}
//
// R_PointToAngle
// To get a global angle from cartesian coordinates,

View file

@ -71,11 +71,17 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
// There a 0-31, i.e. 32 LUT in the COLORMAP lump.
#define NUMCOLORMAPS 32
INT32 R_OldPointOnSide(fixed_t x, fixed_t y, node_t *node);
INT32 R_OldPointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
// Utility functions.
static inline INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node)
{
// use cross product to determine side quickly
return ((INT64)y - node->y) * node->dx - ((INT64)x - node->x) * node->dy > 0;
INT64 v = ((INT64)y - node->y) * node->dx - ((INT64)x - node->x) * node->dy;
if (v == 0) // if we're on the line, use the old algorithm
return R_OldPointOnSide(x, y, node);
return v > 0;
}
static inline INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line)
@ -86,7 +92,10 @@ static inline INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line)
fixed_t ldy = line->v2->y - ly;
// use cross product to determine side quickly
return ((INT64)y - ly) * ldx - ((INT64)x - lx) * ldy > 0;
INT64 v = ((INT64)y - ly) * ldx - ((INT64)x - lx) * ldy > 0;
if (v == 0) // if we're on the line, use the old algorithm
return R_OldPointOnSegSide(x, y, line);
return v > 0;
}
angle_t R_PointToAngle(fixed_t x, fixed_t y);