Add variables that bake 3D offsets into a sprite

https://git.do.srb2.org/KartKrew/RingRacers/-/merge_requests/63
This commit is contained in:
NepDisk 2025-09-12 11:50:24 -04:00
parent 4a5c7fcae2
commit d98dd3e2dd
15 changed files with 398 additions and 9 deletions

View file

@ -4310,6 +4310,12 @@ enum
THING_PROP_HNEXT,
THING_PROP_HPREV,
THING_PROP_ITNEXT,
THING_PROP_BAKEDXOFFSET,
THING_PROP_BAKEDYOFFSET,
THING_PROP_BAKEDZOFFSET,
THING_PROP_BAKEDXPIVOT,
THING_PROP_BAKEDYPIVOT,
THING_PROP_BAKEDZPIVOT,
THING_PROP__MAX
};
@ -4479,6 +4485,12 @@ bool CallFunc_GetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
PROP_MOBJ(THING_PROP_HNEXT, hnext)
PROP_MOBJ(THING_PROP_HPREV, hprev)
PROP_MOBJ(THING_PROP_ITNEXT, itnext)
PROP_INT(THING_PROP_BAKEDXOFFSET, bakexoff)
PROP_INT(THING_PROP_BAKEDYOFFSET, bakeyoff)
PROP_INT(THING_PROP_BAKEDZOFFSET, bakezoff)
PROP_INT(THING_PROP_BAKEDXPIVOT, bakexpiv)
PROP_INT(THING_PROP_BAKEDYPIVOT, bakeypiv)
PROP_INT(THING_PROP_BAKEDZPIVOT, bakezpiv)
default:
{
CONS_Alert(CONS_WARNING, "GetThingProperty type %d out of range (expected 0 - %d).\n", property, THING_PROP__MAX-1);

View file

@ -1087,6 +1087,7 @@ struct int_const_s const INT_CONST[] = {
{"OV_DONT3DOFFSET", OV_DONT3DOFFSET},
{"OV_DONTXYSCALE", OV_DONTXYSCALE},
{"OV_DONTROLL", OV_DONTROLL},
{"OV_DONTBAKEOFFSET", OV_DONTBAKEOFFSET},
// Player state (playerstate_t)
{"PST_LIVE",PST_LIVE}, // Playing or camping.

View file

@ -4712,6 +4712,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
patch_t *rotsprite = NULL;
INT32 rollangle = 0;
angle_t spriterotangle = 0;
vector2_t visoffs;
#endif
// uncapped/interpolation
@ -4877,12 +4878,28 @@ static void HWR_ProjectSprite(mobj_t *thing)
flip = 0;
}
}
// initialize and rotate pitch/roll vector
visoffs.x = 0;
visoffs.y = 0;
const fixed_t visoffymul = (vflip ? -FRACUNIT : FRACUNIT);
if (R_ThingIsUsingBakedOffsets(thing))
{
R_RotateSpriteOffsetsByPitchRoll(thing,
vflip, hflip, &visoffs);
}
#endif
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
{
spr_offset = interp.spritexoffset;
#ifdef ROTSPRITE
spr_topoffset = (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul), mapobjectscale));
#else
spr_topoffset = interp.spriteyoffset;
#endif
}
else
{
@ -4892,7 +4909,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
flipoffset = -1;
spr_offset += interp.spritexoffset * flipoffset;
#ifdef ROTSPRITE
spr_topoffset += (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul),
mapobjectscale)) * flipoffset;
#else
spr_topoffset += interp.spriteyoffset * flipoffset;
#endif
}
if (papersprite)
@ -4943,17 +4965,28 @@ static void HWR_ProjectSprite(mobj_t *thing)
}
else
{
#ifdef ROTSPRITE
if (visoffs.x)
{
visoffs.x = (FixedDiv((visoffs.x * FRACUNIT), mapobjectscale));
}
#endif
if (flip)
{
x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale);
#ifdef ROTSPRITE
spr_offset -= visoffs.x;
#endif
x1 = (FIXED_TO_FLOAT((spr_width - spr_offset)) * this_xscale);
x2 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
}
else
{
#ifdef ROTSPRITE
spr_offset += visoffs.x;
#endif
x1 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale);
}
// test if too close
/*
if (papersprite)

View file

@ -1685,18 +1685,27 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.angley = FIXED_TO_FLOAT(anglef);
}
angle_t pitchR, rollR, fixedAngY;
// drift frame unrotation hack...
if (modeltype == MODELTYPE_OLDPLAYER && (spr2 == SPR2_DRRN || spr2 == SPR2_DRLN))
p.angley += spr2 == SPR2_DRRN ? 45.0f : -45.0f;
pitchR = 0;
rollR = 0;
fixedAngY = 0;
{
fixed_t anglef = AngleFixed(R_SpriteRotationAngle(spr->mobj, NULL, &interp));
p.rollangle = 0.0f;
// make fixedAngY a disguised fixed_t first
fixedAngY = FLOAT_TO_FIXED(p.angley);
if (anglef)
{
fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know
fixed_t camAngleDiff = AngleFixed(viewangle) - (fixed_t)(fixedAngY); // dumb reconversion back, I know
anglef *= flip ? -1 : 1; // Adjust for flipping
@ -1708,9 +1717,19 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2);
// rotation axes relative to camera
p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
pitchR = FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT);
rollR = FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT);
p.rollx = FIXED_TO_FLOAT((fixed_t)rollR);
p.rollz = FIXED_TO_FLOAT((fixed_t)pitchR);
// convert to angles
pitchR = FixedAngle((fixed_t)pitchR);
rollR = FixedAngle((fixed_t)rollR);
}
// make this a proper angle now
fixedAngY = FixedAngle(fixedAngY);
}
p.anglez = FIXED_TO_FLOAT(AngleFixed(R_InterpolateAngle(spr->mobj->old_pitch, spr->mobj->pitch)));
@ -1744,6 +1763,88 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.y += ox * gl_viewcos;
p.z += oy;
if (R_ThingIsUsingBakedOffsets(spr->mobj))
{
// visoffset stuff
float xx, xy, yx, yy;
float zx, zy, zz;
float xpiv, ypiv, zpiv;
fixed_t zh;
fixed_t xoffs, yoffs;
// xoffs = (cos(xoff) + sin(yoff))
xoffs =
FixedMul(spr->mobj->bakeyoff, -FINECOSINE(fixedAngY >> ANGLETOFINESHIFT)) +
FixedMul(spr->mobj->bakexoff, FINESINE(fixedAngY >> ANGLETOFINESHIFT));
// yoffs = (-sin(xoff) + cos(yoff))
yoffs =
FixedMul(spr->mobj->bakeyoff, -FINESINE(fixedAngY >> ANGLETOFINESHIFT)) +
FixedMul(spr->mobj->bakexoff, FINECOSINE(fixedAngY >> ANGLETOFINESHIFT));
const fixed_t hflipmul = hflip ? -FRACUNIT : FRACUNIT;
xpiv = FIXED_TO_FLOAT(
FixedMul(
FixedMul(spr->mobj->bakeypiv,
-FINECOSINE(fixedAngY >> ANGLETOFINESHIFT)) +
FixedMul(spr->mobj->bakexpiv,
FINESINE(fixedAngY >> ANGLETOFINESHIFT)),
hflipmul));
ypiv = FIXED_TO_FLOAT(
FixedMul(
FixedMul(spr->mobj->bakeypiv,
-FINESINE(fixedAngY >> ANGLETOFINESHIFT)) +
FixedMul(spr->mobj->bakexpiv,
FINECOSINE(fixedAngY >> ANGLETOFINESHIFT)),
hflipmul));
zpiv = FIXED_TO_FLOAT(spr->mobj->bakezpiv * ((flip) ? -1 : 1));
pitchR = ((pitchR + spr->mobj->pitch) * ((flip) ? -1 : 1));
rollR = ((rollR + spr->mobj->roll) * ((flip) ? -1 : 1));
// x offset
xx = FIXED_TO_FLOAT(FixedMul(FixedMul(
FixedMul(xoffs,spr->mobj->spritexscale),
hflipmul),
FINECOSINE(pitchR >> ANGLETOFINESHIFT)
));
xy = FIXED_TO_FLOAT(FixedMul(FixedMul(
FixedMul(xoffs,spr->mobj->spritexscale),
hflipmul),
-FINESINE(pitchR >> ANGLETOFINESHIFT)
));
// y offset
yx = FIXED_TO_FLOAT(FixedMul(FixedMul(
FixedMul(yoffs,spr->mobj->spritexscale),
hflipmul),
FINECOSINE(rollR >> ANGLETOFINESHIFT)
));
yy = FIXED_TO_FLOAT(FixedMul(FixedMul(
FixedMul(yoffs,spr->mobj->spritexscale),
hflipmul),
-FINESINE(rollR >> ANGLETOFINESHIFT)
));
// z offset
zh = FixedMul(FixedMul(spr->mobj->bakezoff,spr->mobj->spriteyscale),
FINECOSINE(rollR >> ANGLETOFINESHIFT));
zz = FIXED_TO_FLOAT(FixedMul(zh,
FINECOSINE(pitchR >> ANGLETOFINESHIFT)));
zx = FIXED_TO_FLOAT(FixedMul(zh,
FINESINE(pitchR >> ANGLETOFINESHIFT)));
zy = FIXED_TO_FLOAT(FixedMul(zh,
FINESINE(rollR >> ANGLETOFINESHIFT)));
// do these namings even make sense at this point?
p.x += xx + zx + xpiv;
p.z += (xy + yy + zz * (flip ? -1 : 1)) + zpiv;
p.y += yx + zy + ypiv;
}
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, hflip, &Surf);
}
}

View file

@ -6477,6 +6477,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->mo->spritexoffset = 0;
player->mo->spriteyoffset = 0;
player->mo->bakexoff = 0;
player->mo->bakeyoff = 0;
player->mo->bakezoff = 0;
player->mo->bakexpiv = 0;
player->mo->bakeypiv = 0;
player->mo->bakezpiv = 0;
player->cameraOffset = 0;
if (player->loop.radius)

View file

@ -103,6 +103,12 @@ enum mobj_e {
mobj_sprxoff,
mobj_spryoff,
mobj_sprzoff,
mobj_bakexoff,
mobj_bakeyoff,
mobj_bakezoff,
mobj_bakexpiv,
mobj_bakeypiv,
mobj_bakezpiv,
mobj_terrain,
mobj_dispoffset,
mobj_tid,
@ -192,6 +198,12 @@ static const char *const mobj_opt[] = {
"sprxoff",
"spryoff",
"sprzoff",
"bakexoff",
"bakeyoff",
"bakezoff",
"bakexpiv",
"bakeypiv",
"bakezpiv",
"terrain",
"dispoffset",
"tid",
@ -542,6 +554,24 @@ static int mobj_get(lua_State *L)
case mobj_sprzoff:
lua_pushfixed(L, mo->sprzoff);
break;
case mobj_bakexoff:
lua_pushfixed(L, mo->bakexoff);
break;
case mobj_bakeyoff:
lua_pushfixed(L, mo->bakeyoff);
break;
case mobj_bakezoff:
lua_pushfixed(L, mo->bakezoff);
break;
case mobj_bakexpiv:
lua_pushfixed(L, mo->bakexpiv);
break;
case mobj_bakeypiv:
lua_pushfixed(L, mo->bakeypiv);
break;
case mobj_bakezpiv:
lua_pushfixed(L, mo->bakezpiv);
break;
case mobj_terrain:
LUA_PushUserdata(L, mo->terrain, META_TERRAIN);
break;
@ -982,6 +1012,24 @@ static int mobj_set(lua_State *L)
case mobj_sprzoff:
mo->sprzoff = luaL_checkfixed(L, 3);
break;
case mobj_bakexoff:
mo->bakexoff = luaL_checkfixed(L, 3);
break;
case mobj_bakeyoff:
mo->bakeyoff = luaL_checkfixed(L, 3);
break;
case mobj_bakezoff:
mo->bakezoff = luaL_checkfixed(L, 3);
break;
case mobj_bakexpiv:
mo->bakexpiv = luaL_checkfixed(L, 3);
break;
case mobj_bakeypiv:
mo->bakeypiv = luaL_checkfixed(L, 3);
break;
case mobj_bakezpiv:
mo->bakezpiv = luaL_checkfixed(L, 3);
break;
case mobj_terrain:
mo->terrain = *((terrain_t **)luaL_checkudata(L, 3, META_TERRAIN));
break;

View file

@ -321,6 +321,7 @@ void P_RunOverlays(void);
#define OV_DONT3DOFFSET 1<<1
#define OV_DONTXYSCALE 1<<2
#define OV_DONTROLL 1<<3
#define OV_DONTBAKEOFFSET 1<<4
void P_HandleMinecartSegments(mobj_t *mobj);
void P_MobjThinker(mobj_t *mobj);

View file

@ -6740,6 +6740,19 @@ void P_RunOverlays(void)
mo->roll = mo->target->roll;
}
if (!(mo->threshold & OV_DONTBAKEOFFSET))
{
// offsets
mo->bakexoff = mo->target->bakexoff;
mo->bakeyoff = mo->target->bakeyoff;
mo->bakezoff = mo->target->bakezoff;
// pivots
mo->bakexpiv = mo->target->bakexpiv;
mo->bakeypiv = mo->target->bakeypiv;
mo->bakezpiv = mo->target->bakezpiv;
}
if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP))
mo->flags ^= MF_DONTENCOREMAP;

View file

@ -421,6 +421,8 @@ struct mobj_t
UINT8 shadowcolor; // Palette index to use for rendering the shadow
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
fixed_t bakexoff, bakeyoff, bakezoff; // BAKED sprite offsets. Simulates visuals in real space, and rotates along the object's sprite
fixed_t bakexpiv, bakeypiv, bakezpiv; // Pivot points for baked offsets. These are *not* rotated with a sprite
terrain_t *terrain; // Terrain definition of the floor this object last hit. NULL when in the air.
mobj_t *terrainOverlay; // Overlay sprite object for terrain

View file

@ -2071,7 +2071,7 @@ typedef enum
{
MD3_GRAVITY = 1,
MD3_MISCCAP = 1<<1,
MD3_BAKEDOFFSET = 1<<2,
} mobj_diff3_t;
typedef enum
@ -2383,6 +2383,9 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff3 |= MD3_GRAVITY;
if (mobj == misccap)
diff3 |= MD3_MISCCAP;
if (mobj->bakexoff || mobj->bakeyoff || mobj->bakezoff || mobj->bakexpiv ||
mobj->bakeypiv || mobj->bakezpiv)
diff3 |= MD3_BAKEDOFFSET;
if (diff3 != 0)
diff2 |= MD2_MORE;
@ -2658,6 +2661,15 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
{
WRITEFIXED(save->p, mobj->gravity);
}
if (diff3 & MD3_BAKEDOFFSET)
{
WRITEFIXED(save->p, mobj->bakexoff);
WRITEFIXED(save->p, mobj->bakeyoff);
WRITEFIXED(save->p, mobj->bakezoff);
WRITEFIXED(save->p, mobj->bakexpiv);
WRITEFIXED(save->p, mobj->bakeypiv);
WRITEFIXED(save->p, mobj->bakezpiv);
}
WRITEUINT32(save->p, mobj->mobjnum);
}
@ -3914,6 +3926,20 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
{
mobj->gravity = FRACUNIT;
}
if (diff3 & MD3_BAKEDOFFSET)
{
mobj->bakexoff = READFIXED(save->p);
mobj->bakeyoff = READFIXED(save->p);
mobj->bakezoff = READFIXED(save->p);
mobj->bakexpiv = READFIXED(save->p);
mobj->bakeypiv = READFIXED(save->p);
mobj->bakezpiv = READFIXED(save->p);
}
else
{
mobj->bakexoff = mobj->bakeyoff = mobj->bakezoff = 0;
mobj->bakexpiv = mobj->bakeypiv = mobj->bakezpiv = 0;
}
// Reset some non-synch values
mobj->sloperoll = 0;

View file

@ -1219,6 +1219,15 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->sprxoff = mobj->sprxoff;
ghost->spryoff = mobj->spryoff;
ghost->sprzoff = mobj->sprzoff;
// baked offsets
ghost->bakexoff = mobj->bakexoff;
ghost->bakeyoff = mobj->bakeyoff;
ghost->bakezoff = mobj->bakezoff;
ghost->bakexpiv = mobj->bakexpiv;
ghost->bakeypiv = mobj->bakeypiv;
ghost->bakezpiv = mobj->bakezpiv;
ghost->rollangle = mobj->rollangle;
ghost->spritexscale = mobj->spritexscale;

View file

@ -50,6 +50,11 @@ boolean R_IsOverlayingInvinciblePlayer(mobj_t* mobj);
angle_t R_GetPitchRollAngle(mobj_t *mobj, player_t *viewPlayer, interpmobjstate_t *interp);
angle_t R_ModelRotationAngle(mobj_t *mobj, player_t *viewPlayer);
angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer, interpmobjstate_t *interp);
vector2_t* R_RotateSpriteOffsetsByPitchRoll(
mobj_t* mobj,
boolean vflip,
boolean hflip,
vector2_t* out);
#endif
#ifdef __cplusplus

View file

@ -26,8 +26,8 @@ fixed_t rollsinang[ROTANGLES];
angle_t R_GetPitchRollAngle(mobj_t *mobj, player_t *viewPlayer, interpmobjstate_t *interp)
{
angle_t viewingAngle, rollOrPitch;
angle_t sloperoll = interp->slopepitch;
angle_t slopepitch = interp->sloperoll;
angle_t sloperoll = !interp ? 0 : interp->slopepitch;
angle_t slopepitch = !interp ? 0 : interp->sloperoll;
fixed_t pitchMul, rollMul;
if (mobj->player)
@ -131,6 +131,98 @@ INT32 R_GetRollAngle(angle_t rollangle)
return ra;
}
#define VISROTMUL (ANG1 * ROTANGDIFF)
vector2_t* R_RotateSpriteOffsetsByPitchRoll(
mobj_t* mobj,
boolean vflip,
boolean hflip,
vector2_t* out)
{
fixed_t rotcos, rotsin, finx, finy;
vector2_t xvec, yvec;
// input offsets
fixed_t xoffs, yoffs, xpiv, ypiv;
// final offsets
INT16 visx, visy, visz;
INT16 vxpiv, vypiv;
// visual rotation
angle_t visrollang;
// camera angle
angle_t viewingAngle = R_PointToAngle(mobj->x, mobj->y);
// rotate ourselves entirely by the sprite's own rotation angle
angle_t visrot = R_SpriteRotationAngle(mobj, NULL, NULL);
// xoffs = (-cos(xoff) + sin(yoff))
xoffs =
FixedMul(mobj->bakeyoff, -FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)) +
FixedMul(mobj->bakexoff, FINESINE(mobj->angle >> ANGLETOFINESHIFT));
xpiv =
FixedMul(mobj->bakeypiv, -FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)) +
FixedMul(mobj->bakexpiv, FINESINE(mobj->angle >> ANGLETOFINESHIFT));
// yoffs = (-sin(yoff) + cos(xoff))
yoffs =
FixedMul(mobj->bakeyoff, -FINESINE(mobj->angle >> ANGLETOFINESHIFT)) +
FixedMul(mobj->bakexoff, FINECOSINE(mobj->angle >> ANGLETOFINESHIFT));
ypiv =
FixedMul(mobj->bakeypiv, -FINESINE(mobj->angle >> ANGLETOFINESHIFT)) +
FixedMul(mobj->bakexpiv, FINECOSINE(mobj->angle >> ANGLETOFINESHIFT));
visrollang = (R_GetRollAngle(visrot) * VISROTMUL) * (hflip ? -1 : 1);
// get pitch and roll multipliers, mainly used to align the
// viewpoint with the camera
fixed_t pitchMul = -FINESINE(viewingAngle >> ANGLETOFINESHIFT);
fixed_t rollMul = FINECOSINE(viewingAngle >> ANGLETOFINESHIFT);
// get visual positions
visz = visy = visx = 0;
visz = (INT16)(-(mobj->bakezoff / FRACUNIT));
visx = (INT16)(FixedMul((yoffs / FRACUNIT), rollMul));
visy = (INT16)(FixedMul((xoffs / FRACUNIT), pitchMul));
vxpiv = (INT16)(FixedMul((ypiv / FRACUNIT), rollMul));
vypiv = (INT16)(FixedMul((xpiv / FRACUNIT), pitchMul));
// rotate by rollangle
finx = (visx + visy);
finy = -visz;
rotcos = FINECOSINE(visrollang >> ANGLETOFINESHIFT);
rotsin = FINESINE(visrollang >> ANGLETOFINESHIFT);
xvec.x = FixedMul(finx, rotcos);
xvec.y = FixedMul(finx, -rotsin);
yvec.x = FixedMul(finy, rotsin);
yvec.y = FixedMul(finy, -rotcos);
// set finalized offsets
out->x = (fixed_t)(xvec.x + yvec.x + vxpiv + vypiv);
out->y = (fixed_t)(xvec.y - yvec.y) + (mobj->bakezpiv / FRACUNIT);
// flip based on vflip and hflip
// flip the view angle if we're horizontally flipped
if (hflip)
{
out->x *= -1;
}
if (vflip)
{
out->y *= -1;
}
return out;
}
#undef VISROTMUL
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip)
{
rotsprite_t *rotsprite = patch->rotated;

View file

@ -854,6 +854,12 @@ boolean R_ThingIsFlashing(mobj_t *thing)
baddie_is_flashing(thing);
}
boolean R_ThingIsUsingBakedOffsets(mobj_t* thing)
{
return ((thing->bakexoff) || (thing->bakeyoff) || (thing->bakezoff) ||
(thing->bakexpiv) || (thing->bakeypiv) || (thing->bakezpiv));
}
UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
{
if (!(vis->cut & SC_PRECIP) &&
@ -1734,6 +1740,7 @@ static void R_ProjectSprite(mobj_t *thing)
patch_t *rotsprite = NULL;
INT32 rollangle = 0;
angle_t spriterotangle = 0;
vector2_t visoffs;
#endif
// uncapped/interpolation
@ -1923,10 +1930,28 @@ static void R_ProjectSprite(mobj_t *thing)
if (spritexscale < 1 || spriteyscale < 1)
return;
#ifdef ROTSPRITE
// initialize and rotate pitch/roll vector
visoffs.x = 0;
visoffs.y = 0;
const fixed_t visoffymul = (vflip ? -FRACUNIT : FRACUNIT);
if (R_ThingIsUsingBakedOffsets(thing))
{
R_RotateSpriteOffsetsByPitchRoll(thing,
vflip, hflip, &visoffs);
}
#endif
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
{
spr_offset = interp.spritexoffset;
#ifdef ROTSPRITE
spr_topoffset = (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul), mapobjectscale));
#else
spr_topoffset = interp.spriteyoffset;
#endif
}
else
{
@ -1935,8 +1960,13 @@ static void R_ProjectSprite(mobj_t *thing)
if ((thing->renderflags & RF_FLIPOFFSETS) && flip)
flipoffset = -1;
spr_offset += interp.spritexoffset * flipoffset;
spr_offset += (interp.spritexoffset) * flipoffset;
#ifdef ROTSPRITE
spr_topoffset += (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul),
mapobjectscale)) * flipoffset;
#else
spr_topoffset += interp.spriteyoffset * flipoffset;
#endif
}
if (flip)
@ -1944,6 +1974,13 @@ static void R_ProjectSprite(mobj_t *thing)
else
offset = -spr_offset;
#ifdef ROTSPRITE
if (visoffs.x)
{
offset -= FixedDiv((visoffs.x * FRACUNIT), mapobjectscale);
}
#endif
offset = FixedMul(offset, FixedMul(spritexscale, this_scale));
offset2 = FixedMul(spr_width, FixedMul(spritexscale, this_scale));

View file

@ -95,6 +95,8 @@ boolean R_ThingIsFullDark (mobj_t *thing);
boolean R_ThingIsFlashing(mobj_t *thing);
boolean R_ThingIsUsingBakedOffsets(mobj_t *thing);
INT32 R_ThingLightLevel(mobj_t *thing);
// --------------