From 450955cba264ea3dde9eb3f745ff9816307635ce Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Thu, 26 Aug 2021 13:22:32 -0300 Subject: [PATCH] Fix floor sprite projection --- src/r_plane.c | 124 ++++++++----------------------------------------- src/r_plane.h | 1 - src/r_splats.c | 91 ++++++++++++++---------------------- src/r_splats.h | 3 +- src/r_things.c | 5 +- src/r_things.h | 10 +++- 6 files changed, 68 insertions(+), 166 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 818770906..d844048ae 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -89,8 +89,6 @@ static fixed_t planeheight; fixed_t yslopetab[MAXVIDHEIGHT*16]; fixed_t *yslope; -fixed_t basexscale, baseyscale; - fixed_t cachedheight[MAXVIDHEIGHT]; fixed_t cacheddistance[MAXVIDHEIGHT]; fixed_t cachedxstep[MAXVIDHEIGHT]; @@ -114,7 +112,7 @@ void R_InitPlanes(void) // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // -struct +static struct { INT32 offset; fixed_t xfrac, yfrac; @@ -143,15 +141,6 @@ static void R_UpdatePlaneRipple(void) planeripple.offset = (leveltime * 140); } -// -// R_MapPlane -// -// Uses global vars: -// planeheight -// basexscale -// baseyscale -// centerx - static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; @@ -176,16 +165,13 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); span = abs(centery - y); - if (span) // don't divide by zero + if (span) // Don't divide by zero { ds_xstep = FixedMul(planesin, planeheight) / span; ds_ystep = FixedMul(planecos, planeheight) / span; } else - { - ds_xstep = FixedMul(distance, basexscale); - ds_ystep = FixedMul(distance, baseyscale); - } + ds_xstep = ds_ystep = FRACUNIT; cachedxstep[y] = ds_xstep; cachedystep[y] = ds_ystep; @@ -197,6 +183,11 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_ystep = cachedystep[y]; } + // [RH] Instead of using the xtoviewangle array, I calculated the fractional values + // at the middle of the screen, then used the calculated ds_xstep and ds_ystep + // to step from those to the proper texture coordinate to start drawing at. + // That way, the texture coordinate is always calculated by its position + // on the screen and not by its position relative to the edge of the visplane. ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; @@ -295,7 +286,6 @@ void R_ClearFFloorClips (void) void R_ClearPlanes(void) { INT32 i, p; - angle_t angle; // opening / clipping determination for (i = 0; i < viewwidth; i++) @@ -321,13 +311,6 @@ void R_ClearPlanes(void) // texture calculation memset(cachedheight, 0, sizeof (cachedheight)); - - // left to right mapping - angle = (viewangle-ANGLE_90)>>ANGLETOFINESHIFT; - - // scale will be unit scale at SCREENWIDTH/2 distance - basexscale = FixedDiv (FINECOSINE(angle),centerxfrac); - baseyscale = -FixedDiv (FINESINE(angle),centerxfrac); } static visplane_t *new_visplane(unsigned hash) @@ -532,53 +515,22 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) // // R_ExpandPlane // -// This function basically expands the visplane or I_Errors. +// This function basically expands the visplane. // The reason for this is that when creating 3D floor planes, there is no // need to create new ones with R_CheckPlane, because 3D floor planes // are created by subsector and there is no way a subsector can graphically // overlap. void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) { -// INT32 unionl, unionh; -// INT32 x; - // Don't expand polyobject planes here - we do that on our own. if (pl->polyobj) return; if (pl->minx > start) pl->minx = start; if (pl->maxx < stop) pl->maxx = stop; -/* - if (start < pl->minx) - { - unionl = start; - } - else - { - unionl = pl->minx; - } - - if (stop > pl->maxx) - { - unionh = stop; - } - else - { - unionh = pl->maxx; - } - for (x = start; x <= stop; x++) - if (pl->top[x] != 0xffff || pl->bottom[x] != 0x0000) - break; - - if (x <= stop) - I_Error("R_ExpandPlane: planes in same subsector overlap?!\nminx: %d, maxx: %d, start: %d, stop: %d\n", pl->minx, pl->maxx, start, stop); - - pl->minx = unionl, pl->maxx = unionh; -*/ - } -static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) +static void R_MakeSpans(void (*mapfunc)(INT32, INT32, INT32), INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) { // Alam: from r_splats's R_RasterizeFloorSplat if (t1 >= vid.height) t1 = vid.height-1; @@ -589,38 +541,12 @@ static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) while (t1 < t2 && t1 <= b1) { - R_MapPlane(t1, spanstart[t1], x - 1); + mapfunc(t1, spanstart[t1], x - 1); t1++; } while (b1 > b2 && b1 >= t1) { - R_MapPlane(b1, spanstart[b1], x - 1); - b1--; - } - - while (t2 < t1 && t2 <= b2) - spanstart[t2++] = x; - while (b2 > b1 && b2 >= t2) - spanstart[b2--] = x; -} - -static void R_MakeTiltedSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) -{ - // Alam: from r_splats's R_RasterizeFloorSplat - if (t1 >= vid.height) t1 = vid.height-1; - if (b1 >= vid.height) b1 = vid.height-1; - if (t2 >= vid.height) t2 = vid.height-1; - if (b2 >= vid.height) b2 = vid.height-1; - if (x-1 >= vid.width) x = vid.width; - - while (t1 < t2 && t1 <= b1) - { - R_MapTiltedPlane(t1, spanstart[t1], x - 1); - t1++; - } - while (b1 > b2 && b1 >= t1) - { - R_MapTiltedPlane(b1, spanstart[b1], x - 1); + mapfunc(b1, spanstart[b1], x - 1); b1--; } @@ -867,11 +793,10 @@ void R_DrawSinglePlane(visplane_t *pl) { levelflat_t *levelflat; INT32 light = 0; - INT32 x; - INT32 stop, angle; + INT32 x, stop; ffloor_t *rover; - INT32 type; - INT32 spanfunctype = BASEDRAWFUNC; + INT32 type, spanfunctype = BASEDRAWFUNC; + void (*mapfunc)(INT32, INT32, INT32) = R_MapPlane; if (!(pl->minx <= pl->maxx)) return; @@ -1023,9 +948,6 @@ void R_DrawSinglePlane(visplane_t *pl) && viewangle != pl->viewangle+pl->plangle) { memset(cachedheight, 0, sizeof (cachedheight)); - angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT; - basexscale = FixedDiv(FINECOSINE(angle),centerxfrac); - baseyscale = -FixedDiv(FINESINE(angle),centerxfrac); viewangle = pl->viewangle+pl->plangle; } @@ -1040,6 +962,8 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { + mapfunc = R_MapTiltedPlane; + if (!pl->plangle) { if (ds_powersoftwo) @@ -1107,16 +1031,8 @@ void R_DrawSinglePlane(visplane_t *pl) stop = pl->maxx + 1; - if (pl->slope) - { - for (x = pl->minx; x <= stop; x++) - R_MakeTiltedSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); - } - else - { - for (x = pl->minx; x <= stop; x++) - R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); - } + for (x = pl->minx; x <= stop; x++) + R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); /* QUINCUNX anti-aliasing technique (sort of) @@ -1183,7 +1099,7 @@ using the palette colors. stop = pl->maxx + 1; for (x = pl->minx; x <= stop; x++) - R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], + R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); } } diff --git a/src/r_plane.h b/src/r_plane.h index bdad77930..862b95069 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -69,7 +69,6 @@ extern fixed_t cachedheight[MAXVIDHEIGHT]; extern fixed_t cacheddistance[MAXVIDHEIGHT]; extern fixed_t cachedxstep[MAXVIDHEIGHT]; extern fixed_t cachedystep[MAXVIDHEIGHT]; -extern fixed_t basexscale, baseyscale; extern fixed_t *yslope; extern lighttable_t **planezlight; diff --git a/src/r_splats.c b/src/r_splats.c index 4783fb640..c554e9b1f 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -155,7 +155,6 @@ void R_DrawFloorSplat(vissprite_t *spr) fixed_t xscale, yscale; fixed_t xoffset, yoffset; fixed_t leftoffset, topoffset; - pslope_t *slope = NULL; INT32 i; boolean hflip = (spr->xiscale < 0); @@ -188,7 +187,7 @@ void R_DrawFloorSplat(vissprite_t *spr) if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) splatangle = mobj->angle; else - splatangle = spr->viewangle; + splatangle = spr->viewpoint.angle; if (!(spr->cut & SC_ISROTATED)) splatangle += mobj->rollangle; @@ -218,7 +217,7 @@ void R_DrawFloorSplat(vissprite_t *spr) splat.x = x; splat.y = y; splat.z = mobj->z; - splat.tilted = false; + splat.slope = NULL; // Set positions @@ -238,9 +237,9 @@ void R_DrawFloorSplat(vissprite_t *spr) splat.verts[3].x = w - xoffset; splat.verts[3].y = -h + yoffset; - angle = -splat.angle; - ca = FINECOSINE(angle>>ANGLETOFINESHIFT); - sa = FINESINE(angle>>ANGLETOFINESHIFT); + angle = -splat.angle>>ANGLETOFINESHIFT; + ca = FINECOSINE(angle); + sa = FINESINE(angle); // Rotate for (i = 0; i < 4; i++) @@ -255,36 +254,10 @@ void R_DrawFloorSplat(vissprite_t *spr) // The slope that was defined for the sprite. if (renderflags & RF_SLOPESPLAT) - slope = mobj->floorspriteslope; + splat.slope = mobj->floorspriteslope; if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) - slope = standingslope; - - // Set splat as tilted - splat.tilted = (slope != NULL); - } - - if (splat.tilted) - { - pslope_t *s = &splat.slope; - - s->o.x = slope->o.x; - s->o.y = slope->o.y; - s->o.z = slope->o.z; - - s->d.x = slope->d.x; - s->d.y = slope->d.y; - - s->normal.x = slope->normal.x; - s->normal.y = slope->normal.y; - s->normal.z = slope->normal.z; - - s->zdelta = slope->zdelta; - s->zangle = slope->zangle; - s->xydirection = slope->xydirection; - - s->next = NULL; - s->flags = 0; + splat.slope = standingslope; } // Translate @@ -293,9 +266,9 @@ void R_DrawFloorSplat(vissprite_t *spr) tr_x = rotated[i].x + x; tr_y = rotated[i].y + y; - if (slope) + if (splat.slope) { - rot_z = P_GetSlopeZAt(slope, tr_x, tr_y); + rot_z = P_GetSlopeZAt(splat.slope, tr_x, tr_y); splat.verts[i].z = rot_z; } else @@ -305,18 +278,23 @@ void R_DrawFloorSplat(vissprite_t *spr) splat.verts[i].y = tr_y; } + angle = spr->viewpoint.angle >> ANGLETOFINESHIFT; + ca = FINECOSINE(angle); + sa = FINESINE(angle); + + // Project for (i = 0; i < 4; i++) { v3d = &splat.verts[i]; // transform the origin point - tr_x = v3d->x - viewx; - tr_y = v3d->y - viewy; + tr_x = v3d->x - spr->viewpoint.x; + tr_y = v3d->y - spr->viewpoint.y; // rotation around vertical y axis - rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); - rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - rot_z = v3d->z - viewz; + rot_x = FixedMul(tr_x, sa) - FixedMul(tr_y, ca); + rot_y = FixedMul(tr_x, ca) + FixedMul(tr_y, sa); + rot_z = v3d->z - spr->viewpoint.z; if (rot_y < FRACUNIT) return; @@ -416,31 +394,32 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (R_CheckPowersOfTwo()) R_CheckFlatLength(ds_flatwidth * ds_flatheight); - if (pSplat->tilted) + if (pSplat->slope) { R_SetTiltedSpan(0); - R_SetScaledSlopePlane(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle); + R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); R_CalculateSlopeVectors(); spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; } else { - planeheight = abs(pSplat->z - viewz); + planeheight = abs(pSplat->z - vis->viewpoint.z); if (pSplat->angle) { - // Add the view offset, rotated by the plane angle. - fixed_t a = -pSplat->verts[0].x + viewx; - fixed_t b = -pSplat->verts[0].y + viewy; - angle_t angle = (pSplat->angle >> ANGLETOFINESHIFT); - offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle)); - offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle)); memset(cachedheight, 0, sizeof(cachedheight)); + + // Add the view offset, rotated by the plane angle. + fixed_t a = -pSplat->verts[0].x + vis->viewpoint.x; + fixed_t b = -pSplat->verts[0].y + vis->viewpoint.y; + angle_t angle = (pSplat->angle >> ANGLETOFINESHIFT); + offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b, FINESINE(angle)); + offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b, FINECOSINE(angle)); } else { - offsetx = viewx - pSplat->verts[0].x; - offsety = pSplat->verts[0].y - viewy; + offsetx = vis->viewpoint.x - pSplat->verts[0].x; + offsety = pSplat->verts[0].y - vis->viewpoint.y; } } @@ -461,7 +440,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr { ds_transmap = vis->transmap; - if (pSplat->tilted) + if (pSplat->slope) spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE; else spanfunctype = SPANDRAWFUNC_TRANSSPRITE; @@ -528,12 +507,12 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (x2 < x1) continue; - if (!pSplat->tilted) + if (!pSplat->slope) { fixed_t xstep, ystep; fixed_t distance, span; - angle_t angle = (vis->viewangle + pSplat->angle)>>ANGLETOFINESHIFT; + angle_t angle = (vis->viewpoint.angle + pSplat->angle)>>ANGLETOFINESHIFT; angle_t planecos = FINECOSINE(angle); angle_t planesin = FINESINE(angle); @@ -577,7 +556,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr rastertab[y].maxx = INT32_MIN; } - if (pSplat->angle && !pSplat->tilted) + if (pSplat->angle && !pSplat->slope) memset(cachedheight, 0, sizeof(cachedheight)); } diff --git a/src/r_splats.h b/src/r_splats.h index cab3d63b6..7e31406d1 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -34,8 +34,7 @@ typedef struct floorsplat_s INT32 width, height; fixed_t scale, xscale, yscale; angle_t angle; - boolean tilted; // Uses the tilted drawer - pslope_t slope; + pslope_t *slope; vector3_t verts[4]; // (x,y,z) as viewed from above on map fixed_t x, y, z; // position diff --git a/src/r_things.c b/src/r_things.c index 0283712b8..f1996d743 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1956,9 +1956,12 @@ static void R_ProjectSprite(mobj_t *thing) vis->paperoffset = paperoffset; vis->paperdistance = paperdistance; vis->centerangle = centerangle; - vis->viewangle = viewangle; vis->shear.tan = sheartan; vis->shear.offset = 0; + vis->viewpoint.x = viewx; + vis->viewpoint.y = viewy; + vis->viewpoint.z = viewz; + vis->viewpoint.angle = viewangle; vis->mobj = thing; // Easy access! Tails 06-07-2002 diff --git a/src/r_things.h b/src/r_things.h index 9315b36e9..79dc80d94 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -164,7 +164,12 @@ typedef struct vissprite_s fixed_t xiscale; // negative if flipped angle_t centerangle; // for paper sprites - angle_t viewangle; // for floor sprites, the viewpoint's current angle + + // for floor sprites + struct { + fixed_t x, y, z; // the viewpoint's current position + angle_t angle; // the viewpoint's current angle + } viewpoint; struct { fixed_t tan; // The amount to shear the sprite vertically per row @@ -185,9 +190,10 @@ typedef struct vissprite_s extracolormap_t *extra_colormap; // global colormaps - // Precalculated top and bottom screen coords for the sprite. fixed_t thingheight; // The actual height of the thing (for 3D floors) sector_t *sector; // The sector containing the thing. + + // Precalculated top and bottom screen coords for the sprite. INT16 sz, szt; spritecut_e cut;