diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2f8db45a7..3aa31663d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,14 @@ +June 4, 2008 (Changes by Graf Zahl) +- While doing the interpolation rewrite I noticed that DScroller and DPolyAction + were doing some things in their destructor that needed to be done in the + Destroy method. +- Rewrote the interpolation code. Interpolations are no longer some objects + that are separate from the rest of the engine. Instead, they are owned by + the thinkers starting them. Also, polyobjects only spawn a single interpolation + for each polyobject instead of a single one for each vertex. + Also, different types of interpolation objects are used for different types + of interpolation so that they can do some additional work if eventually needed. + June 3, 2008 (Changes by Graf Zahl) - Fixed: MAPINFO's 'lookup' option should only work for actual strings but not for lump and file names. diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 865ce8025..118aefb34 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -26,6 +26,7 @@ #include "gi.h" #include "p_local.h" #include "p_3dmidtex.h" +#include "r_interpolate.h" IMPLEMENT_CLASS (DSectorEffect) @@ -41,12 +42,10 @@ void DSectorEffect::Destroy() if (m_Sector->floordata == this) { m_Sector->floordata = NULL; - stopinterpolation (INTERP_SectorFloor, m_Sector); } if (m_Sector->ceilingdata == this) { m_Sector->ceilingdata = NULL; - stopinterpolation (INTERP_SectorCeiling, m_Sector); } if (m_Sector->lightingdata == this) { @@ -67,7 +66,9 @@ void DSectorEffect::Serialize (FArchive &arc) arc << m_Sector; } -IMPLEMENT_CLASS (DMover) +IMPLEMENT_POINTY_CLASS (DMover) + DECLARE_POINTER(interpolation) +END_POINTERS DMover::DMover () { @@ -76,8 +77,32 @@ DMover::DMover () DMover::DMover (sector_t *sector) : DSectorEffect (sector) { + interpolation = NULL; } +void DMover::Destroy() +{ + StopInterpolation(); + Super::Destroy(); +} + +void DMover::Serialize (FArchive &arc) +{ + Super::Serialize (arc); + arc << interpolation; +} + +void DMover::StopInterpolation() +{ + if (interpolation != NULL) + { + interpolation->DelRef(); + interpolation = NULL; + } +} + + + IMPLEMENT_CLASS (DMovingFloor) DMovingFloor::DMovingFloor () @@ -88,7 +113,7 @@ DMovingFloor::DMovingFloor (sector_t *sector) : DMover (sector) { sector->floordata = this; - setinterpolation (INTERP_SectorFloor, sector); + interpolation = sector->SetInterpolation(sector_t::FloorMove, true); } IMPLEMENT_CLASS (DMovingCeiling) @@ -101,7 +126,7 @@ DMovingCeiling::DMovingCeiling (sector_t *sector) : DMover (sector) { sector->ceilingdata = this; - setinterpolation (INTERP_SectorCeiling, sector); + interpolation = sector->SetInterpolation(sector_t::CeilingMove, true); } bool DMover::MoveAttached(int crush, fixed_t move, int floorOrCeiling, bool resetfailed) diff --git a/src/dsectoreffect.h b/src/dsectoreffect.h index 0a54f9e77..850af10df 100644 --- a/src/dsectoreffect.h +++ b/src/dsectoreffect.h @@ -24,15 +24,20 @@ protected: class DMover : public DSectorEffect { DECLARE_CLASS (DMover, DSectorEffect) + HAS_OBJECT_POINTERS public: DMover (sector_t *sector); protected: enum EResult { ok, crushed, pastdest }; + TObjPtr interpolation; private: bool MoveAttached(int crush, fixed_t move, int floorOrCeiling, bool resetfailed); EResult MovePlane (fixed_t speed, fixed_t dest, int crush, int floorOrCeiling, int direction, bool hexencrush); protected: DMover (); + void Serialize (FArchive &arc); + void Destroy(); + void StopInterpolation(); inline EResult MoveFloor (fixed_t speed, fixed_t dest, int crush, int direction, bool hexencrush) { return MovePlane (speed, dest, crush, 0, direction, hexencrush); diff --git a/src/g_level.cpp b/src/g_level.cpp index b07369f48..a885a965e 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -2744,7 +2744,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) P_SerializePolyobjs (arc); P_SerializeSounds (arc); StatusBar->Serialize (arc); - SerializeInterpolations (arc); + //SerializeInterpolations (arc); arc << level.total_monsters << level.total_items << level.total_secrets; diff --git a/src/p_3dmidtex.cpp b/src/p_3dmidtex.cpp index 4388c22a9..2cdb5016a 100644 --- a/src/p_3dmidtex.cpp +++ b/src/p_3dmidtex.cpp @@ -80,7 +80,7 @@ bool P_Scroll3dMidtex(sector_t *sector, int crush, fixed_t move, bool ceiling) // //============================================================================ -void P_Start3dMidtexInterpolations(sector_t *sector, bool ceiling) +void P_Start3dMidtexInterpolations(TArray &list, sector_t *sector, bool ceiling) { extsector_t::midtex::plane &scrollplane = ceiling? sector->e->Midtex.Ceiling : sector->e->Midtex.Floor; @@ -88,30 +88,8 @@ void P_Start3dMidtexInterpolations(sector_t *sector, bool ceiling) { line_t *l = scrollplane.AttachedLines[i]; - sides[l->sidenum[0]].SetInterpolation(side_t::mid); - sides[l->sidenum[1]].SetInterpolation(side_t::mid); - } -} - -//============================================================================ -// -// P_Stop3DMidtexInterpolations -// -// Stops interpolators for every sidedef that is being changed by moving -// this sector -// -//============================================================================ - -void P_Stop3dMidtexInterpolations(sector_t *sector, bool ceiling) -{ - extsector_t::midtex::plane &scrollplane = ceiling? sector->e->Midtex.Ceiling : sector->e->Midtex.Floor; - - for(unsigned i = 0; i < scrollplane.AttachedLines.Size(); i++) - { - line_t *l = scrollplane.AttachedLines[i]; - - sides[l->sidenum[0]].StopInterpolation(side_t::mid); - sides[l->sidenum[1]].StopInterpolation(side_t::mid); + list.Push(sides[l->sidenum[0]].SetInterpolation(side_t::mid)); + list.Push(sides[l->sidenum[1]].SetInterpolation(side_t::mid)); } } diff --git a/src/p_3dmidtex.h b/src/p_3dmidtex.h index 0b9497ec7..6b7201b7b 100644 --- a/src/p_3dmidtex.h +++ b/src/p_3dmidtex.h @@ -8,16 +8,14 @@ class AActor; bool P_Scroll3dMidtex(sector_t *sector, int crush, fixed_t move, bool ceiling); -void P_Start3dMidtexInterpolations(sector_t *sec, bool ceiling); -void P_Stop3dMidtexInterpolations(sector_t *sec, bool ceiling); +void P_Start3dMidtexInterpolations(TArray &list, sector_t *sec, bool ceiling); void P_Attach3dMidtexLinesToSector(sector_t *dest, int lineid, int tag, bool ceiling); bool P_GetMidTexturePosition(const line_t *line, int sideno, fixed_t *ptextop, fixed_t *ptexbot); bool P_Check3dMidSwitch(AActor *actor, line_t *line, int side); bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, fixed_t &opentop, fixed_t &openbottom); bool P_MoveLinkedSectors(sector_t *sector, int crush, fixed_t move, bool ceiling); -void P_StartLinkedSectorInterpolations(sector_t *sector, bool ceiling); -void P_StopLinkedSectorInterpolations(sector_t *sector, bool ceiling); +void P_StartLinkedSectorInterpolations(TArray &list, sector_t *sector, bool ceiling); bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype); void P_AddSectorLinksByID(sector_t *control, int id, INTBOOL ceiling); diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index ac51d6bf5..e13323f33 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -401,7 +401,7 @@ manual_ceiling: } if (ceiling->m_Speed >= movedist) { - stopinterpolation (INTERP_SectorCeiling, sec); + ceiling->StopInterpolation(); } // set texture/type change properties diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 2a5df44c9..8443cf908 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -138,7 +138,6 @@ void DDoor::Tick () case doorRaise: case doorClose: m_Sector->ceilingdata = NULL; //jff 2/22/98 - stopinterpolation (INTERP_SectorCeiling, m_Sector); Destroy (); // unlink and free break; @@ -190,7 +189,6 @@ void DDoor::Tick () case doorCloseWaitOpen: case doorOpen: m_Sector->ceilingdata = NULL; //jff 2/22/98 - stopinterpolation (INTERP_SectorCeiling, m_Sector); Destroy (); // unlink and free break; @@ -697,7 +695,7 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay) // The DMovingCeiling constructor automatically sets up an interpolation for us. // Stop it, since the ceiling is moving instantly here. - stopinterpolation (INTERP_SectorCeiling, sec); + StopInterpolation(); m_WhichDoorIndex = P_FindSlidingDoorType (sides[line->sidenum[0]].GetTexture(side_t::top)); if (m_WhichDoorIndex < 0) { diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 232d2d275..f7818cd6f 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -29,6 +29,7 @@ #include "doomstat.h" #include "r_state.h" #include "tables.h" +#include "r_interpolate.h" // // FLOORS @@ -59,7 +60,10 @@ void DFloor::Serialize (FArchive &arc) << m_Hexencrush; } -IMPLEMENT_CLASS (DElevator) +IMPLEMENT_POINTY_CLASS (DElevator) + DECLARE_POINTER(m_Interp_Floor) + DECLARE_POINTER(m_Interp_Ceiling) +END_POINTERS DElevator::DElevator () { @@ -72,10 +76,30 @@ void DElevator::Serialize (FArchive &arc) << m_Direction << m_FloorDestDist << m_CeilingDestDist - << m_Speed; + << m_Speed + << m_Interp_Floor + << m_Interp_Ceiling; } -IMPLEMENT_CLASS (DWaggleBase) +void DElevator::Destroy() +{ + if (m_Interp_Ceiling != NULL) + { + m_Interp_Ceiling->DelRef(); + m_Interp_Ceiling = NULL; + } + if (m_Interp_Floor != NULL) + { + m_Interp_Floor->DelRef(); + m_Interp_Floor = NULL; + } + Super::Destroy(); +} + +IMPLEMENT_POINTY_CLASS (DWaggleBase) + DECLARE_POINTER(m_Interpolation) +END_POINTERS + IMPLEMENT_CLASS (DFloorWaggle) IMPLEMENT_CLASS (DCeilingWaggle) @@ -93,7 +117,8 @@ void DWaggleBase::Serialize (FArchive &arc) << m_Scale << m_ScaleDelta << m_Ticker - << m_State; + << m_State + << m_Interpolation; } @@ -181,7 +206,7 @@ void DFloor::Tick () } m_Sector->floordata = NULL; //jff 2/22/98 - stopinterpolation (INTERP_SectorFloor, m_Sector); + StopInterpolation(); //jff 2/26/98 implement stair retrigger lockout while still building // note this only applies to the retriggerable generalized stairs @@ -268,8 +293,6 @@ void DElevator::Tick () m_Sector->floordata = NULL; //jff 2/22/98 m_Sector->ceilingdata = NULL; //jff 2/22/98 - stopinterpolation (INTERP_SectorFloor, m_Sector); - stopinterpolation (INTERP_SectorCeiling, m_Sector); Destroy (); // remove elevator from actives } } @@ -539,7 +562,7 @@ manual_floor: (floor->m_Direction<0 && floor->m_FloorDestDistfloorplane.d) || // moving down but going up (floor->m_Speed >= abs(sec->floorplane.d - floor->m_FloorDestDist))) // moving in one step { - stopinterpolation (INTERP_SectorFloor, sec); + floor->StopInterpolation(); // [Graf Zahl] // Don't make sounds for instant movement hacks but make an exception for @@ -959,8 +982,8 @@ DElevator::DElevator (sector_t *sec) { sec->floordata = this; sec->ceilingdata = this; - setinterpolation (INTERP_SectorFloor, sec); - setinterpolation (INTERP_SectorCeiling, sec); + m_Interp_Floor = sec->SetInterpolation(sector_t::FloorMove, true); + m_Interp_Ceiling = sec->SetInterpolation(sector_t::CeilingMove, true); } // @@ -1074,6 +1097,16 @@ DWaggleBase::DWaggleBase (sector_t *sec) { } +void DWaggleBase::Destroy() +{ + if (m_Interpolation != NULL) + { + m_Interpolation->DelRef(); + m_Interpolation = NULL; + } + Super::Destroy(); +} + void DWaggleBase::DoWaggle (bool ceiling) { secplane_t *plane; @@ -1111,12 +1144,10 @@ void DWaggleBase::DoWaggle (bool ceiling) if (ceiling) { m_Sector->ceilingdata = NULL; - stopinterpolation (INTERP_SectorCeiling, m_Sector); } else { m_Sector->floordata = NULL; - stopinterpolation (INTERP_SectorFloor, m_Sector); } Destroy (); return; @@ -1156,7 +1187,7 @@ DFloorWaggle::DFloorWaggle (sector_t *sec) : Super (sec) { sec->floordata = this; - setinterpolation (INTERP_SectorFloor, sec); + m_Interpolation = sec->SetInterpolation(sector_t::FloorMove, false); } void DFloorWaggle::Tick () @@ -1178,7 +1209,7 @@ DCeilingWaggle::DCeilingWaggle (sector_t *sec) : Super (sec) { sec->ceilingdata = this; - setinterpolation (INTERP_SectorCeiling, sec); + m_Interpolation = sec->SetInterpolation(sector_t::CeilingMove, false); } void DCeilingWaggle::Tick () diff --git a/src/p_linkedsectors.cpp b/src/p_linkedsectors.cpp index ec59e8e9d..dcdd7dcec 100644 --- a/src/p_linkedsectors.cpp +++ b/src/p_linkedsectors.cpp @@ -207,7 +207,7 @@ bool P_MoveLinkedSectors(sector_t *sector, int crush, fixed_t move, bool ceiling // //============================================================================ -void P_StartLinkedSectorInterpolations(sector_t *sector, bool ceiling) +void P_StartLinkedSectorInterpolations(TArray &list, sector_t *sector, bool ceiling) { extsector_t::linked::plane &scrollplane = ceiling? sector->e->Linked.Ceiling : sector->e->Linked.Floor; @@ -215,43 +215,15 @@ void P_StartLinkedSectorInterpolations(sector_t *sector, bool ceiling) { if (scrollplane.Sectors[i].Type & LINK_FLOOR) { - setinterpolation(INTERP_SectorFloor, scrollplane.Sectors[i].Sector, false); + list.Push(scrollplane.Sectors[i].Sector->SetInterpolation(sector_t::FloorMove, false)); } if (scrollplane.Sectors[i].Type & LINK_CEILING) { - setinterpolation(INTERP_SectorCeiling, scrollplane.Sectors[i].Sector, false); + list.Push(scrollplane.Sectors[i].Sector->SetInterpolation(sector_t::CeilingMove, false)); } } } -//============================================================================ -// -// P_StopLinkedSectorInterpolations -// -// Stops interpolators for every sector plane is being changed by moving -// this sector -// -//============================================================================ - -void P_StopLinkedSectorInterpolations(sector_t *sector, bool ceiling) -{ - extsector_t::linked::plane &scrollplane = ceiling? sector->e->Linked.Ceiling : sector->e->Linked.Floor; - - for(unsigned i = 0; i < scrollplane.Sectors.Size(); i++) - { - if (scrollplane.Sectors[i].Type & LINK_FLOOR) - { - stopinterpolation(INTERP_SectorFloor, scrollplane.Sectors[i].Sector, false); - } - if (scrollplane.Sectors[i].Type & LINK_CEILING) - { - stopinterpolation(INTERP_SectorCeiling, scrollplane.Sectors[i].Sector, false); - } - } -} - - - //============================================================================ // // AddSingleSector diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index a0934cecc..a17ee521c 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -37,13 +37,32 @@ #include "p_spec.h" #include "g_level.h" #include "s_sndseq.h" +#include "r_interpolate.h" -IMPLEMENT_CLASS (DPillar) +IMPLEMENT_POINTY_CLASS (DPillar) + DECLARE_POINTER(m_Interp_Floor) + DECLARE_POINTER(m_Interp_Ceiling) +END_POINTERS DPillar::DPillar () { } +void DPillar::Destroy() +{ + if (m_Interp_Ceiling != NULL) + { + m_Interp_Ceiling->DelRef(); + m_Interp_Ceiling = NULL; + } + if (m_Interp_Floor != NULL) + { + m_Interp_Floor->DelRef(); + m_Interp_Floor = NULL; + } + Super::Destroy(); +} + void DPillar::Serialize (FArchive &arc) { Super::Serialize (arc); @@ -53,7 +72,9 @@ void DPillar::Serialize (FArchive &arc) << m_FloorTarget << m_CeilingTarget << m_Crush - << m_Hexencrush; + << m_Hexencrush + << m_Interp_Floor + << m_Interp_Ceiling; } void DPillar::Tick () @@ -101,8 +122,8 @@ DPillar::DPillar (sector_t *sector, EPillar type, fixed_t speed, vertex_t *spot; sector->floordata = sector->ceilingdata = this; - setinterpolation (INTERP_SectorFloor, sector); - setinterpolation (INTERP_SectorCeiling, sector); + m_Interp_Floor = sector->SetInterpolation(sector_t::FloorMove, true); + m_Interp_Ceiling = sector->SetInterpolation(sector_t::CeilingMove, true); m_Type = type; m_Crush = crush; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 63b2d1bd8..505f69290 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -45,6 +45,7 @@ #include "s_sndseq.h" #include "v_palette.h" #include "a_sharedglobal.h" +#include "r_interpolate.h" static void CopyPlayer (player_t *dst, player_t *src, const char *name); static void ReadOnePlayer (FArchive &arc); @@ -333,7 +334,11 @@ void P_SerializeWorld (FArchive &arc) << sec->Flags << sec->FloorSkyBox << sec->CeilingSkyBox << sec->ZoneNumber - << sec->oldspecial; + << sec->oldspecial + << sec->interpolations[0] + << sec->interpolations[1] + << sec->interpolations[2] + << sec->interpolations[3]; sec->e->Serialize(arc); if (arc.IsStoring ()) @@ -409,6 +414,21 @@ void extsector_t::Serialize(FArchive &arc) << Linked.Ceiling.Sectors; } +FArchive &operator<< (FArchive &arc, side_t::part &p) +{ + arc << p.xoffset << p.yoffset << p.interpolation;// << p.Light; + if (arc.IsStoring ()) + { + TexMan.WriteTexture (arc, p.texture); + } + else + { + p.texture = TexMan.ReadTexture (arc); + } + return arc; +} + + // // Thinkers // @@ -468,7 +488,7 @@ void P_SerializePolyobjs (FArchive &arc) for(i = 0, po = polyobjs; i < po_NumPolyobjs; i++, po++) { arc << po->tag << po->angle << po->startSpot[0] << - po->startSpot[1] << po->startSpot[2]; + po->startSpot[1] << po->startSpot[2] << po->interpolation; } } else @@ -495,7 +515,7 @@ void P_SerializePolyobjs (FArchive &arc) } arc << angle; PO_RotatePolyobj (po->tag, angle); - arc << deltaX << deltaY << deltaZ; + arc << deltaX << deltaY << deltaZ << po->interpolation; deltaX -= po->startSpot[0]; deltaY -= po->startSpot[1]; deltaZ -= po->startSpot[2]; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index efa689aee..3efa54569 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -60,6 +60,7 @@ #include "sbar.h" #include "p_setup.h" #include "r_translate.h" +#include "r_interpolate.h" void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt); void P_SetSlopes (); @@ -3194,7 +3195,7 @@ void P_SetupLevel (char *lumpname, int position) // Free all level data from the previous map P_FreeLevelData (); - clearinterpolations(); // [RH] Nothing to interpolate on a fresh level. + interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. MapData * map = P_OpenMapData(lumpname); if (map == NULL) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index a3569c580..5b98cdf3b 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -65,15 +65,18 @@ #include "c_console.h" -// [RH] Needed for sky scrolling -#include "r_sky.h" +#include "r_interpolate.h" static FRandom pr_playerinspecialsector ("PlayerInSpecialSector"); // [GrafZahl] Make this message changable by the user! ;) CVAR(String, secretmessage, "A Secret is revealed!", CVAR_ARCHIVE) -IMPLEMENT_CLASS (DScroller) +IMPLEMENT_POINTY_CLASS (DScroller) + DECLARE_POINTER (m_Interpolations[0]) + DECLARE_POINTER (m_Interpolations[1]) + DECLARE_POINTER (m_Interpolations[2]) +END_POINTERS IMPLEMENT_POINTY_CLASS (DPusher) DECLARE_POINTER (m_Source) @@ -93,7 +96,10 @@ void DScroller::Serialize (FArchive &arc) << m_LastHeight << m_vdx << m_vdy << m_Accel - << m_Parts; + << m_Parts + << m_Interpolations[0] + << m_Interpolations[1] + << m_Interpolations[2]; } DPusher::DPusher () @@ -1196,6 +1202,8 @@ DScroller::DScroller (EScrollType type, fixed_t dx, fixed_t dy, m_LastHeight = sectors[control].CenterFloor () + sectors[control].CenterCeiling (); m_Affectee = affectee; + m_Interpolations[0] = m_Interpolations[1] = m_Interpolations[2] = NULL; + switch (type) { case sc_carry: @@ -1206,25 +1214,25 @@ DScroller::DScroller (EScrollType type, fixed_t dx, fixed_t dy, sides[affectee].Flags |= WALLF_NOAUTODECALS; if (m_Parts & scw_top) { - sides[m_Affectee].SetInterpolation(side_t::top); + m_Interpolations[0] = sides[m_Affectee].SetInterpolation(side_t::top); } if (m_Parts & scw_mid && (lines[sides[m_Affectee].linenum].backsector == NULL || !(lines[sides[m_Affectee].linenum].flags&ML_3DMIDTEX))) { - sides[m_Affectee].SetInterpolation(side_t::mid); + m_Interpolations[1] = sides[m_Affectee].SetInterpolation(side_t::mid); } if (m_Parts & scw_bottom) { - sides[m_Affectee].SetInterpolation(side_t::bottom); + m_Interpolations[2] = sides[m_Affectee].SetInterpolation(side_t::bottom); } break; case sc_floor: - setinterpolation (INTERP_FloorPanning, §ors[affectee]); + m_Interpolations[0] = sectors[affectee].SetInterpolation(sector_t::FloorScroll, false); break; case sc_ceiling: - setinterpolation (INTERP_CeilingPanning, §ors[affectee]); + m_Interpolations[0] = sectors[affectee].SetInterpolation(sector_t::CeilingScroll, false); break; default: @@ -1232,37 +1240,17 @@ DScroller::DScroller (EScrollType type, fixed_t dx, fixed_t dy, } } -DScroller::~DScroller () +void DScroller::Destroy () { - switch (m_Type) + for(int i=0;i<3;i++) { - case sc_side: - if (m_Parts & scw_top) + if (m_Interpolations[i] != NULL) { - sides[m_Affectee].StopInterpolation(side_t::top); + m_Interpolations[i]->DelRef(); + m_Interpolations[i] = NULL; } - if (m_Parts & scw_mid && (lines[sides[m_Affectee].linenum].backsector == NULL || - !(lines[sides[m_Affectee].linenum].flags&ML_3DMIDTEX))) - { - sides[m_Affectee].StopInterpolation(side_t::mid); - } - if (m_Parts & scw_bottom) - { - sides[m_Affectee].StopInterpolation(side_t::bottom); - } - break; - - case sc_floor: - stopinterpolation (INTERP_FloorPanning, §ors[m_Affectee]); - break; - - case sc_ceiling: - stopinterpolation (INTERP_CeilingPanning, §ors[m_Affectee]); - break; - - default: - break; } + Super::Destroy(); } // Adds wall scroller. Scroll amount is rotated with respect to wall's @@ -1294,19 +1282,20 @@ DScroller::DScroller (fixed_t dx, fixed_t dy, const line_t *l, m_LastHeight = sectors[control].CenterFloor() + sectors[control].CenterCeiling(); m_Affectee = *l->sidenum; sides[m_Affectee].Flags |= WALLF_NOAUTODECALS; + m_Interpolations[0] = m_Interpolations[1] = m_Interpolations[2] = NULL; if (m_Parts & scw_top) { - sides[m_Affectee].SetInterpolation(side_t::top); + m_Interpolations[0] = sides[m_Affectee].SetInterpolation(side_t::top); } if (m_Parts & scw_mid && (lines[sides[m_Affectee].linenum].backsector == NULL || !(lines[sides[m_Affectee].linenum].flags&ML_3DMIDTEX))) { - sides[m_Affectee].SetInterpolation(side_t::mid); + m_Interpolations[1] = sides[m_Affectee].SetInterpolation(side_t::mid); } if (m_Parts & scw_bottom) { - sides[m_Affectee].SetInterpolation(side_t::bottom); + m_Interpolations[2] = sides[m_Affectee].SetInterpolation(side_t::bottom); } } diff --git a/src/p_spec.h b/src/p_spec.h index 5b73ace2b..017004e35 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -43,6 +43,7 @@ typedef enum class DScroller : public DThinker { DECLARE_CLASS (DScroller, DThinker) + HAS_OBJECT_POINTERS public: enum EScrollType { @@ -62,7 +63,7 @@ public: DScroller (EScrollType type, fixed_t dx, fixed_t dy, int control, int affectee, int accel, int scrollpos = scw_all); DScroller (fixed_t dx, fixed_t dy, const line_t *l, int control, int accel, int scrollpos = scw_all); - ~DScroller (); + void Destroy(); void Serialize (FArchive &arc); void Tick (); @@ -83,6 +84,7 @@ protected: fixed_t m_vdx, m_vdy; // Accumulated velocity if accelerative int m_Accel; // Whether it's accelerative int m_Parts; // Which parts of a sidedef are being scrolled? + TObjPtr m_Interpolations[3]; private: DScroller (); @@ -490,6 +492,7 @@ inline FArchive &operator<< (FArchive &arc, DPlat::EPlatState &state) class DPillar : public DMover { DECLARE_CLASS (DPillar, DMover) + HAS_OBJECT_POINTERS public: enum EPillar { @@ -503,6 +506,7 @@ public: void Serialize (FArchive &arc); void Tick (); + void Destroy(); protected: EPillar m_Type; @@ -512,6 +516,8 @@ protected: fixed_t m_CeilingTarget; int m_Crush; bool m_Hexencrush; + TObjPtr m_Interp_Ceiling; + TObjPtr m_Interp_Floor; private: DPillar (); @@ -840,6 +846,7 @@ inline FArchive &operator<< (FArchive &arc, DFloor::EFloor &type) class DElevator : public DMover { DECLARE_CLASS (DElevator, DMover) + HAS_OBJECT_POINTERS public: enum EElevator { @@ -853,6 +860,7 @@ public: DElevator (sector_t *sec); + void Destroy(); void Serialize (FArchive &arc); void Tick (); @@ -862,6 +870,8 @@ protected: fixed_t m_FloorDestDist; fixed_t m_CeilingDestDist; fixed_t m_Speed; + TObjPtr m_Interp_Ceiling; + TObjPtr m_Interp_Floor; void StartFloorSound (); @@ -885,6 +895,7 @@ inline FArchive &operator<< (FArchive &arc, DElevator::EElevator &type) class DWaggleBase : public DMover { DECLARE_CLASS (DWaggleBase, DMover) + HAS_OBJECT_POINTERS public: DWaggleBase (sector_t *sec); @@ -899,11 +910,13 @@ protected: fixed_t m_ScaleDelta; int m_Ticker; int m_State; + TObjPtr m_Interpolation; friend bool EV_StartWaggle (int tag, int height, int speed, int offset, int timer, bool ceiling); void DoWaggle (bool ceiling); + void Destroy(); DWaggleBase (); }; diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 3d6c3a20d..05460ce94 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -30,6 +30,7 @@ #include "s_sound.h" #include "doomstat.h" #include "sbar.h" +#include "r_interpolate.h" extern gamestate_t wipegamestate; @@ -68,7 +69,7 @@ void P_Ticker (void) { int i; - updateinterpolations (); + interpolator.UpdateInterpolations (); r_NoInterpolate = true; // run the tic diff --git a/src/po_man.cpp b/src/po_man.cpp index 1e1a7092d..ab9109f35 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -24,6 +24,7 @@ #include "a_sharedglobal.h" #include "r_main.h" #include "p_lnspec.h" +#include "r_interpolate.h" // MACROS ------------------------------------------------------------------ @@ -42,10 +43,11 @@ inline FArchive &operator<< (FArchive &arc, podoortype_t &type) class DPolyAction : public DThinker { DECLARE_CLASS (DPolyAction, DThinker) + HAS_OBJECT_POINTERS public: DPolyAction (int polyNum); - ~DPolyAction (); void Serialize (FArchive &arc); + void Destroy(); void StopInterpolation (); protected: @@ -53,6 +55,7 @@ protected: int m_PolyObj; int m_Speed; int m_Dist; + TObjPtr m_Interpolation; void SetInterpolation (); @@ -152,7 +155,10 @@ static TArray KnownPolySegs; // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS (DPolyAction) +IMPLEMENT_POINTY_CLASS (DPolyAction) + DECLARE_POINTER(m_Interpolation) +END_POINTERS + IMPLEMENT_CLASS (DRotatePoly) IMPLEMENT_CLASS (DMovePoly) IMPLEMENT_CLASS (DPolyDoor) @@ -164,7 +170,7 @@ DPolyAction::DPolyAction () void DPolyAction::Serialize (FArchive &arc) { Super::Serialize (arc); - arc << m_PolyObj << m_Speed << m_Dist; + arc << m_PolyObj << m_Speed << m_Dist << m_Interpolation; } DPolyAction::DPolyAction (int polyNum) @@ -175,32 +181,31 @@ DPolyAction::DPolyAction (int polyNum) SetInterpolation (); } -DPolyAction::~DPolyAction () +void DPolyAction::Destroy() { FPolyObj *poly = GetPolyobj (m_PolyObj); if (poly->specialdata == NULL || poly->specialdata == this) { poly->specialdata = NULL; - StopInterpolation (); } + + StopInterpolation(); + Super::Destroy(); } void DPolyAction::SetInterpolation () { FPolyObj *poly = GetPolyobj (m_PolyObj); - for (int i = 0; i < poly->numvertices; ++i) - { - setinterpolation (INTERP_Vertex, poly->vertices[i]); - } + m_Interpolation = poly->SetInterpolation(); } void DPolyAction::StopInterpolation () { - FPolyObj *poly = GetPolyobj (m_PolyObj); - for (int i = 0; i < poly->numvertices; ++i) + if (m_Interpolation != NULL) { - stopinterpolation (INTERP_Vertex, poly->vertices[i]); + m_Interpolation->DelRef(); + m_Interpolation = NULL; } } diff --git a/src/r_defs.h b/src/r_defs.h index 82479a82c..d4a349aec 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -35,9 +35,6 @@ #include "actor.h" #include "dthinker.h" -#include "r_interpolate.h" - - #define MAXWIDTH 2560 #define MAXHEIGHT 1600 @@ -88,6 +85,7 @@ class player_t; class FScanner; class FBitmap; struct FCopyInfo; +class DInterpolation; // // The SECTORS record, at runtime. @@ -346,6 +344,9 @@ struct sector_t void SetColor(int r, int g, int b, int desat); void SetFade(int r, int g, int b); + DInterpolation *SetInterpolation(int position, bool attach); + void StopInterpolation(int position); + // Member variables fixed_t CenterFloor () const { return floorplane.ZatPoint (soundorg[0], soundorg[1]); } fixed_t CenterCeiling () const { return ceilingplane.ZatPoint (soundorg[0], soundorg[1]); } @@ -400,6 +401,15 @@ struct sector_t TObjPtr ceilingdata; // floors, ceilings, lighting, TObjPtr lightingdata; // independent of one another + enum + { + CeilingMove, + FloorMove, + CeilingScroll, + FloorScroll + }; + TObjPtr interpolations[4]; + // jff 2/26/98 lockout machinery for stairbuilding SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally SWORD prevsec; // -1 or number of sector for previous step @@ -479,6 +489,7 @@ struct side_t fixed_t xoffset; fixed_t yoffset; int texture; + TObjPtr interpolation; //int Light; }; @@ -540,15 +551,8 @@ struct side_t textures[which].yoffset += delta; } - void SetInterpolation(int position) - { - setinterpolation(EInterpType(INTERP_WallPanning_Top+position), this); - } - void StopInterpolation(int position) - { - stopinterpolation(EInterpType(INTERP_WallPanning_Top+position), this); - } - + DInterpolation *SetInterpolation(int position); + void StopInterpolation(int position); }; FArchive &operator<< (FArchive &arc, side_t::part &p); @@ -670,8 +674,12 @@ struct FPolyObj int seqType; fixed_t size; // polyobj size (area of POLY_AREAUNIT == size of FRACUNIT) DThinker *specialdata; // pointer to a thinker, if the poly is moving + TObjPtr interpolation; ~FPolyObj(); + DInterpolation *SetInterpolation(); + void StopInterpolation(); + }; // diff --git a/src/r_interpolate.cpp b/src/r_interpolate.cpp index c282dad43..cbe1553e6 100644 --- a/src/r_interpolate.cpp +++ b/src/r_interpolate.cpp @@ -1,327 +1,248 @@ -// Stuff from BUILD to interpolate floors and ceilings -// -// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman -// Ken Silverman's official web site: "http://www.advsys.net/ken" -// See the included license file "BUILDLIC.TXT" for license info. -// This code has been modified from its original form. +/* +** r_interpolate.cpp +** +** Movement interpolation +** +**--------------------------------------------------------------------------- +** Copyright 2008 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ #include "r_data.h" #include "p_3dmidtex.h" #include "stats.h" +#include "r_interpolate.h" +#include "p_local.h" -struct FActiveInterpolation +//========================================================================== +// +// +// +//========================================================================== + +class DSectorPlaneInterpolation : public DInterpolation { - FActiveInterpolation *Next; - void *Address; - EInterpType Type; + DECLARE_CLASS(DSectorPlaneInterpolation, DInterpolation) - friend FArchive &operator << (FArchive &arc, FActiveInterpolation *&interp); + sector_t *sector; + fixed_t oldheight, oldtexz; + fixed_t bakheight, baktexz; + bool ceiling; + TArray attached; - static int CountInterpolations (); - static int CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill); -private: - fixed_t oldipos[2], bakipos[2]; +public: - void CopyInterpToOld(); - void CopyBakToInterp(); - void DoAnInterpolation(fixed_t smoothratio); + DSectorPlaneInterpolation() {} + DSectorPlaneInterpolation(sector_t *sector, bool plane, bool attach); + void Destroy(); + void UpdateInterpolation(); + void Restore(); + void Interpolate(fixed_t smoothratio); + void Serialize(FArchive &arc); + size_t PointerSubstitution (DObject *old, DObject *notOld); + size_t PropagateMark(); +}; - static size_t HashKey(EInterpType type, void *interptr); - static FActiveInterpolation *FindInterpolation(EInterpType, void *interptr, FActiveInterpolation **&interp_p); +//========================================================================== +// +// +// +//========================================================================== - friend void updateinterpolations(); - friend void setinterpolation(EInterpType, void *interptr, bool dolinks); - friend void stopinterpolation(EInterpType, void *interptr, bool dolinks); - friend void dointerpolations(fixed_t smoothratio); - friend void restoreinterpolations(); - friend void clearinterpolations(); - friend void SerializeInterpolations(FArchive &arc); +class DSectorScrollInterpolation : public DInterpolation +{ + DECLARE_CLASS(DSectorScrollInterpolation, DInterpolation) - static FActiveInterpolation *curiposhash[INTERPOLATION_BUCKETS]; + sector_t *sector; + fixed_t oldx, oldy; + fixed_t bakx, baky; + bool ceiling; + +public: + + DSectorScrollInterpolation() {} + DSectorScrollInterpolation(sector_t *sector, bool plane); + void UpdateInterpolation(); + void Restore(); + void Interpolate(fixed_t smoothratio); + void Serialize(FArchive &arc); }; +//========================================================================== +// +// +// +//========================================================================== -static bool didInterp; - -FActiveInterpolation *FActiveInterpolation::curiposhash[INTERPOLATION_BUCKETS]; - -void FActiveInterpolation::CopyInterpToOld () +class DWallScrollInterpolation : public DInterpolation { - switch (Type) - { - case INTERP_SectorFloor: - oldipos[0] = ((sector_t*)Address)->floorplane.d; - oldipos[1] = ((sector_t*)Address)->floortexz; - break; - case INTERP_SectorCeiling: - oldipos[0] = ((sector_t*)Address)->ceilingplane.d; - oldipos[1] = ((sector_t*)Address)->ceilingtexz; - break; - case INTERP_Vertex: - oldipos[0] = ((vertex_t*)Address)->x; - oldipos[1] = ((vertex_t*)Address)->y; - break; - case INTERP_FloorPanning: - oldipos[0] = ((sector_t*)Address)->floor_xoffs; - oldipos[1] = ((sector_t*)Address)->floor_yoffs; - break; - case INTERP_CeilingPanning: - oldipos[0] = ((sector_t*)Address)->ceiling_xoffs; - oldipos[1] = ((sector_t*)Address)->ceiling_yoffs; - break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - oldipos[0] = ((side_t*)Address)->GetTextureYOffset(Type - INTERP_WallPanning_Top); - oldipos[1] = ((side_t*)Address)->GetTextureXOffset(Type - INTERP_WallPanning_Top); - break; - } -} + DECLARE_CLASS(DWallScrollInterpolation, DInterpolation) -void FActiveInterpolation::CopyBakToInterp () + side_t *side; + int part; + fixed_t oldx, oldy; + fixed_t bakx, baky; + +public: + + DWallScrollInterpolation() {} + DWallScrollInterpolation(side_t *side, int part); + void UpdateInterpolation(); + void Restore(); + void Interpolate(fixed_t smoothratio); + void Serialize(FArchive &arc); +}; + +//========================================================================== +// +// +// +//========================================================================== + +class DPolyobjInterpolation : public DInterpolation { - switch (Type) - { - case INTERP_SectorFloor: - ((sector_t*)Address)->floorplane.d = bakipos[0]; - ((sector_t*)Address)->floortexz = bakipos[1]; - break; - case INTERP_SectorCeiling: - ((sector_t*)Address)->ceilingplane.d = bakipos[0]; - ((sector_t*)Address)->ceilingtexz = bakipos[1]; - break; - case INTERP_Vertex: - ((vertex_t*)Address)->x = bakipos[0]; - ((vertex_t*)Address)->y = bakipos[1]; - break; - case INTERP_FloorPanning: - ((sector_t*)Address)->floor_xoffs = bakipos[0]; - ((sector_t*)Address)->floor_yoffs = bakipos[1]; - break; - case INTERP_CeilingPanning: - ((sector_t*)Address)->ceiling_xoffs = bakipos[0]; - ((sector_t*)Address)->ceiling_yoffs = bakipos[1]; - break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - ((side_t*)Address)->SetTextureYOffset(Type - INTERP_WallPanning_Top, bakipos[0]); - ((side_t*)Address)->SetTextureXOffset(Type - INTERP_WallPanning_Top, bakipos[1]); - break; - } -} + DECLARE_CLASS(DPolyobjInterpolation, DInterpolation) -void FActiveInterpolation::DoAnInterpolation (fixed_t smoothratio) -{ - fixed_t *adr1, *adr2, pos; - int v1, v2; + FPolyObj *poly; + TArray oldverts, bakverts; - switch (Type) - { - case INTERP_SectorFloor: - adr1 = &((sector_t*)Address)->floorplane.d; - adr2 = &((sector_t*)Address)->floortexz; - break; - case INTERP_SectorCeiling: - adr1 = &((sector_t*)Address)->ceilingplane.d; - adr2 = &((sector_t*)Address)->ceilingtexz; - break; - case INTERP_Vertex: - adr1 = &((vertex_t*)Address)->x; - adr2 = &((vertex_t*)Address)->y; - break; - case INTERP_FloorPanning: - adr1 = &((sector_t*)Address)->floor_xoffs; - adr2 = &((sector_t*)Address)->floor_yoffs; - break; - case INTERP_CeilingPanning: - adr1 = &((sector_t*)Address)->ceiling_xoffs; - adr2 = &((sector_t*)Address)->ceiling_yoffs; - break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - v1 = ((side_t*)Address)->GetTextureYOffset(Type - INTERP_WallPanning_Top); - v2 = ((side_t*)Address)->GetTextureXOffset(Type - INTERP_WallPanning_Top); - adr1 = &v1; - adr2 = &v2; - break; - default: - return; - } +public: - pos = bakipos[0] = *adr1; - *adr1 = oldipos[0] + FixedMul (pos - oldipos[0], smoothratio); + DPolyobjInterpolation() {} + DPolyobjInterpolation(FPolyObj *poly); + void UpdateInterpolation(); + void Restore(); + void Interpolate(fixed_t smoothratio); + void Serialize(FArchive &arc); +}; - pos = bakipos[1] = *adr2; - *adr2 = oldipos[1] + FixedMul (pos - oldipos[1], smoothratio); - switch (Type) - { - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - ((side_t*)Address)->SetTextureYOffset(Type - INTERP_WallPanning_Top, v1); - ((side_t*)Address)->SetTextureXOffset(Type - INTERP_WallPanning_Top, v2); - break; - default: - return; - } +//========================================================================== +// +// +// +//========================================================================== -} +IMPLEMENT_ABSTRACT_CLASS(DInterpolation) +IMPLEMENT_CLASS(DSectorPlaneInterpolation) +IMPLEMENT_CLASS(DSectorScrollInterpolation) +IMPLEMENT_CLASS(DWallScrollInterpolation) +IMPLEMENT_CLASS(DPolyobjInterpolation) -size_t FActiveInterpolation::HashKey (EInterpType type, void *interptr) -{ - return (size_t)type * ((size_t)interptr>>5); -} +//========================================================================== +// +// Important note: +// The linked list of interpolations and the pointers in the interpolated +// objects are not processed by the garbage collector. This is intentional! +// +// If an interpolation is no longer owned by any thinker it should +// be destroyed even if the interpolator still has a link to it. +// +// When such an interpolation is destroyed by the garbage collector it +// will automatically be unlinked from the list. +// +//========================================================================== -int FActiveInterpolation::CountInterpolations () -{ - int d1, d2, d3; - return CountInterpolations (&d1, &d2, &d3); -} +FInterpolator interpolator; -int FActiveInterpolation::CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill) +//========================================================================== +// +// +// +//========================================================================== + +int FInterpolator::CountInterpolations () { int count = 0; - int inuse = 0; - int minuse = INT_MAX; - int maxuse = INT_MIN; - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + DInterpolation *probe = Head; + while (probe != NULL) { - int use = 0; - FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - if (probe != NULL) - { - inuse++; - } - while (probe != NULL) - { - count++; - use++; - probe = probe->Next; - } - if (use > 0 && use < minuse) - { - minuse = use; - } - if (use > maxuse) - { - maxuse = use; - } + count++; + probe = probe->Next; } - *usedbuckets = inuse; - *minbucketfill = minuse == INT_MAX ? 0 : minuse; - *maxbucketfill = maxuse; return count; } -FActiveInterpolation *FActiveInterpolation::FindInterpolation (EInterpType type, void *interptr, FActiveInterpolation **&interp_p) -{ - size_t hash = HashKey (type, interptr) % INTERPOLATION_BUCKETS; - FActiveInterpolation *probe, **probe_p; +//========================================================================== +// +// +// +//========================================================================== - for (probe_p = &curiposhash[hash], probe = *probe_p; - probe != NULL; - probe_p = &probe->Next, probe = *probe_p) - { - if (probe->Address > interptr) - { // We passed the place it would have been, so it must not be here. - probe = NULL; - break; - } - if (probe->Address == interptr && probe->Type == type) - { // Found it. - break; - } - } - interp_p = probe_p; - return probe; -} - -void clearinterpolations() +void FInterpolator::UpdateInterpolations() { - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + for (DInterpolation *probe = Head; probe != NULL; probe = probe->Next) { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; ) - { - FActiveInterpolation *next = probe->Next; - delete probe; - probe = next; - } - FActiveInterpolation::curiposhash[i] = NULL; + probe->UpdateInterpolation (); } } -void updateinterpolations() //Stick at beginning of domovethings +//========================================================================== +// +// +// +//========================================================================== + +void FInterpolator::AddInterpolation(DInterpolation *interp) { - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + interp->Next = Head; + if (Head != NULL) Head->Prev = &interp->Next; + Head = interp; + interp->Prev = &Head; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FInterpolator::RemoveInterpolation(DInterpolation *interp) +{ + if (interp->Prev != NULL) { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; probe = probe->Next) - { - probe->CopyInterpToOld (); - } + *interp->Prev = interp->Next; + if (interp->Next != NULL) interp->Next->Prev = interp->Prev; + interp->Next = NULL; + interp->Prev = NULL; } } -void setinterpolation(EInterpType type, void *posptr, bool dolinks) -{ - FActiveInterpolation **interp_p; - FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); - if (interp != NULL) return; // It's already active - interp = new FActiveInterpolation; - interp->Type = type; - interp->Address = posptr; - interp->Next = *interp_p; - *interp_p = interp; - interp->CopyInterpToOld (); +//========================================================================== +// +// +// +//========================================================================== - if (dolinks) - { - if (type == INTERP_SectorFloor) - { - P_Start3dMidtexInterpolations((sector_t*)posptr, false); - P_StartLinkedSectorInterpolations((sector_t*)posptr, false); - } - else if (type == INTERP_SectorCeiling) - { - P_Start3dMidtexInterpolations((sector_t*)posptr, true); - P_StartLinkedSectorInterpolations((sector_t*)posptr, true); - } - } -} - -void stopinterpolation(EInterpType type, void *posptr, bool dolinks) -{ - FActiveInterpolation **interp_p; - FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); - if (interp != NULL) - { - *interp_p = interp->Next; - delete interp; - - if (dolinks) - { - if (type == INTERP_SectorFloor) - { - P_Stop3dMidtexInterpolations((sector_t*)posptr, false); - P_StopLinkedSectorInterpolations((sector_t*)posptr, false); - } - else if (type == INTERP_SectorCeiling) - { - P_Stop3dMidtexInterpolations((sector_t*)posptr, true); - P_StopLinkedSectorInterpolations((sector_t*)posptr, true); - } - } - } -} - -void dointerpolations(fixed_t smoothratio) //Stick at beginning of drawscreen +void FInterpolator::DoInterpolations(fixed_t smoothratio) { if (smoothratio == FRACUNIT) { @@ -331,119 +252,670 @@ void dointerpolations(fixed_t smoothratio) //Stick at beginning of drawscr didInterp = true; - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + for (DInterpolation *probe = Head; probe != NULL; probe = probe->Next) { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; probe = probe->Next) - { - probe->DoAnInterpolation (smoothratio); - } + probe->Interpolate(smoothratio); } } -void restoreinterpolations() //Stick at end of drawscreen +//========================================================================== +// +// +// +//========================================================================== + +void FInterpolator::RestoreInterpolations() { if (didInterp) { didInterp = false; - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + for (DInterpolation *probe = Head; probe != NULL; probe = probe->Next) { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; probe = probe->Next) - { - probe->CopyBakToInterp (); - } + probe->Restore(); } } } -void SerializeInterpolations (FArchive &arc) -{ - FActiveInterpolation *interp; - int numinterpolations; - int i; +//========================================================================== +// +// +// +//========================================================================== - if (arc.IsStoring ()) +void FInterpolator::ClearInterpolations() +{ + for (DInterpolation *probe = Head; probe != NULL; ) { - numinterpolations = FActiveInterpolation::CountInterpolations(); - arc.WriteCount (numinterpolations); - for (i = INTERPOLATION_BUCKETS-1; i >= 0; --i) - { - for (interp = FActiveInterpolation::curiposhash[i]; - interp != NULL; interp = interp->Next) - { - arc << interp; - } - } + DInterpolation *next = probe->Next; + probe->Destroy(); + probe = next; + } + Head = NULL; +} + + +//========================================================================== +// +// +// +//========================================================================== + +//========================================================================== +// +// +// +//========================================================================== + +DInterpolation::DInterpolation() +{ + Next = NULL; + Prev = NULL; + refcount = 0; +} + +//========================================================================== +// +// +// +//========================================================================== + +int DInterpolation::AddRef() +{ + return ++refcount; +} + +//========================================================================== +// +// +// +//========================================================================== + +int DInterpolation::DelRef() +{ + if (refcount > 0) --refcount; + if (refcount <= 0 && !(ObjectFlags & OF_EuthanizeMe)) + { + Destroy(); + } + return refcount; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DInterpolation::Destroy() +{ + interpolator.RemoveInterpolation(this); + refcount = 0; + Super::Destroy(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DInterpolation::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + arc << refcount; + if (arc.IsLoading()) + { + interpolator.AddInterpolation(this); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +//========================================================================== +// +// +// +//========================================================================== + +DSectorPlaneInterpolation::DSectorPlaneInterpolation(sector_t *_sector, bool _plane, bool attach) +{ + sector = _sector; + ceiling = _plane; + UpdateInterpolation (); + + if (attach) + { + P_Start3dMidtexInterpolations(attached, sector, ceiling); + P_StartLinkedSectorInterpolations(attached, sector, ceiling); + } + interpolator.AddInterpolation(this); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DSectorPlaneInterpolation::Destroy() +{ + for(unsigned i=0; iDelRef(); + } + Super::Destroy(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DSectorPlaneInterpolation::UpdateInterpolation() +{ + if (!ceiling) + { + oldheight = sector->floorplane.d; + oldtexz = sector->floortexz; } else { - clearinterpolations (); - numinterpolations = arc.ReadCount (); - for (i = numinterpolations; i > 0; --i) - { - FActiveInterpolation **interp_p; - arc << interp; - if (FActiveInterpolation::FindInterpolation (interp->Type, interp->Address, interp_p) == NULL) - { // Should always return NULL, because there should never be any duplicates stored. - interp->Next = *interp_p; - *interp_p = interp; - } - } + oldheight = sector->ceilingplane.d; + oldtexz = sector->ceilingtexz; } } -FArchive &operator << (FArchive &arc, FActiveInterpolation *&interp) -{ - BYTE type; - union - { - vertex_t *vert; - sector_t *sect; - side_t *side; - void *ptr; - } ptr; +//========================================================================== +// +// +// +//========================================================================== - if (arc.IsStoring ()) +void DSectorPlaneInterpolation::Restore() +{ + if (!ceiling) { - type = interp->Type; - ptr.ptr = interp->Address; - arc << type; - switch (type) - { - case INTERP_Vertex: arc << ptr.vert; break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - arc << ptr.side; break; - default: arc << ptr.sect; break; - } + sector->floorplane.d = bakheight; + sector->floortexz = baktexz; } else { - interp = new FActiveInterpolation; - arc << type; - interp->Type = (EInterpType)type; - switch (type) - { - case INTERP_Vertex: arc << ptr.vert; break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - arc << ptr.side; break; - default: arc << ptr.sect; break; - } - interp->Address = ptr.ptr; + sector->ceilingplane.d = bakheight; + sector->ceilingtexz = baktexz; } - return arc; } +//========================================================================== +// +// +// +//========================================================================== + +void DSectorPlaneInterpolation::Interpolate(fixed_t smoothratio) +{ + fixed_t *pheight; + fixed_t *ptexz; + + if (!ceiling) + { + pheight = §or->floorplane.d; + ptexz = §or->floortexz; + } + else + { + pheight = §or->ceilingplane.d; + ptexz = §or->ceilingtexz; + } + + bakheight = *pheight; + baktexz = *ptexz; + + *pheight = oldheight + FixedMul(bakheight - oldheight, smoothratio); + *ptexz = oldtexz + FixedMul(baktexz - oldtexz, smoothratio); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DSectorPlaneInterpolation::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + arc << sector << ceiling << oldheight << oldtexz << attached; +} + +//========================================================================== +// +// +// +//========================================================================== + +size_t DSectorPlaneInterpolation::PointerSubstitution (DObject *old, DObject *notOld) +{ + int subst = 0; + for(unsigned i=0; ifloor_xoffs; + oldy = sector->floor_yoffs; + } + else + { + oldx = sector->ceiling_xoffs; + oldy = sector->ceiling_yoffs; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void DSectorScrollInterpolation::Restore() +{ + if (!ceiling) + { + sector->floor_xoffs = bakx; + sector->floor_yoffs = baky; + } + else + { + sector->ceiling_xoffs = bakx; + sector->ceiling_yoffs = baky; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void DSectorScrollInterpolation::Interpolate(fixed_t smoothratio) +{ + fixed_t *px; + fixed_t *py; + + if (!ceiling) + { + px = §or->floor_xoffs; + py = §or->floor_yoffs; + } + else + { + px = §or->ceiling_xoffs; + py = §or->ceiling_yoffs; + } + + bakx = *px; + baky = *py; + + *px = oldx + FixedMul(bakx - oldx, smoothratio); + *py = oldy + FixedMul(baky - oldy, smoothratio); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DSectorScrollInterpolation::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + arc << sector << ceiling << oldx << oldy; +} + + +//========================================================================== +// +// +// +//========================================================================== + +//========================================================================== +// +// +// +//========================================================================== + +DWallScrollInterpolation::DWallScrollInterpolation(side_t *_side, int _part) +{ + side = _side; + part = _part; + UpdateInterpolation (); + interpolator.AddInterpolation(this); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DWallScrollInterpolation::UpdateInterpolation() +{ + oldx = side->GetTextureXOffset(part); + oldy = side->GetTextureYOffset(part); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DWallScrollInterpolation::Restore() +{ + side->SetTextureXOffset(part, bakx); + side->SetTextureYOffset(part, baky); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DWallScrollInterpolation::Interpolate(fixed_t smoothratio) +{ + bakx = side->GetTextureXOffset(part); + baky = side->GetTextureYOffset(part); + + side->SetTextureXOffset(part, oldx + FixedMul(bakx - oldx, smoothratio)); + side->SetTextureYOffset(part, oldy + FixedMul(baky - oldy, smoothratio)); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DWallScrollInterpolation::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + arc << side << part << oldx << oldy; +} + +//========================================================================== +// +// +// +//========================================================================== + +//========================================================================== +// +// +// +//========================================================================== + +DPolyobjInterpolation::DPolyobjInterpolation(FPolyObj *po) +{ + poly = po; + oldverts.Resize(po->numvertices<<1); + bakverts.Resize(po->numvertices<<1); + UpdateInterpolation (); + interpolator.AddInterpolation(this); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPolyobjInterpolation::UpdateInterpolation() +{ + for(int i = 0; i < poly->numvertices; i++) + { + oldverts[i*2 ] = poly->vertices[i]->x; + oldverts[i*2+1] = poly->vertices[i]->y; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPolyobjInterpolation::Restore() +{ + for(int i = 0; i < poly->numvertices; i++) + { + poly->vertices[i]->x = bakverts[i*2 ]; + poly->vertices[i]->y = bakverts[i*2+1]; + } + //poly->Moved(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPolyobjInterpolation::Interpolate(fixed_t smoothratio) +{ + for(int i = 0; i < poly->numvertices; i++) + { + fixed_t *px = &poly->vertices[i]->x; + fixed_t *py = &poly->vertices[i]->y; + + bakverts[i*2 ] = *px; + bakverts[i*2+1] = *py; + + *px = oldverts[i*2 ] + FixedMul(bakverts[i*2 ] - oldverts[i*2 ], smoothratio); + *py = oldverts[i*2+1] + FixedMul(bakverts[i*2+1] - oldverts[i*2+1], smoothratio); + } + //poly->Moved(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void DPolyobjInterpolation::Serialize(FArchive &arc) +{ + + Super::Serialize(arc); + int po = int(poly - polyobjs); + arc << po << oldverts; + poly = polyobjs + po; + if (arc.IsLoading()) bakverts.Resize(oldverts.Size()); +} + + +//========================================================================== +// +// +// +//========================================================================== + +DInterpolation *side_t::SetInterpolation(int position) +{ + if (textures[position].interpolation == NULL) + { + textures[position].interpolation = new DWallScrollInterpolation(this, position); + textures[position].interpolation->AddRef(); + } + textures[position].interpolation->AddRef(); + GC::WriteBarrier(textures[position].interpolation); + return textures[position].interpolation; +} + +//========================================================================== +// +// +// +//========================================================================== + +void side_t::StopInterpolation(int position) +{ + if (textures[position].interpolation != NULL) + { + textures[position].interpolation->DelRef(); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +DInterpolation *sector_t::SetInterpolation(int position, bool attach) +{ + if (interpolations[position] == NULL) + { + DInterpolation *interp; + switch (position) + { + case sector_t::CeilingMove: + interp = new DSectorPlaneInterpolation(this, true, attach); + break; + + case sector_t::FloorMove: + interp = new DSectorPlaneInterpolation(this, false, attach); + break; + + case sector_t::CeilingScroll: + interp = new DSectorScrollInterpolation(this, true); + break; + + case sector_t::FloorScroll: + interp = new DSectorScrollInterpolation(this, false); + break; + + default: + return NULL; + } + interpolations[position] = interp; + } + interpolations[position]->AddRef(); + GC::WriteBarrier(interpolations[position]); + return interpolations[position]; +} + +//========================================================================== +// +// +// +//========================================================================== + +void sector_t::StopInterpolation(int position) +{ + if (interpolations[position] != NULL) + { + interpolations[position]->DelRef(); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +DInterpolation *FPolyObj::SetInterpolation() +{ + if (interpolation != NULL) + { + interpolation->AddRef(); + } + else + { + interpolation = new DPolyobjInterpolation(this); + interpolation->AddRef(); + } + GC::WriteBarrier(interpolation); + return interpolation; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FPolyObj::StopInterpolation() +{ + if (interpolation != NULL) + { + interpolation->DelRef(); + } +} + + ADD_STAT (interpolations) { - int inuse, minuse, maxuse, total; FString out; - total = FActiveInterpolation::CountInterpolations (&inuse, &minuse, &maxuse); - out.Format ("%d interpolations buckets:%3d min:%3d max:%3d avg:%3d %d%% full %d%% buckfull", - total, inuse, minuse, maxuse, inuse?total/inuse:0, total*100/INTERPOLATION_BUCKETS, inuse*100/INTERPOLATION_BUCKETS); + out.Format ("%d interpolations", interpolator.CountInterpolations ()); return out; } + + diff --git a/src/r_interpolate.h b/src/r_interpolate.h index 5a455d1fe..63716e367 100644 --- a/src/r_interpolate.h +++ b/src/r_interpolate.h @@ -1,156 +1,66 @@ #ifndef R_INTERPOLATE_H #define R_INTERPOLATE_H -#include "doomtype.h" -#include "dobject.h" -#include "r_defs.h" - -// BUILD stuff for interpolating between frames, but modified (rather a lot) -#define INTERPOLATION_BUCKETS 107 - -#if 0 +//========================================================================== +// +// +// +//========================================================================== class DInterpolation : public DObject { + friend struct FInterpolator; + DECLARE_ABSTRACT_CLASS(DInterpolation, DObject) - HAS_OBJECT_POINTERS DInterpolation *Next; + DInterpolation **Prev; + int refcount; protected: DInterpolation(); public: + int AddRef(); + int DelRef(); virtual void Destroy(); - virtual void CopyInterpToOld() = 0; - virtual void CopyBakToInterp() = 0; - virtual void DoAnInterpolation(fixed_t smoothratio) = 0; + virtual void UpdateInterpolation() = 0; + virtual void Restore() = 0; + virtual void Interpolate(fixed_t smoothratio) = 0; virtual void Serialize(FArchive &arc); }; -class DSectorPlaneInterpolation : public DInterpolation -{ - DECLARE_CLASS(DSectorPlaneInterpolation, DInterpolation) - - sector_t *sector; - fixed_t oldheight, oldtexz; - fixed_t bakheight, baktexz; - bool floor; - TArray attached; - - -public: - - DSectorPlaneInterpolation(sector_t *sector, int plane, bool attach); - void Destroy(); - void CopyInterpToOld(); - void CopyBakToInterp(); - void DoAnInterpolation(fixed_t smoothratio); - void Serialize(FArchive &arc); - size_t PointerSubstitution (DObject *old, DObject *notOld); - size_t PropagateMark(); -}; - -class DSectorScrollInterpolation : public DInterpolation -{ - DECLARE_CLASS(DSectorScrollInterpolation, DInterpolation) - - sector_t *sector; - fixed_t oldx, oldy; - fixed_t bakx, baky; - bool floor; - -public: - - DSectorScrollInterpolation(sector_t *sector, int plane); - void Destroy(); - void CopyInterpToOld(); - void CopyBakToInterp(); - void DoAnInterpolation(fixed_t smoothratio); - void Serialize(FArchive &arc); -}; - -class DWallScrollInterpolation : public DInterpolation -{ - DECLARE_CLASS(DWallScrollInterpolation, DInterpolation) - - side_t *side; - side_t::ETexpart part; - fixed_t oldx, oldy; - fixed_t bakx, baky; - -public: - - DWallScrollInterpolation(side_t *side, side_t::ETexpart part); - void Destroy(); - void CopyInterpToOld(); - void CopyBakToInterp(); - void DoAnInterpolation(fixed_t smoothratio); - void Serialize(FArchive &arc); -}; - -class DPolyobjInterpolation : public DInterpolation -{ - DECLARE_CLASS(DPolyobjInterpolation, DInterpolation) - - FPolyobj *poly; - vertex_t *oldverts, *bakverts; - -public: - - DPolyobjInterpolation(FPolyObj *poly); - void Destroy(); - void CopyInterpToOld(); - void CopyBakToInterp(); - void DoAnInterpolation(fixed_t smoothratio); - void Serialize(FArchive &arc); -}; +//========================================================================== +// +// +// +//========================================================================== struct FInterpolator { - DInterpolation *curiposhash[INTERPOLATION_BUCKETS]; + DInterpolation *Head; + bool didInterp; int CountInterpolations (); - int CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill); - -private: - - size_t HashKey(FName type, void *interptr, int param); - DInterpolation *FindInterpolation(const PClass *, void *interptr, int param, DInterpolation **&interp_p); public: - DInterpolation *FindInterpolation(const PClass *, void *interptr, int param); + FInterpolator() + { + Head = NULL; + didInterp = false; + } void UpdateInterpolations(); void AddInterpolation(DInterpolation *); void RemoveInterpolation(DInterpolation *); void DoInterpolations(fixed_t smoothratio); void RestoreInterpolations(); + void ClearInterpolations(); }; - -#endif - -class FArchive; - -enum EInterpType -{ - INTERP_SectorFloor, // Pass a sector_t * - INTERP_SectorCeiling, // Pass a sector_t * - INTERP_Vertex, // Pass a vertex_t * - INTERP_FloorPanning, // Pass a sector_t * - INTERP_CeilingPanning, // Pass a sector_t * - INTERP_WallPanning_Top, // Pass a side_t * - INTERP_WallPanning_Mid, - INTERP_WallPanning_Bottom, -}; - -void updateinterpolations(); -void setinterpolation(EInterpType, void *interptr, bool dolinks = true); -void stopinterpolation(EInterpType, void *interptr, bool dolinks = true); -void dointerpolations(fixed_t smoothratio); -void restoreinterpolations(); -void clearinterpolations(); -void SerializeInterpolations(FArchive &arc); + +extern FInterpolator interpolator; + + #endif diff --git a/src/r_main.cpp b/src/r_main.cpp index 95a823a1b..1195d95b6 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -48,6 +48,7 @@ #include "a_sharedglobal.h" #include "r_translate.h" #include "p_3dmidtex.h" +#include "r_interpolate.h" // MACROS ------------------------------------------------------------------ @@ -1126,7 +1127,7 @@ void R_SetupFrame (AActor *actor) R_CopyStackedViewParameters(); R_SetViewAngle (); - dointerpolations (r_TicFrac); + interpolator.DoInterpolations (r_TicFrac); // Keep the view within the sector's floor and ceiling fixed_t theZ = viewsector->ceilingplane.ZatPoint (viewx, viewy) - 4*FRACUNIT; @@ -1570,7 +1571,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) } WallMirrors.Clear (); - restoreinterpolations (); + interpolator.RestoreInterpolations (); // If there is vertical doubling, and the view window is not an even height, // draw a black line at the bottom of the view window. diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 1bd1af94e..6567e7249 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1444,20 +1444,6 @@ int side_t::GetLightLevel (bool foggy, int baselight) const return clamp(baselight, 0, 255); } -FArchive &operator<< (FArchive &arc, side_t::part &p) -{ - arc << p.xoffset << p.yoffset;// << p.Light; - if (arc.IsStoring ()) - { - TexMan.WriteTexture (arc, p.texture); - } - else - { - p.texture = TexMan.ReadTexture (arc); - } - return arc; -} - //