mirror of
https://github.com/fabiangreffrath/woof.git
synced 2025-09-24 21:38:39 -04:00
fix rendering glitches (#73)
This commit introduces: * Vertex coordinates only used for rendering. These get moved in P_RemoveSlimeTrails(), the actual vertex coordinates are moved only if not in compatibility mode, and the rendering coordinates are moved back to their original location if a Linguortal is detected. * Seg lengths and angles only used for rendering. These get recalculated after the vertices were moved. * A fix for the "Long Line Wobble" based on the seg lengths introduced above. * An overflow-safe variant of SlopeDiv(). This is only used in R_PointToAngleCrispy(), which in turn is an overflow-safe variant of R_PointToAngle(), which in turn is only used for rendering in R_CheckBBox(), R_AddLine() and P_SegLengthsAngles(). * Fixes for the Automap to cope with huge level dimensions which span the entire INT range. All of the above fix the rendering glitches found in extreme maps such as e.g. planisf2. They were taken from Crispy Doom (and thus mostly from PrBoom+), where they have been introduced years ago and have proven to work. Fixes #70
This commit is contained in:
parent
1892141334
commit
719c988433
@ -100,8 +100,9 @@ extern int joybautomap;
|
||||
#define M_ZOOMOUT ((int) (FRACUNIT/1.02))
|
||||
|
||||
// translates between frame-buffer and map distances
|
||||
#define FTOM(x) FixedMul(((x)<<16),scale_ftom)
|
||||
#define MTOF(x) (FixedMul((x),scale_mtof)>>16)
|
||||
// [FG] fix int overflow that causes map and grid lines to disappear
|
||||
#define FTOM(x) ((((int64_t)(x)<<16)*scale_ftom)>>16)
|
||||
#define MTOF(x) ((((int64_t)(x)*scale_mtof)>>16)>>16)
|
||||
// translates between frame-buffer and map coordinates
|
||||
#define CXMTOF(x) (f_x + MTOF((x)-m_x))
|
||||
#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y)))
|
||||
@ -235,14 +236,14 @@ static mpoint_t m_paninc; // how far the window pans each tic (map coords)
|
||||
static fixed_t mtof_zoommul; // how far the window zooms each tic (map coords)
|
||||
static fixed_t ftom_zoommul; // how far the window zooms each tic (fb coords)
|
||||
|
||||
static fixed_t m_x, m_y; // LL x,y window location on the map (map coords)
|
||||
static fixed_t m_x2, m_y2; // UR x,y window location on the map (map coords)
|
||||
static int64_t m_x, m_y; // LL x,y window location on the map (map coords)
|
||||
static int64_t m_x2, m_y2; // UR x,y window location on the map (map coords)
|
||||
|
||||
//
|
||||
// width/height of window on map (map coords)
|
||||
//
|
||||
static fixed_t m_w;
|
||||
static fixed_t m_h;
|
||||
static int64_t m_w;
|
||||
static int64_t m_h;
|
||||
|
||||
// based on level size
|
||||
static fixed_t min_x;
|
||||
@ -262,8 +263,8 @@ static fixed_t min_scale_mtof; // used to tell when to stop zooming out
|
||||
static fixed_t max_scale_mtof; // used to tell when to stop zooming in
|
||||
|
||||
// old stuff for recovery later
|
||||
static fixed_t old_m_w, old_m_h;
|
||||
static fixed_t old_m_x, old_m_y;
|
||||
static int64_t old_m_w, old_m_h;
|
||||
static int64_t old_m_x, old_m_y;
|
||||
|
||||
// old location used by the Follower routine
|
||||
static mpoint_t f_oldloc;
|
||||
@ -433,8 +434,9 @@ void AM_findMinMaxBoundaries(void)
|
||||
max_y = vertexes[i].y;
|
||||
}
|
||||
|
||||
max_w = max_x - min_x;
|
||||
max_h = max_y - min_y;
|
||||
// [FG] cope with huge level dimensions which span the entire INT range
|
||||
max_w = max_x/2 - min_x/2;
|
||||
max_h = max_y/2 - min_y/2;
|
||||
|
||||
min_w = 2*PLAYERRADIUS; // const? never changed?
|
||||
min_h = 2*PLAYERRADIUS;
|
||||
@ -442,7 +444,7 @@ void AM_findMinMaxBoundaries(void)
|
||||
a = FixedDiv(f_w<<FRACBITS, max_w);
|
||||
b = FixedDiv(f_h<<FRACBITS, max_h);
|
||||
|
||||
min_scale_mtof = a < b ? a : b;
|
||||
min_scale_mtof = a < b ? a/2 : b/2;
|
||||
max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
|
||||
}
|
||||
|
||||
@ -1181,8 +1183,8 @@ void AM_drawMline
|
||||
//
|
||||
void AM_drawGrid(int color)
|
||||
{
|
||||
fixed_t x, y;
|
||||
fixed_t start, end;
|
||||
int64_t x, y;
|
||||
int64_t start, end;
|
||||
mline_t ml;
|
||||
|
||||
// Figure out start of vertical gridlines
|
||||
@ -1477,11 +1479,11 @@ void AM_drawWalls(void)
|
||||
// Returns the coordinates rotated by the angle
|
||||
//
|
||||
void AM_rotate
|
||||
( fixed_t* x,
|
||||
fixed_t* y,
|
||||
( int64_t* x,
|
||||
int64_t* y,
|
||||
angle_t a )
|
||||
{
|
||||
fixed_t tmpx;
|
||||
int64_t tmpx;
|
||||
|
||||
tmpx =
|
||||
FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
|
||||
|
@ -61,7 +61,7 @@ extern void AM_clearMarks(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t x,y;
|
||||
int64_t x,y;
|
||||
} mpoint_t;
|
||||
|
||||
extern mpoint_t *markpoints;
|
||||
|
@ -339,9 +339,11 @@ void P_LoadNodes_ZDBSP (int lump, boolean compressed)
|
||||
|
||||
for (i = 0; i < newVerts; i++)
|
||||
{
|
||||
newvertarray[i + orgVerts].r_x =
|
||||
newvertarray[i + orgVerts].x = *((unsigned int*)data);
|
||||
data += sizeof(newvertarray[0].x);
|
||||
|
||||
newvertarray[i + orgVerts].r_y =
|
||||
newvertarray[i + orgVerts].y = *((unsigned int*)data);
|
||||
data += sizeof(newvertarray[0].y);
|
||||
}
|
||||
|
@ -138,6 +138,10 @@ void P_LoadVertexes (int lump)
|
||||
{
|
||||
vertexes[i].x = SHORT(((mapvertex_t *) data)[i].x)<<FRACBITS;
|
||||
vertexes[i].y = SHORT(((mapvertex_t *) data)[i].y)<<FRACBITS;
|
||||
|
||||
// [FG] vertex coordinates used for rendering
|
||||
vertexes[i].r_x = vertexes[i].x;
|
||||
vertexes[i].r_y = vertexes[i].y;
|
||||
}
|
||||
|
||||
// Free buffer memory.
|
||||
@ -917,8 +921,24 @@ void P_RemoveSlimeTrails(void) // killough 10/98
|
||||
Long64 dxy = (l->dx >> FRACBITS) * (l->dy >> FRACBITS);
|
||||
Long64 s = dx2 + dy2;
|
||||
int x0 = v->x, y0 = v->y, x1 = l->v1->x, y1 = l->v1->y;
|
||||
v->x = (fixed_t)((dx2 * x0 + dy2 * x1 + dxy * (y0 - y1)) / s);
|
||||
v->y = (fixed_t)((dy2 * y0 + dx2 * y1 + dxy * (x0 - x1)) / s);
|
||||
// [FG] move vertex coordinates used for rendering
|
||||
v->r_x = (fixed_t)((dx2 * x0 + dy2 * x1 + dxy * (y0 - y1)) / s);
|
||||
v->r_y = (fixed_t)((dy2 * y0 + dx2 * y1 + dxy * (x0 - x1)) / s);
|
||||
|
||||
// [FG] override actual vertex coordinates except in compatibility mode
|
||||
if (!demo_compatibility)
|
||||
{
|
||||
v->x = v->r_x;
|
||||
v->y = v->r_y;
|
||||
}
|
||||
|
||||
// [FG] wait a minute... moved more than 8 map units?
|
||||
// maybe that's a Linguortal then, back to the original coordinates
|
||||
if (abs(v->r_x - x0) > 8*FRACUNIT || abs(v->r_y - y0) > 8*FRACUNIT)
|
||||
{
|
||||
v->r_x = x0;
|
||||
v->r_y = y0;
|
||||
}
|
||||
}
|
||||
} // Obfuscated C contest entry: :)
|
||||
while ((v != segs[i].v2) && (v = segs[i].v2));
|
||||
@ -927,6 +947,27 @@ void P_RemoveSlimeTrails(void) // killough 10/98
|
||||
free(hit);
|
||||
}
|
||||
|
||||
// [FG] re-calculated seg lengths and angles used for rendering
|
||||
|
||||
static void P_SegLengthsAngles (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numsegs; i++)
|
||||
{
|
||||
seg_t *li = segs+i;
|
||||
int64_t dx, dy;
|
||||
|
||||
dx = li->v2->r_x - li->v1->r_x;
|
||||
dy = li->v2->r_y - li->v1->r_y;
|
||||
li->r_length = (uint32_t)(sqrt((double)dx*dx + (double)dy*dy)/2);
|
||||
|
||||
viewx = li->v1->r_x;
|
||||
viewy = li->v1->r_y;
|
||||
li->r_angle = R_PointToAngleCrispy(li->v2->r_x, li->v2->r_y);
|
||||
}
|
||||
}
|
||||
|
||||
// [FG] pad the REJECT table when the lump is too small
|
||||
|
||||
static void P_LoadReject(int lumpnum)
|
||||
@ -1048,6 +1089,9 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
|
||||
|
||||
P_RemoveSlimeTrails(); // killough 10/98: remove slime trails from wad
|
||||
|
||||
// [FG] seg lengths and angles used for rendering
|
||||
P_SegLengthsAngles();
|
||||
|
||||
// Note: you don't need to clear player queue slots --
|
||||
// a much simpler fix is in g_game.c -- killough 10/98
|
||||
|
||||
|
@ -378,8 +378,8 @@ static void R_AddLine (seg_t *line)
|
||||
|
||||
curline = line;
|
||||
|
||||
angle1 = R_PointToAngle (line->v1->x, line->v1->y);
|
||||
angle2 = R_PointToAngle (line->v2->x, line->v2->y);
|
||||
angle1 = R_PointToAngleCrispy (line->v1->r_x, line->v1->r_y);
|
||||
angle2 = R_PointToAngleCrispy (line->v2->r_x, line->v2->r_y);
|
||||
|
||||
// Clip to view edges.
|
||||
span = angle1 - angle2;
|
||||
@ -532,8 +532,8 @@ static boolean R_CheckBBox(fixed_t *bspcoord) // killough 1/28/98: static
|
||||
y2 = bspcoord[checkcoord[boxpos][3]];
|
||||
|
||||
// check clip list for an open space
|
||||
angle1 = R_PointToAngle (x1, y1) - viewangle;
|
||||
angle2 = R_PointToAngle (x2, y2) - viewangle;
|
||||
angle1 = R_PointToAngleCrispy (x1, y1) - viewangle;
|
||||
angle2 = R_PointToAngleCrispy (x2, y2) - viewangle;
|
||||
|
||||
span = angle1 - angle2;
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
||||
typedef struct
|
||||
{
|
||||
fixed_t x, y;
|
||||
|
||||
// [FG] vertex coordinates used for rendering
|
||||
fixed_t r_x, r_y;
|
||||
} vertex_t;
|
||||
|
||||
// Each sector has a degenmobj_t in its center for sound origin purposes.
|
||||
@ -255,6 +258,10 @@ typedef struct
|
||||
// backsector is NULL for one sided lines
|
||||
|
||||
sector_t *frontsector, *backsector;
|
||||
|
||||
// [FG] seg lengths and angles used for rendering
|
||||
uint32_t r_length;
|
||||
angle_t r_angle;
|
||||
} seg_t;
|
||||
|
||||
//
|
||||
|
@ -188,6 +188,37 @@ angle_t R_PointToAngle2(fixed_t viewx, fixed_t viewy, fixed_t x, fixed_t y)
|
||||
0;
|
||||
}
|
||||
|
||||
// [FG] overflow-safe R_PointToAngle() flavor,
|
||||
// only used in R_CheckBBox(), R_AddLine() and P_SegLengthsAngles()
|
||||
|
||||
angle_t R_PointToAngleCrispy(fixed_t x, fixed_t y)
|
||||
{
|
||||
// [FG] fix overflows for very long distances
|
||||
int64_t y_viewy = (int64_t)y - viewy;
|
||||
int64_t x_viewx = (int64_t)x - viewx;
|
||||
|
||||
// [FG] the worst that could happen is e.g. INT_MIN-INT_MAX = 2*INT_MIN
|
||||
if (x_viewx < INT_MIN || x_viewx > INT_MAX || y_viewy < INT_MIN || y_viewy > INT_MAX)
|
||||
{
|
||||
// [FG] preserving the angle by halfing the distance in both directions
|
||||
x = (int)(x_viewx / 2 + viewx);
|
||||
y = (int)(y_viewy / 2 + viewy);
|
||||
}
|
||||
|
||||
return (y -= viewy, (x -= viewx) || y) ?
|
||||
x >= 0 ?
|
||||
y >= 0 ?
|
||||
(x > y) ? tantoangle[SlopeDivCrispy(y,x)] : // octant 0
|
||||
ANG90-1-tantoangle[SlopeDivCrispy(x,y)] : // octant 1
|
||||
x > (y = -y) ? 0-tantoangle[SlopeDivCrispy(y,x)] : // octant 8
|
||||
ANG270+tantoangle[SlopeDivCrispy(x,y)] : // octant 7
|
||||
y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDivCrispy(y,x)] : // octant 3
|
||||
ANG90 + tantoangle[SlopeDivCrispy(x,y)] : // octant 2
|
||||
(x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDivCrispy(y,x)] : // octant 4
|
||||
ANG270-1-tantoangle[SlopeDivCrispy(x,y)] : // octant 5
|
||||
0;
|
||||
}
|
||||
|
||||
//
|
||||
// R_ScaleFromGlobalAngle
|
||||
// Returns the texture mapping scale
|
||||
|
@ -92,6 +92,7 @@ int R_PointOnSide(fixed_t x, fixed_t y, node_t *node);
|
||||
int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
|
||||
angle_t R_PointToAngle(fixed_t x, fixed_t y);
|
||||
angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
|
||||
angle_t R_PointToAngleCrispy(fixed_t x, fixed_t y);
|
||||
fixed_t R_ScaleFromGlobalAngle(angle_t visangle);
|
||||
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
|
||||
|
||||
|
@ -365,6 +365,7 @@ static void R_RenderSegLoop (void)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// killough 5/2/98: move from r_main.c, made static, simplified
|
||||
|
||||
static fixed_t R_PointToDist(fixed_t x, fixed_t y)
|
||||
@ -380,6 +381,7 @@ static fixed_t R_PointToDist(fixed_t x, fixed_t y)
|
||||
return dx ? FixedDiv(dx, finesine[(tantoangle[FixedDiv(dy,dx) >> DBITS]
|
||||
+ ANG90) >> ANGLETOFINESHIFT]) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// R_StoreWallRange
|
||||
@ -388,9 +390,9 @@ static fixed_t R_PointToDist(fixed_t x, fixed_t y)
|
||||
//
|
||||
void R_StoreWallRange(const int start, const int stop)
|
||||
{
|
||||
fixed_t hyp;
|
||||
fixed_t sineval;
|
||||
angle_t distangle, offsetangle;
|
||||
// [FG] fix long wall wobble
|
||||
int64_t dx, dy, dx1, dy1, dist;
|
||||
const uint32_t len = curline->r_length; // [FG] use re-calculated seg lengths
|
||||
|
||||
if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM
|
||||
{
|
||||
@ -412,16 +414,16 @@ void R_StoreWallRange(const int start, const int stop)
|
||||
linedef->flags |= ML_MAPPED;
|
||||
|
||||
// calculate rw_distance for scale calculation
|
||||
rw_normalangle = curline->angle + ANG90;
|
||||
offsetangle = abs(rw_normalangle-rw_angle1);
|
||||
rw_normalangle = curline->r_angle + ANG90; // [FG] use re-calculated seg angles
|
||||
|
||||
if (offsetangle > ANG90)
|
||||
offsetangle = ANG90;
|
||||
|
||||
distangle = ANG90 - offsetangle;
|
||||
hyp = R_PointToDist (curline->v1->x, curline->v1->y);
|
||||
sineval = finesine[distangle>>ANGLETOFINESHIFT];
|
||||
rw_distance = FixedMul(hyp, sineval);
|
||||
// [FG] fix long wall wobble
|
||||
// shift right to avoid possibility of int64 overflow in rw_distance calculation
|
||||
dx = ((int64_t)curline->v2->r_x - curline->v1->r_x) >> 1;
|
||||
dy = ((int64_t)curline->v2->r_y - curline->v1->r_y) >> 1;
|
||||
dx1 = ((int64_t)viewx - curline->v1->r_x) >> 1;
|
||||
dy1 = ((int64_t)viewy - curline->v1->r_y) >> 1;
|
||||
dist = ((dy * dx1 - dx * dy1) / len) << 1;
|
||||
rw_distance = (fixed_t)(dist < INT_MIN ? INT_MIN : dist > INT_MAX ? INT_MAX : dist);
|
||||
|
||||
ds_p->x1 = rw_x = start;
|
||||
ds_p->x2 = stop;
|
||||
@ -627,20 +629,8 @@ void R_StoreWallRange(const int start, const int stop)
|
||||
|
||||
if (segtextured)
|
||||
{
|
||||
offsetangle = rw_normalangle-rw_angle1;
|
||||
|
||||
if (offsetangle > ANG180)
|
||||
offsetangle = 0 - offsetangle;
|
||||
|
||||
if (offsetangle > ANG90)
|
||||
offsetangle = ANG90;
|
||||
|
||||
sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
|
||||
rw_offset = FixedMul (hyp, sineval);
|
||||
|
||||
if (rw_normalangle-rw_angle1 < ANG180)
|
||||
rw_offset = -rw_offset;
|
||||
|
||||
// [FG] fix long wall wobble
|
||||
rw_offset = (fixed_t)(((dx * dx1 + dy * dy1) / len) << 1);
|
||||
rw_offset += sidedef->textureoffset + curline->offset;
|
||||
|
||||
rw_centerangle = ANG90 + viewangle - rw_normalangle;
|
||||
|
@ -54,6 +54,18 @@ int SlopeDiv(unsigned num, unsigned den)
|
||||
return ans <= SLOPERANGE ? ans : SLOPERANGE;
|
||||
}
|
||||
|
||||
// [FG] overflow-safe SlopeDiv() flavor, only used in R_PointToAngleCrispy()
|
||||
|
||||
int SlopeDivCrispy(unsigned num, unsigned den)
|
||||
{
|
||||
uint64_t ans;
|
||||
|
||||
if (den < 512)
|
||||
return SLOPERANGE;
|
||||
ans = ((uint64_t)num<<3)/(den>>8);
|
||||
return ans <= SLOPERANGE ? (int)ans : SLOPERANGE;
|
||||
}
|
||||
|
||||
const int finetangent[4096] = { -170910304,
|
||||
-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683,
|
||||
-10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368,
|
||||
|
@ -78,6 +78,7 @@ extern const angle_t tantoangle[SLOPERANGE+1];
|
||||
|
||||
// Utility function, called by R_PointToAngle.
|
||||
int SlopeDiv(unsigned num, unsigned den);
|
||||
int SlopeDivCrispy(unsigned num, unsigned den);
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user