- 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; 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]; LOCATION *pPrevLoc = &gPrevSpriteLoc[nSprite];
int iInterpolate = (int)gInterpolate; int iInterpolate = (int)gInterpolate;

View file

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

View file

@ -2269,6 +2269,16 @@ void useSectorWindGen(XSPRITE* pXSource, sectortype* pSector) {
pXSector->panCeiling = true; pXSector->panCeiling = true;
break; 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; short oldPan = pXSector->panVel;
pXSector->panAngle = pXSector->windAng; pXSector->panAngle = pXSector->windAng;
@ -2284,7 +2294,9 @@ void useSectorWindGen(XSPRITE* pXSource, sectortype* pSector) {
} }
if (i == panCount) if (i == panCount)
{
panList[panCount++] = nXSector; 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 "gameutil.h"
#include "globals.h" #include "globals.h"
#include "sectorfx.h" #include "sectorfx.h"
#include "interpolate.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -342,7 +343,21 @@ void InitSectorFX(void)
if (pXSector->amplitude) if (pXSector->amplitude)
shadeList[shadeCount++] = nXSector; shadeList[shadeCount++] = nXSector;
if (pXSector->panVel) if (pXSector->panVel)
{
panList[panCount++] = nXSector; 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++) for (int i = 0; i < numwalls; i++)
@ -352,7 +367,11 @@ void InitSectorFX(void)
{ {
XWALL *pXWall = &xwall[nXWall]; XWALL *pXWall = &xwall[nXWall];
if (pXWall->panXVel || pXWall->panYVel) if (pXWall->panXVel || pXWall->panYVel)
{
wallPanList[wallPanCount++] = nXWall; 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); ChangeSpriteSect(nSprite, pDest->sectnum);
sfxPlay3DSound(pDest, 201, -1, 0); sfxPlay3DSound(pDest, 201, -1, 0);
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0; xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
ClearBitString(gInterpolateSprite, nSprite); gInterpolateSprite.Clear(nSprite);
viewBackupSpriteLoc(nSprite, pSprite); viewBackupSpriteLoc(nSprite, pSprite);
if (pPlayer) if (pPlayer)
{ {

View file

@ -50,27 +50,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
FixedBitArray<kMaxSprites> gInterpolateSprite;
VIEW gPrevView[kMaxPlayers]; VIEW gPrevView[kMaxPlayers];
VIEWPOS gViewPos; VIEWPOS gViewPos;
int gViewIndex; int gViewIndex;
struct INTERPOLATE {
void *pointer;
int value;
int value2;
INTERPOLATE_TYPE type;
};
double gInterpolate; 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; int gScreenTilt;
@ -131,76 +116,6 @@ void viewCorrectViewOffsets(int nPlayer, vec3_t const *oldpos)
pView->at38 += pPlayer->pSprite->z-oldpos->z; 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) 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; if (nFont < 0 || nFont >= kFontNum || !pString) return;
@ -603,7 +518,7 @@ void viewDrawScreen(bool sceneonly)
if (cl_interpolate) if (cl_interpolate)
{ {
CalcInterpolations(); DoInterpolations(gInterpolate / MaxSmoothRatio);
} }
if (automapMode != am_full) 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 "common_game.h"
#include "messages.h" #include "messages.h"
#include "player.h" #include "player.h"
#include "interpolate.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -101,11 +102,6 @@ enum VIEWPOS {
VIEWPOS_1 VIEWPOS_1
}; };
enum INTERPOLATE_TYPE {
INTERPOLATE_TYPE_INT = 0,
INTERPOLATE_TYPE_SHORT,
};
enum enum
{ {
kBackTile = 253, kBackTile = 253,
@ -134,9 +130,7 @@ extern int gScreenTilt;
extern int deliriumTilt, deliriumTurn, deliriumPitch; extern int deliriumTilt, deliriumTurn, deliriumPitch;
extern int gScreenTiltO, deliriumTurnO, deliriumPitchO; extern int gScreenTiltO, deliriumTurnO, deliriumPitchO;
extern int gShowFrameRate; extern int gShowFrameRate;
extern char gInterpolateSprite[]; extern FixedBitArray<kMaxSprites> gInterpolateSprite;
extern char gInterpolateWall[];
extern char gInterpolateSector[];
extern LOCATION gPrevSpriteLoc[kMaxSprites]; extern LOCATION gPrevSpriteLoc[kMaxSprites];
extern int gLastPal; extern int gLastPal;
extern double gInterpolate; extern double gInterpolate;
@ -147,10 +141,6 @@ void viewUpdatePrediction(InputPacket *pInput);
void viewCorrectPrediction(void); void viewCorrectPrediction(void);
void viewBackupView(int nPlayer); void viewBackupView(int nPlayer);
void viewCorrectViewOffsets(int nPlayer, vec3_t const *oldpos); 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 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 InitStatusBar(void);
void UpdateStatusBar(); void UpdateStatusBar();
@ -169,35 +159,27 @@ void viewSetSystemMessage(const char* pMessage, ...);
inline void viewInterpolateSector(int nSector, sectortype *pSector) inline void viewInterpolateSector(int nSector, sectortype *pSector)
{ {
if (!TestBitString(gInterpolateSector, nSector)) StartInterpolation(nSector, Interp_Sect_Floorz);
{ StartInterpolation(nSector, Interp_Sect_Ceilingz);
viewAddInterpolation(&pSector->floorz, INTERPOLATE_TYPE_INT); StartInterpolation(nSector, Interp_Sect_Floorheinum);
viewAddInterpolation(&pSector->ceilingz, INTERPOLATE_TYPE_INT);
viewAddInterpolation(&pSector->floorheinum, INTERPOLATE_TYPE_SHORT);
SetBitString(gInterpolateSector, nSector);
}
} }
inline void viewInterpolateWall(int nWall, walltype *pWall) inline void viewInterpolateWall(int nWall, walltype *pWall)
{ {
if (!TestBitString(gInterpolateWall, nWall)) StartInterpolation(nWall, Interp_Wall_X);
{ StartInterpolation(nWall, Interp_Wall_Y);
viewAddInterpolation(&pWall->x, INTERPOLATE_TYPE_INT);
viewAddInterpolation(&pWall->y, INTERPOLATE_TYPE_INT);
SetBitString(gInterpolateWall, nWall);
}
} }
inline void viewBackupSpriteLoc(int nSprite, spritetype *pSprite) inline void viewBackupSpriteLoc(int nSprite, spritetype *pSprite)
{ {
if (!TestBitString(gInterpolateSprite, nSprite)) if (!gInterpolateSprite[nSprite])
{ {
LOCATION *pPrevLoc = &gPrevSpriteLoc[nSprite]; LOCATION *pPrevLoc = &gPrevSpriteLoc[nSprite];
pPrevLoc->x = pSprite->x; pPrevLoc->x = pSprite->x;
pPrevLoc->y = pSprite->y; pPrevLoc->y = pSprite->y;
pPrevLoc->z = pSprite->z; pPrevLoc->z = pSprite->z;
pPrevLoc->ang = pSprite->ang; pPrevLoc->ang = pSprite->ang;
SetBitString(gInterpolateSprite, nSprite); gInterpolateSprite.Set(nSprite);
} }
} }

View file

@ -208,7 +208,7 @@ int CheckLink(spritetype *pSprite)
else else
z2 = getceilzofslope(pSprite->sectnum, pSprite->x, pSprite->y); z2 = getceilzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
pSprite->z += z2-z; pSprite->z += z2-z;
ClearBitString(gInterpolateSprite, pSprite->index); gInterpolateSprite.Clear(pSprite->index);
return pUpper->type; return pUpper->type;
} }
} }
@ -235,7 +235,7 @@ int CheckLink(spritetype *pSprite)
else else
z2 = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y); z2 = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
pSprite->z += z2-z; pSprite->z += z2-z;
ClearBitString(gInterpolateSprite, pSprite->index); gInterpolateSprite.Clear(pSprite->index);
return pLower->type; 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 "interpolate.h"
#include "xs_Float.h" #include "xs_Float.h"
#include "serializer.h" #include "serializer.h"
#include "gamecvars.h"
struct Interpolation struct Interpolation
@ -50,8 +51,8 @@ double Get(int index, int type)
case Interp_Wall_X: return wall[index].x; case Interp_Wall_X: return wall[index].x;
case Interp_Wall_Y: return wall[index].y; case Interp_Wall_Y: return wall[index].y;
case Interp_Wall_PanX: return 0/*wall[index].panx_*/; // later case Interp_Wall_PanX: return wall[index].xpan_;
case Interp_Wall_PanY: return 0/*wall[index].pany_*/; // later case Interp_Wall_PanY: return wall[index].ypan_;
case Interp_Sprite_Z: return sprite[index].z; case Interp_Sprite_Z: return sprite[index].z;
default: return 0; 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_X: wall[index].x = xs_CRoundToInt(val); break;
case Interp_Wall_Y: wall[index].y = xs_CRoundToInt(val); break; case Interp_Wall_Y: wall[index].y = xs_CRoundToInt(val); break;
case Interp_Wall_PanX: break; case Interp_Wall_PanX: wall[index].xpan_ = float(val); break;
case Interp_Wall_PanY: break; case Interp_Wall_PanY: wall[index].ypan_ = float(val); break;
case Interp_Sprite_Z: sprite[index].z = xs_CRoundToInt(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++) 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++) for (unsigned i = 0; i < interpolations.Size(); i++)
{ {
double bak; double bak;
interpolations[i].bak = bak = Get(interpolations[i].index, interpolations[i].type); interpolations[i].bak = bak = Get(interpolations[i].index, interpolations[i].type);
double old = interpolations[i].old; 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() 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); 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) FSerializer& Serialize(FSerializer& arc, const char* keyname, Interpolation& w, Interpolation* def)
{ {
if (arc.BeginObject(keyname)) if (arc.BeginObject(keyname))

View file

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