mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 13:23:56 -07:00
Fixes visual actor interpolation, handling position changes more cleanly, based on patch by sbte.
Fixes rally point lines not updating, fixes #1865 This was SVN commit r13323.
This commit is contained in:
parent
6f33003f30
commit
71ae5a19d8
5 changed files with 41 additions and 38 deletions
|
|
@ -72,7 +72,7 @@ public:
|
|||
entity_pos_t m_YOffset;
|
||||
bool m_RelativeToGround; // whether m_YOffset is relative to terrain/water plane, or an absolute height
|
||||
|
||||
entity_angle_t m_RotX, m_RotY, m_LastRotY, m_PrevRotY, m_RotZ;
|
||||
entity_angle_t m_RotX, m_RotY, m_RotZ;
|
||||
float m_InterpolatedRotY; // not serialized
|
||||
|
||||
static std::string GetSchema()
|
||||
|
|
@ -121,11 +121,8 @@ public:
|
|||
|
||||
m_RotYSpeed = paramNode.GetChild("TurnRate").ToFixed().ToFloat();
|
||||
|
||||
m_RotX = m_RotY = m_RotZ = m_PrevRotY = m_LastRotY = entity_angle_t::FromInt(0);
|
||||
m_RotX = m_RotY = m_RotZ = entity_angle_t::FromInt(0);
|
||||
m_InterpolatedRotY = 0;
|
||||
|
||||
m_PositionChanged = false;
|
||||
m_Interpolated = false;
|
||||
}
|
||||
|
||||
virtual void Deinit()
|
||||
|
|
@ -330,8 +327,6 @@ public:
|
|||
virtual void SetYRotation(entity_angle_t y)
|
||||
{
|
||||
m_RotY = y;
|
||||
m_PrevRotY = y;
|
||||
m_LastRotY = y;
|
||||
m_InterpolatedRotY = m_RotY.ToFloat();
|
||||
|
||||
AdvertisePositionChanges();
|
||||
|
|
@ -422,10 +417,6 @@ public:
|
|||
{
|
||||
case MT_Interpolate:
|
||||
{
|
||||
m_Interpolated = true;
|
||||
if (!m_PositionChanged)
|
||||
return;
|
||||
|
||||
const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
|
||||
|
||||
float rotY = m_RotY.ToFloat();
|
||||
|
|
@ -447,25 +438,15 @@ public:
|
|||
// Store the positions from the turn before
|
||||
m_PrevX = m_LastX;
|
||||
m_PrevZ = m_LastZ;
|
||||
m_PrevRotY = m_LastRotY;
|
||||
|
||||
m_LastX = m_X;
|
||||
m_LastZ = m_Z;
|
||||
m_LastRotY = m_RotY;
|
||||
|
||||
m_PositionChanged = m_X != m_PrevX || m_Z != m_PrevZ || m_RotY != m_PrevRotY || !m_Interpolated;
|
||||
m_Interpolated = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool GetReinterpolate()
|
||||
{
|
||||
return m_PositionChanged;
|
||||
}
|
||||
|
||||
private:
|
||||
void AdvertisePositionChanges()
|
||||
{
|
||||
|
|
@ -479,11 +460,7 @@ private:
|
|||
CMessagePositionChanged msg(GetEntityId(), false, entity_pos_t::Zero(), entity_pos_t::Zero(), entity_angle_t::Zero());
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
m_PositionChanged = true;
|
||||
}
|
||||
|
||||
bool m_PositionChanged;
|
||||
bool m_Interpolated;
|
||||
};
|
||||
|
||||
REGISTER_COMPONENT_TYPE(Position)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ public:
|
|||
componentManager.SubscribeToMessageType(MT_Interpolate);
|
||||
componentManager.SubscribeToMessageType(MT_RenderSubmit);
|
||||
componentManager.SubscribeToMessageType(MT_OwnershipChanged);
|
||||
componentManager.SubscribeToMessageType(MT_PositionChanged);
|
||||
componentManager.SubscribeToMessageType(MT_TurnStart);
|
||||
componentManager.SubscribeGloballyToMessageType(MT_TerrainChanged);
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +85,9 @@ public:
|
|||
bool m_ConstructionPreview;
|
||||
fixed m_ConstructionProgress;
|
||||
|
||||
bool m_NeedsInterpolation;
|
||||
bool m_PositionChanged;
|
||||
|
||||
static std::string GetSchema()
|
||||
{
|
||||
return
|
||||
|
|
@ -172,6 +177,9 @@ public:
|
|||
|
||||
// We need to select animation even if graphics are disabled, as this modifies serialized state
|
||||
SelectAnimation("idle", false, fixed::FromInt(1), L"");
|
||||
|
||||
m_NeedsInterpolation = true;
|
||||
m_PositionChanged = true;
|
||||
}
|
||||
|
||||
virtual void Deinit()
|
||||
|
|
@ -283,6 +291,22 @@ public:
|
|||
{
|
||||
const CMessageTerrainChanged& msgData = static_cast<const CMessageTerrainChanged&> (msg);
|
||||
m_Unit->GetModel().SetTerrainDirty(msgData.i0, msgData.j0, msgData.i1, msgData.j1);
|
||||
// Terrain has changed, so we need to interpolate again
|
||||
m_NeedsInterpolation = true;
|
||||
break;
|
||||
}
|
||||
case MT_PositionChanged:
|
||||
{
|
||||
// The position was changed, so we need to interpolate again
|
||||
m_PositionChanged = true;
|
||||
m_NeedsInterpolation = true;
|
||||
break;
|
||||
}
|
||||
case MT_TurnStart:
|
||||
{
|
||||
// Check whether we need to reinterpolate during this turn
|
||||
m_NeedsInterpolation = m_PositionChanged || m_NeedsInterpolation;
|
||||
m_PositionChanged = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -453,7 +477,12 @@ public:
|
|||
|
||||
virtual void SetConstructionProgress(fixed progress)
|
||||
{
|
||||
m_ConstructionProgress = progress;
|
||||
if (progress != m_ConstructionProgress)
|
||||
{
|
||||
m_ConstructionProgress = progress;
|
||||
// Visual height changed, so we need to interpolate again
|
||||
m_NeedsInterpolation = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Hotload(const VfsPath& name)
|
||||
|
|
@ -726,6 +755,13 @@ void CCmpVisualActor::Interpolate(float frameTime, float frameOffset)
|
|||
if (m_Unit == NULL)
|
||||
return;
|
||||
|
||||
if (!m_NeedsInterpolation)
|
||||
{
|
||||
// Position hasn't changed so skip most of the work
|
||||
m_Unit->UpdateModel(frameTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable rendering of the unit if it has no position
|
||||
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
|
||||
if (!cmpPosition || !cmpPosition->IsInWorld())
|
||||
|
|
@ -735,14 +771,8 @@ void CCmpVisualActor::Interpolate(float frameTime, float frameOffset)
|
|||
UpdateVisibility();
|
||||
m_PreviouslyRendered = true;
|
||||
}
|
||||
else if (!cmpPosition->GetReinterpolate() && m_ConstructionProgress.IsZero() &&
|
||||
!g_AtlasGameLoop->running)
|
||||
{
|
||||
// Position hasn't changed so skip most of the work. Special cases are when placing a building or being
|
||||
// in atlas (since terrain height can change in atlas)
|
||||
m_Unit->UpdateModel(frameTime);
|
||||
return;
|
||||
}
|
||||
|
||||
m_NeedsInterpolation = m_PositionChanged;
|
||||
|
||||
// Even if HIDDEN due to LOS, we need to set up the transforms
|
||||
// so that projectiles will be launched from the right place
|
||||
|
|
|
|||
|
|
@ -38,6 +38,5 @@ DEFINE_INTERFACE_METHOD_1("TurnTo", void, ICmpPosition, TurnTo, entity_angle_t)
|
|||
DEFINE_INTERFACE_METHOD_1("SetYRotation", void, ICmpPosition, SetYRotation, entity_angle_t)
|
||||
DEFINE_INTERFACE_METHOD_2("SetXZRotation", void, ICmpPosition, SetXZRotation, entity_angle_t, entity_angle_t)
|
||||
DEFINE_INTERFACE_METHOD_0("GetRotation", CFixedVector3D, ICmpPosition, GetRotation)
|
||||
DEFINE_INTERFACE_METHOD_0("GetReinterpolate", bool, ICmpPosition, GetReinterpolate)
|
||||
// Excluded: GetInterpolatedTransform (not safe for scripts)
|
||||
END_INTERFACE_WRAPPER(Position)
|
||||
|
|
|
|||
|
|
@ -168,8 +168,6 @@ public:
|
|||
*/
|
||||
virtual CMatrix3D GetInterpolatedTransform(float frameOffset, bool forceFloating) = 0;
|
||||
|
||||
virtual bool GetReinterpolate() = 0;
|
||||
|
||||
DECLARE_INTERFACE_TYPE(Position)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ public:
|
|||
virtual fixed GetDistanceTravelled() { return fixed::Zero(); }
|
||||
virtual void GetInterpolatedPosition2D(float UNUSED(frameOffset), float& x, float& z, float& rotY) { x = z = rotY = 0; }
|
||||
virtual CMatrix3D GetInterpolatedTransform(float UNUSED(frameOffset), bool UNUSED(forceFloating)) { return CMatrix3D(); }
|
||||
virtual bool GetReinterpolate() { return true; }
|
||||
};
|
||||
|
||||
class TestCmpRangeManager : public CxxTest::TestSuite
|
||||
|
|
|
|||
Loading…
Reference in a new issue