- made the new interpolation system work in Blood.

The panning interpolations need wraparuound handling due to their small value range.
This commit is contained in:
Christoph Oelckers 2020-11-26 17:19:42 +01:00
parent 2cd3927613
commit 82a0e95485
10 changed files with 109 additions and 133 deletions

View file

@ -468,7 +468,7 @@ void viewProcessSprites(int32_t cX, int32_t cY, int32_t cZ, int32_t cA, int32_t
}
int nSprite = pTSprite->owner;
if (cl_interpolate && TestBitString(gInterpolateSprite, nSprite) && !(pTSprite->flags&512))
if (cl_interpolate && gInterpolateSprite[nSprite] && !(pTSprite->flags&512))
{
LOCATION *pPrevLoc = &gPrevSpriteLoc[nSprite];
int iInterpolate = (int)gInterpolate;

View file

@ -290,7 +290,9 @@ void GameInterface::Ticker()
if (newweap > 0 && newweap < WeaponSel_MaxBlood) gPlayer[i].newWeapon = newweap;
}
viewClearInterpolations();
gInterpolateSprite.Zero();
ClearMovementInterpolations();
UpdateInterpolations();
if (!(paused || (gGameOptions.nGameType == 0 && M_Active())))
{

View file

@ -2269,6 +2269,16 @@ void useSectorWindGen(XSPRITE* pXSource, sectortype* pSector) {
pXSector->panCeiling = true;
break;
}
if (pXSector->panCeiling)
{
StartInterpolation(pXSector->reference, Interp_Sect_CeilingPanX);
StartInterpolation(pXSector->reference, Interp_Sect_CeilingPanY);
}
if (pXSector->panFloor)
{
StartInterpolation(pXSector->reference, Interp_Sect_FloorPanX);
StartInterpolation(pXSector->reference, Interp_Sect_FloorPanY);
}
short oldPan = pXSector->panVel;
pXSector->panAngle = pXSector->windAng;
@ -2284,7 +2294,9 @@ void useSectorWindGen(XSPRITE* pXSource, sectortype* pSector) {
}
if (i == panCount)
{
panList[panCount++] = nXSector;
}
}
}

View file

@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "gameutil.h"
#include "globals.h"
#include "sectorfx.h"
#include "interpolate.h"
BEGIN_BLD_NS
@ -342,7 +343,21 @@ void InitSectorFX(void)
if (pXSector->amplitude)
shadeList[shadeCount++] = nXSector;
if (pXSector->panVel)
{
panList[panCount++] = nXSector;
if (pXSector->panCeiling)
{
StartInterpolation(i, Interp_Sect_CeilingPanX);
StartInterpolation(i, Interp_Sect_CeilingPanY);
}
if (pXSector->panFloor)
{
StartInterpolation(i, Interp_Sect_FloorPanX);
StartInterpolation(i, Interp_Sect_FloorPanY);
}
}
}
}
for (int i = 0; i < numwalls; i++)
@ -352,7 +367,11 @@ void InitSectorFX(void)
{
XWALL *pXWall = &xwall[nXWall];
if (pXWall->panXVel || pXWall->panYVel)
{
wallPanList[wallPanCount++] = nXWall;
if (pXWall->panXVel) StartInterpolation(i, Interp_Wall_PanX);
if (pXWall->panXVel) StartInterpolation(i, Interp_Wall_PanY);
}
}
}
}

View file

@ -1497,7 +1497,7 @@ void OperateTeleport(unsigned int nSector, XSECTOR *pXSector)
ChangeSpriteSect(nSprite, pDest->sectnum);
sfxPlay3DSound(pDest, 201, -1, 0);
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
ClearBitString(gInterpolateSprite, nSprite);
gInterpolateSprite.Clear(nSprite);
viewBackupSpriteLoc(nSprite, pSprite);
if (pPlayer)
{

View file

@ -50,27 +50,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
FixedBitArray<kMaxSprites> gInterpolateSprite;
VIEW gPrevView[kMaxPlayers];
VIEWPOS gViewPos;
int gViewIndex;
struct INTERPOLATE {
void *pointer;
int value;
int value2;
INTERPOLATE_TYPE type;
};
double gInterpolate;
int nInterpolations;
char gInterpolateSprite[(kMaxSprites+7)>>3];
char gInterpolateWall[(kMaxWalls+7)>>3];
char gInterpolateSector[(kMaxSectors+7)>>3];
enum { kMaxInterpolations = 16384 };
INTERPOLATE gInterpolation[kMaxInterpolations];
int gScreenTilt;
@ -131,76 +116,6 @@ void viewCorrectViewOffsets(int nPlayer, vec3_t const *oldpos)
pView->at38 += pPlayer->pSprite->z-oldpos->z;
}
void viewClearInterpolations(void)
{
nInterpolations = 0;
memset(gInterpolateSprite, 0, sizeof(gInterpolateSprite));
memset(gInterpolateWall, 0, sizeof(gInterpolateWall));
memset(gInterpolateSector, 0, sizeof(gInterpolateSector));
}
void viewAddInterpolation(void *data, INTERPOLATE_TYPE type)
{
if (nInterpolations == kMaxInterpolations)
I_Error("Too many interpolations");
INTERPOLATE *pInterpolate = &gInterpolation[nInterpolations++];
pInterpolate->pointer = data;
pInterpolate->type = type;
switch (type)
{
case INTERPOLATE_TYPE_INT:
pInterpolate->value = *((int*)data);
break;
case INTERPOLATE_TYPE_SHORT:
pInterpolate->value = *((short*)data);
break;
}
}
void CalcInterpolations(void)
{
int i;
INTERPOLATE *pInterpolate = gInterpolation;
for (i = 0; i < nInterpolations; i++, pInterpolate++)
{
switch (pInterpolate->type)
{
case INTERPOLATE_TYPE_INT:
{
pInterpolate->value2 = *((int*)pInterpolate->pointer);
int newValue = interpolate(pInterpolate->value, *((int*)pInterpolate->pointer), gInterpolate);
*((int*)pInterpolate->pointer) = newValue;
break;
}
case INTERPOLATE_TYPE_SHORT:
{
pInterpolate->value2 = *((short*)pInterpolate->pointer);
int newValue = interpolate(pInterpolate->value, *((short*)pInterpolate->pointer), gInterpolate);
*((short*)pInterpolate->pointer) = newValue;
break;
}
}
}
}
void RestoreInterpolations(void)
{
int i;
INTERPOLATE *pInterpolate = gInterpolation;
for (i = 0; i < nInterpolations; i++, pInterpolate++)
{
switch (pInterpolate->type)
{
case INTERPOLATE_TYPE_INT:
*((int*)pInterpolate->pointer) = pInterpolate->value2;
break;
case INTERPOLATE_TYPE_SHORT:
*((short*)pInterpolate->pointer) = pInterpolate->value2;
break;
}
}
}
void viewDrawText(int nFont, const char *pString, int x, int y, int nShade, int nPalette, int position, char shadow, unsigned int nStat, uint8_t alpha)
{
if (nFont < 0 || nFont >= kFontNum || !pString) return;
@ -603,7 +518,7 @@ void viewDrawScreen(bool sceneonly)
if (cl_interpolate)
{
CalcInterpolations();
DoInterpolations(gInterpolate / MaxSmoothRatio);
}
if (automapMode != am_full)

View file

@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "common_game.h"
#include "messages.h"
#include "player.h"
#include "interpolate.h"
BEGIN_BLD_NS
@ -101,11 +102,6 @@ enum VIEWPOS {
VIEWPOS_1
};
enum INTERPOLATE_TYPE {
INTERPOLATE_TYPE_INT = 0,
INTERPOLATE_TYPE_SHORT,
};
enum
{
kBackTile = 253,
@ -134,9 +130,7 @@ extern int gScreenTilt;
extern int deliriumTilt, deliriumTurn, deliriumPitch;
extern int gScreenTiltO, deliriumTurnO, deliriumPitchO;
extern int gShowFrameRate;
extern char gInterpolateSprite[];
extern char gInterpolateWall[];
extern char gInterpolateSector[];
extern FixedBitArray<kMaxSprites> gInterpolateSprite;
extern LOCATION gPrevSpriteLoc[kMaxSprites];
extern int gLastPal;
extern double gInterpolate;
@ -147,10 +141,6 @@ void viewUpdatePrediction(InputPacket *pInput);
void viewCorrectPrediction(void);
void viewBackupView(int nPlayer);
void viewCorrectViewOffsets(int nPlayer, vec3_t const *oldpos);
void viewClearInterpolations(void);
void viewAddInterpolation(void *data, INTERPOLATE_TYPE type);
void CalcInterpolations(void);
void RestoreInterpolations(void);
void viewDrawText(int nFont, const char *pString, int x, int y, int nShade, int nPalette, int position, char shadow, unsigned int nStat = 0, uint8_t alpha = 255);
void InitStatusBar(void);
void UpdateStatusBar();
@ -169,35 +159,27 @@ void viewSetSystemMessage(const char* pMessage, ...);
inline void viewInterpolateSector(int nSector, sectortype *pSector)
{
if (!TestBitString(gInterpolateSector, nSector))
{
viewAddInterpolation(&pSector->floorz, INTERPOLATE_TYPE_INT);
viewAddInterpolation(&pSector->ceilingz, INTERPOLATE_TYPE_INT);
viewAddInterpolation(&pSector->floorheinum, INTERPOLATE_TYPE_SHORT);
SetBitString(gInterpolateSector, nSector);
}
StartInterpolation(nSector, Interp_Sect_Floorz);
StartInterpolation(nSector, Interp_Sect_Ceilingz);
StartInterpolation(nSector, Interp_Sect_Floorheinum);
}
inline void viewInterpolateWall(int nWall, walltype *pWall)
{
if (!TestBitString(gInterpolateWall, nWall))
{
viewAddInterpolation(&pWall->x, INTERPOLATE_TYPE_INT);
viewAddInterpolation(&pWall->y, INTERPOLATE_TYPE_INT);
SetBitString(gInterpolateWall, nWall);
}
StartInterpolation(nWall, Interp_Wall_X);
StartInterpolation(nWall, Interp_Wall_Y);
}
inline void viewBackupSpriteLoc(int nSprite, spritetype *pSprite)
{
if (!TestBitString(gInterpolateSprite, nSprite))
if (!gInterpolateSprite[nSprite])
{
LOCATION *pPrevLoc = &gPrevSpriteLoc[nSprite];
pPrevLoc->x = pSprite->x;
pPrevLoc->y = pSprite->y;
pPrevLoc->z = pSprite->z;
pPrevLoc->ang = pSprite->ang;
SetBitString(gInterpolateSprite, nSprite);
gInterpolateSprite.Set(nSprite);
}
}

View file

@ -208,7 +208,7 @@ int CheckLink(spritetype *pSprite)
else
z2 = getceilzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
pSprite->z += z2-z;
ClearBitString(gInterpolateSprite, pSprite->index);
gInterpolateSprite.Clear(pSprite->index);
return pUpper->type;
}
}
@ -235,7 +235,7 @@ int CheckLink(spritetype *pSprite)
else
z2 = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
pSprite->z += z2-z;
ClearBitString(gInterpolateSprite, pSprite->index);
gInterpolateSprite.Clear(pSprite->index);
return pLower->type;
}
}

View file

@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "interpolate.h"
#include "xs_Float.h"
#include "serializer.h"
#include "gamecvars.h"
struct Interpolation
@ -50,8 +51,8 @@ double Get(int index, int type)
case Interp_Wall_X: return wall[index].x;
case Interp_Wall_Y: return wall[index].y;
case Interp_Wall_PanX: return 0/*wall[index].panx_*/; // later
case Interp_Wall_PanY: return 0/*wall[index].pany_*/; // later
case Interp_Wall_PanX: return wall[index].xpan_;
case Interp_Wall_PanY: return wall[index].ypan_;
case Interp_Sprite_Z: return sprite[index].z;
default: return 0;
@ -73,14 +74,14 @@ void Set(int index, int type, double val)
case Interp_Wall_X: wall[index].x = xs_CRoundToInt(val); break;
case Interp_Wall_Y: wall[index].y = xs_CRoundToInt(val); break;
case Interp_Wall_PanX: break;
case Interp_Wall_PanY: break;
case Interp_Wall_PanX: wall[index].xpan_ = float(val); break;
case Interp_Wall_PanY: wall[index].ypan_ = float(val); break;
case Interp_Sprite_Z: sprite[index].z = xs_CRoundToInt(val); break;
}
}
void SetInterpolation(int index, int type)
void StartInterpolation(int index, int type)
{
for (unsigned i = 0; i < interpolations.Size(); i++)
{
@ -115,25 +116,67 @@ void UpdateInterpolations()
}
}
void Dointerpolations(float smoothratio)
void DoInterpolations(double smoothratio)
{
if (!cl_interpolate) return;
for (unsigned i = 0; i < interpolations.Size(); i++)
{
double bak;
interpolations[i].bak = bak = Get(interpolations[i].index, interpolations[i].type);
double old = interpolations[i].old;
Set(interpolations[i].index, interpolations[i].type, old + (bak - old) * smoothratio);
if (interpolations[i].type < Interp_Pan_First || fabs(bak-old) < 128.)
{
Set(interpolations[i].index, interpolations[i].type, old + (bak - old) * smoothratio);
}
else
{
// with the panning types we need to check for potential wraparound.
if (bak < old) bak += 256.;
else old += 256;
double cur = old + (bak - old) * smoothratio;
if (cur >= 256.) cur -= 256.;
Set(interpolations[i].index, interpolations[i].type, cur);
}
}
}
void RestoreInterpolations()
{
for (unsigned i = 0; i < interpolations.Size(); i++)
if (!cl_interpolate) return;
for (unsigned i = 0; i < interpolations.Size(); i++)
{
Set(interpolations[i].index, interpolations[i].type, interpolations[i].bak);
}
}
void ClearInterpolations()
{
interpolations.Clear();
}
void ClearMovementInterpolations()
{
// This clears all movement interpolations. Needed for Blood which destroys its interpolations each frame.
for (unsigned i = 0; i < interpolations.Size();)
{
switch (interpolations[i].type)
{
case Interp_Sect_Floorz:
case Interp_Sect_Ceilingz:
case Interp_Sect_Floorheinum:
case Interp_Sect_Ceilingheinum:
case Interp_Wall_X:
case Interp_Wall_Y:
interpolations[i] = interpolations.Last();
interpolations.Pop();
break;
default:
i++;
break;
}
}
}
FSerializer& Serialize(FSerializer& arc, const char* keyname, Interpolation& w, Interpolation* def)
{
if (arc.BeginObject(keyname))

View file

@ -7,23 +7,26 @@ enum EInterpolationType
Interp_Sect_Ceilingz,
Interp_Sect_Floorheinum,
Interp_Sect_Ceilingheinum,
Interp_Sect_FloorPanX,
Interp_Sect_FloorPanY,
Interp_Sect_CeilingPanX,
Interp_Sect_CeilingPanY,
Interp_Wall_X,
Interp_Wall_Y,
Interp_Wall_PanX,
Interp_Wall_PanY,
Interp_Sprite_Z,
Interp_Pan_First,
Interp_Sect_FloorPanX = Interp_Pan_First,
Interp_Sect_FloorPanY,
Interp_Sect_CeilingPanX,
Interp_Sect_CeilingPanY,
Interp_Wall_PanX,
Interp_Wall_PanY,
};
void StartInterpolation(int index, int type);
void StopInterpolation(int index, int type);
void UpdateInterpolations();
void ClearInterpolations();
void ClearMovementInterpolations();
void DoInterpolations(double smoothratio);
void RestoreInterpolations();
void SerializeInterpolations(FSerializer& arc);