diff --git a/src/p_tick.c b/src/p_tick.c index 929615fa2..3b47f7c03 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -884,6 +884,14 @@ void P_Ticker(boolean run) { leveltime++; +#ifdef AFFINEROT_TESTER + if (cv_affinerottest.value == 2) + { + fixed_t newaffineangle = (cv_affineangle.value + (FRACUNIT)) % (360 * FRACUNIT); + CV_StealthSet(&cv_affineangle, va("%f", FIXED_TO_FLOAT(newaffineangle))); + } +#endif + if (starttime > introtime && leveltime == starttime) { ACS_RunRaceStartScript(); diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index efbb69066..ff11428b3 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -21,6 +21,7 @@ // a has a constant z depth from top to bottom. // +#include "r_main.h" #include "r_draw.h" #include @@ -546,29 +547,29 @@ void R_DrawAffineColumn(drawcolumndata_t *dc) const fixed_t b = transform->b; const fixed_t c = transform->c; const fixed_t d = transform->d; - fixed_t cx = (bounds->xlen * FRACHALF); //transform->ox; - fixed_t cy = (bounds->ylen * FRACHALF); //transform->oy; + fixed_t cx = transform->ox; + fixed_t cy = transform->oy; const INT32 pw = dc->sourcelength, ph = dc->texheight; - INT32 ydiff = (bounds->yup - (transform->oy >> FRACBITS)); - INT32 xdiff = (bounds->xleft - (transform->ox >> FRACBITS)); + fixed_t ydiff = (bounds->yup * FRACUNIT) - cy; + fixed_t xdiff = (bounds->xleft * FRACUNIT) - cx; - vector2_t centering; - - centering.x = (bounds->xlen * FRACHALF); - centering.y = (bounds->ylen * FRACHALF); + xdiff -= (xdiff ? FRACUNIT : 0); + ydiff -= (ydiff ? FRACUNIT : 0); // Offset our X and Y positions by the bounding differences. - fixed_t cxx = (xdiff * FRACUNIT); - fixed_t cyy = 0; //+ (ydiff * FRACUNIT); + fixed_t cxx = cx + xdiff; + fixed_t cyy = cy + ydiff; + + //I_OutputMsg("xdiff: %f, ydiff: %f\n", FIXED_TO_FLOAT(xdiff), FIXED_TO_FLOAT(ydiff)); // yoinked from NovaSquirrel's mode 7 0preview // ...which is in turn yoinked from Mesen's S-PPU code // i can't do matrix math to save my life :face_holding_back_tears: // (m7xofs and m7yofs are already factored in by destbase) - fixed_t ux = FixedMul(b, -cxx) + FixedMul(a, -cyy) + FixedMul(a, dc->frac);// + cx; - fixed_t uy = FixedMul(d, -cxx) + FixedMul(c, -cyy) + FixedMul(c, dc->frac) + cy; + fixed_t ux = FixedMul(b, -cyy) + FixedMul(a, -cxx) + FixedMul(a, dc->frac) + cx; + fixed_t uy = FixedMul(d, -cyy) + FixedMul(c, -cxx) + FixedMul(c, dc->frac) + cy; for (; count > 0; dest += stride, --count) { diff --git a/src/r_main.cpp b/src/r_main.cpp index e1192ad93..1da915fcd 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -197,6 +197,14 @@ consvar_t cv_sliptidetilt = CVAR_INIT ("sliptidetilt", "On", CV_SAVE, CV_OnOff, consvar_t cv_nulldriftefx = CVAR_INIT ("nulldriftefx", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_nulldrifttilt = CVAR_INIT ("nulldrifttilt", "On", CV_SAVE, CV_OnOff, NULL); +static CV_PossibleValue_t affineangle_cons_t[] = {{0, "MIN"}, {360 * FRACUNIT, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t affinetest_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Auto"}, {0, NULL}}; + +#ifdef AFFINEROT_TESTER +consvar_t cv_affineangle = CVAR_INIT ("affineangle", "0", CV_FLOAT, affineangle_cons_t, NULL); +consvar_t cv_affinerottest = CVAR_INIT ("affinerottest", "Off", CV_FLOAT, affinetest_cons_t, NULL); +#endif + void SplitScreen_OnChange(void) { UINT8 i; @@ -1812,6 +1820,11 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_playerfade); +#ifdef AFFINEROT_TESTER + CV_RegisterVar(&cv_affineangle); + CV_RegisterVar(&cv_affinerottest); +#endif + CV_RegisterVar(&cv_movebob); // Frame interpolation/uncapped diff --git a/src/r_main.h b/src/r_main.h index 57889b115..115017f34 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -161,6 +161,10 @@ extern consvar_t cv_sloperoll; extern consvar_t cv_sliptidetilt; extern consvar_t cv_nulldriftefx, cv_nulldrifttilt; +#ifdef AFFINEROT_TESTER +extern consvar_t cv_affineangle, cv_affinerottest; +#endif + // debugging typedef enum { diff --git a/src/r_things.cpp b/src/r_things.cpp index 12d668517..e45d8d441 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -986,6 +986,8 @@ static void R_DrawVisSprite(vissprite_t *vis) drawcolumndata_t dc {0}; const INT32 vidwidth = vid.width; + fixed_t maxpatchwidth = (patch->width << FRACBITS); + if (!patch) return; @@ -1001,10 +1003,16 @@ static void R_DrawVisSprite(vissprite_t *vis) if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto } + if (vis->cut & SC_AFFINE) + { + // Resize the max horizontal bounds so we can draw the whole affine patch. + maxpatchwidth = std::max(maxpatchwidth, vis->affine.bounds.xlen * FRACUNIT); + } + // TODO This check should not be necessary. But Papersprites near to the camera will sometimes create invalid values // for the vissprite's startfrac. This happens because they are not depth culled like other sprites. // Someone who is more familiar with papersprites pls check and try to fix <3 - if (vis->startfrac < 0 || vis->startfrac > (patch->width << FRACBITS)) + if (vis->startfrac < 0 || vis->startfrac > maxpatchwidth) { // never draw vissprites with startfrac out of patch range return; @@ -1104,9 +1112,11 @@ static void R_DrawVisSprite(vissprite_t *vis) spryscale = vis->scale; + fixed_t ymovescale = (vis->cut & SC_AFFINE) ? vis->affine.scaling.y : spryscale; + if (!(vis->scalestep)) { - sprtopscreen = centeryfrac - FixedMul(dc.texturemid, spryscale); + sprtopscreen = centeryfrac - FixedMul(dc.texturemid, ymovescale); sprtopscreen += vis->shear.tan * vis->shear.offset; dc.iscale = FixedDiv(FRACUNIT, vis->scale); } @@ -1970,11 +1980,11 @@ static void R_ProjectSprite(mobj_t *thing) if (affinesprite) { - xscale = FRACUNIT; - sortscale = FRACUNIT; - affine_scale.x = FixedDiv(projection[viewssnum], tz); affine_scale.y = FixedDiv(projectiony[viewssnum], tz); + + xscale = FRACUNIT; + sortscale = affine_scale.y; } else { @@ -2180,6 +2190,44 @@ static void R_ProjectSprite(mobj_t *thing) } #endif + if (affinesprite) + { + affine_scale.x = FixedMul(affine_scale.x, FixedMul(spritexscale, this_scale)); + affine_scale.y = FixedMul(affine_scale.y, FixedMul(spriteyscale, this_scale)); + + angle_t angle; + + INT32 flipsign = ((flip) ? -1 : 1); + +#ifdef AFFINEROT_TESTER + if (!cv_affinerottest.value) + angle = spriterotangle * flipsign; + else + angle = FixedAngle(cv_affineangle.value); +#else + angle = spriterotangle * flipsign; +#endif + + fixed_t sa = FSIN(angle), ca = FCOS(angle); + affine_transform.a = FixedDiv(ca, affine_scale.x); + affine_transform.b = FixedDiv(-sa, affine_scale.x); + affine_transform.c = FixedDiv(sa, affine_scale.y); + affine_transform.d = FixedDiv(ca, affine_scale.y); + affine_transform.ox = (patch->pivot.x + patch->leftoffset) * FRACUNIT; + affine_transform.oy = (patch->pivot.y + patch->topoffset) * FRACUNIT; + + V_GetAffineBounds(&affine_transform, patch, FRACUNIT, &affine_bounds); + + spr_width = (affine_bounds.xlen * FRACUNIT); + spr_offset = (affine_bounds.xleft * FRACUNIT); + + //spr_height = (affine_bounds.ylen * FRACUNIT); + //spr_topoffset = (affine_bounds.yup * FRACUNIT); + + spritexscale = FRACUNIT; + spriteyscale = FRACUNIT; + } + if (thing->renderflags & RF_ABSOLUTEOFFSETS) { spr_offset = FixedDiv(interp.spritexoffset, highresscale); @@ -2221,37 +2269,8 @@ static void R_ProjectSprite(mobj_t *thing) } #endif - if (affinesprite) - { - affine_scale.x = FixedMul(affine_scale.x, FixedMul(spritexscale, this_scale)); - - angle_t angle = spriterotangle; //leveltime*ANG2; - fixed_t sa = FSIN(angle), ca = FCOS(angle); - affine_transform.a = FixedDiv(ca, FRACUNIT); - affine_transform.b = FixedDiv(-sa, FRACUNIT); - affine_transform.c = FixedDiv(sa, FRACUNIT); - affine_transform.d = FixedDiv(ca, FRACUNIT); - affine_transform.ox = (patch->pivot.x + patch->leftoffset) * FRACUNIT; - affine_transform.oy = (patch->pivot.y + patch->topoffset) * FRACUNIT; - - V_GetAffineBounds(&affine_transform, patch, FRACUNIT, &affine_bounds); - - spr_width = (affine_bounds.xlen * FRACUNIT); - spr_height = (affine_bounds.ylen * FRACUNIT); - - INT32 xdiff = (affine_bounds.xleft - (affine_transform.ox >> FRACBITS)); - - offset -= (xdiff * FRACUNIT); - offset2 = spr_width; - - spritexscale = FRACUNIT; - spriteyscale = FRACUNIT; - } - else - { - offset = FixedMul(offset, FixedMul(spritexscale, this_scale)); - offset2 = FixedMul(spr_width, FixedMul(spritexscale, this_scale)); - } + offset = FixedMul(offset, FixedMul(spritexscale, this_scale)); + offset2 = FixedMul(spr_width, FixedMul(spritexscale, this_scale)); if (papersprite) { @@ -2356,7 +2375,7 @@ static void R_ProjectSprite(mobj_t *thing) else { scalestep = 0; - yscale = sortscale; + yscale = (affinesprite) ? FRACUNIT : sortscale; tx += offset; x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; @@ -2677,6 +2696,8 @@ static void R_ProjectSprite(mobj_t *thing) if (affinesprite) { + vis->affine.scaling.x = affine_scale.x; + vis->affine.scaling.y = affine_scale.y; vis->affine.rollangle = spriterotangle; vis->affine.transform.a = affine_transform.a; @@ -2708,7 +2729,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000 vis->scale = FixedMul(spriteyscale, yscale); //<thingscale = this_scale; + vis->thingscale = (affinesprite) ? FRACUNIT : this_scale; vis->spritexscale = spritexscale; vis->spriteyscale = spriteyscale; diff --git a/src/r_things.h b/src/r_things.h index fb9e91f62..961ae8cb8 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -186,6 +186,7 @@ struct vissprite_t fixed_t startfrac; // horizontal position of x1 fixed_t xscale, scale; // projected horizontal and vertical scales + fixed_t ypush_scale; // Scale for downwards Y movement. Likely only relevant for affines. fixed_t thingscale; // the object's scale fixed_t sortscale; // sortscale only differs from scale for paper sprites and floor sprites fixed_t sortsplat; // the sortscale from behind the floor sprite @@ -208,6 +209,7 @@ struct vissprite_t } shear; struct { + vector2_t scaling; // Affine scaling angle_t rollangle; // Affine rotation angle affine_t transform; // The actual affine transformation. affine_bounding_t bounds; // The "bounding box" (draw area) of the affine sprite.