From 82a0e954852fd35ec1eac813752a8fb74a8ef58f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 26 Nov 2020 17:19:42 +0100 Subject: [PATCH] - made the new interpolation system work in Blood. The panning interpolations need wraparuound handling due to their small value range. --- source/blood/src/animatesprite.cpp | 2 +- source/blood/src/blood.cpp | 4 +- source/blood/src/nnexts.cpp | 12 ++++ source/blood/src/sectorfx.cpp | 19 +++++++ source/blood/src/triggers.cpp | 2 +- source/blood/src/view.cpp | 89 +----------------------------- source/blood/src/view.h | 36 +++--------- source/blood/src/warp.cpp | 4 +- source/core/interpolate.cpp | 59 +++++++++++++++++--- source/core/interpolate.h | 15 +++-- 10 files changed, 109 insertions(+), 133 deletions(-) diff --git a/source/blood/src/animatesprite.cpp b/source/blood/src/animatesprite.cpp index 6a450edbc..7a94dd65d 100644 --- a/source/blood/src/animatesprite.cpp +++ b/source/blood/src/animatesprite.cpp @@ -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; diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index a89d146e3..90ae275c8 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -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()))) { diff --git a/source/blood/src/nnexts.cpp b/source/blood/src/nnexts.cpp index 635a51fd5..484ac2320 100644 --- a/source/blood/src/nnexts.cpp +++ b/source/blood/src/nnexts.cpp @@ -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; + } } } diff --git a/source/blood/src/sectorfx.cpp b/source/blood/src/sectorfx.cpp index a1a28e384..ee9f2d9ac 100644 --- a/source/blood/src/sectorfx.cpp +++ b/source/blood/src/sectorfx.cpp @@ -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); + } } } } diff --git a/source/blood/src/triggers.cpp b/source/blood/src/triggers.cpp index 9ed9f4ac3..de771e20c 100644 --- a/source/blood/src/triggers.cpp +++ b/source/blood/src/triggers.cpp @@ -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) { diff --git a/source/blood/src/view.cpp b/source/blood/src/view.cpp index 8cd5723cb..3c3f67c8a 100644 --- a/source/blood/src/view.cpp +++ b/source/blood/src/view.cpp @@ -50,27 +50,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS - +FixedBitArray 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) diff --git a/source/blood/src/view.h b/source/blood/src/view.h index 7e1822c03..642d31a34 100644 --- a/source/blood/src/view.h +++ b/source/blood/src/view.h @@ -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 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); } } diff --git a/source/blood/src/warp.cpp b/source/blood/src/warp.cpp index 18a81141c..17572618f 100644 --- a/source/blood/src/warp.cpp +++ b/source/blood/src/warp.cpp @@ -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; } } diff --git a/source/core/interpolate.cpp b/source/core/interpolate.cpp index bd6d388a1..902ac7247 100644 --- a/source/core/interpolate.cpp +++ b/source/core/interpolate.cpp @@ -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)) diff --git a/source/core/interpolate.h b/source/core/interpolate.h index b5095ca49..401e978d5 100644 --- a/source/core/interpolate.h +++ b/source/core/interpolate.h @@ -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);