1
0
forked from 0ad/0ad

Clean up position height methods + add new. Now we have the ability to losslessly read and write positions to entities from the scripts.

This was SVN commit r15230.
This commit is contained in:
sanderd17 2014-05-26 16:23:46 +00:00
parent c3a0ac43bf
commit 5ae9f678b0
4 changed files with 116 additions and 76 deletions

View File

@ -72,8 +72,9 @@ public:
// m_LastX/Z contain the position from the start of the most recent turn
// m_PrevX/Z conatain the position from the turn before that
entity_pos_t m_X, m_Z, m_LastX, m_LastZ, m_PrevX, m_PrevZ; // these values contain undefined junk if !InWorld
entity_pos_t m_YOffset, m_LastYOffset;
bool m_RelativeToGround; // whether m_YOffset is relative to terrain/water plane, or an absolute height
entity_pos_t m_Y, m_LastYDifference; // either the relative or the absolute Y coordinate
bool m_RelativeToGround; // whether m_Y is relative to terrain/water plane, or an absolute height
entity_angle_t m_RotX, m_RotY, m_RotZ;
@ -128,7 +129,8 @@ public:
m_InWorld = false;
m_LastYOffset = m_YOffset = paramNode.GetChild("Altitude").ToFixed();
m_LastYDifference = entity_pos_t::Zero();
m_Y = paramNode.GetChild("Altitude").ToFixed();
m_RelativeToGround = true;
m_Floating = paramNode.GetChild("Floating").ToBool();
@ -152,16 +154,19 @@ public:
if (m_InWorld)
{
serialize.NumberFixed_Unbounded("x", m_X);
serialize.NumberFixed_Unbounded("y", m_Y);
serialize.NumberFixed_Unbounded("z", m_Z);
serialize.NumberFixed_Unbounded("last x", m_LastX);
serialize.NumberFixed_Unbounded("last y diff", m_LastYDifference);
serialize.NumberFixed_Unbounded("last z", m_LastZ);
}
serialize.NumberI32_Unbounded("territory", m_Territory);
serialize.NumberFixed_Unbounded("rot x", m_RotX);
serialize.NumberFixed_Unbounded("rot y", m_RotY);
serialize.NumberFixed_Unbounded("rot z", m_RotZ);
serialize.NumberFixed_Unbounded("altitude", m_YOffset);
serialize.NumberFixed_Unbounded("altitude", m_Y);
serialize.Bool("relative", m_RelativeToGround);
serialize.Bool("floating", m_Floating);
if (serialize.IsDebug())
{
@ -186,7 +191,6 @@ public:
break;
}
serialize.StringASCII("anchor", anchor, 0, 16);
serialize.Bool("floating", m_Floating);
}
}
@ -198,20 +202,22 @@ public:
if (m_InWorld)
{
deserialize.NumberFixed_Unbounded("x", m_X);
deserialize.NumberFixed_Unbounded("y", m_Y);
deserialize.NumberFixed_Unbounded("z", m_Z);
deserialize.NumberFixed_Unbounded("last x", m_LastX);
deserialize.NumberFixed_Unbounded("last y diff", m_LastYDifference);
deserialize.NumberFixed_Unbounded("last z", m_LastZ);
}
deserialize.NumberI32_Unbounded("territory", m_Territory);
deserialize.NumberFixed_Unbounded("rot x", m_RotX);
deserialize.NumberFixed_Unbounded("rot y", m_RotY);
deserialize.NumberFixed_Unbounded("rot z", m_RotZ);
deserialize.NumberFixed_Unbounded("altitude", m_YOffset);
deserialize.NumberFixed_Unbounded("altitude", m_Y);
deserialize.Bool("relative", m_RelativeToGround);
deserialize.Bool("floating", m_Floating);
// TODO: should there be range checks on all these values?
m_InterpolatedRotY = m_RotY.ToFloat();
m_LastYOffset = m_YOffset;
if (m_InWorld)
UpdateXZRotation();
@ -239,7 +245,7 @@ public:
m_InWorld = true;
m_LastX = m_PrevX = m_X;
m_LastZ = m_PrevZ = m_Z;
m_LastYOffset = m_YOffset;
m_LastYDifference = entity_pos_t::Zero();
}
AdvertisePositionChanges();
@ -256,7 +262,7 @@ public:
m_InWorld = true;
m_LastX = m_PrevX = m_X;
m_LastZ = m_PrevZ = m_Z;
m_LastYOffset = m_YOffset;
m_LastYDifference = entity_pos_t::Zero();
}
AdvertisePositionChanges();
@ -278,37 +284,69 @@ public:
virtual void SetHeightOffset(entity_pos_t dy)
{
if (m_RelativeToGround)
{
m_LastYOffset = m_YOffset;
m_YOffset = dy;
}
else
{
m_LastYOffset = m_YOffset = dy;
m_RelativeToGround = true;
}
// subtract the offset and replace with a new offset
m_LastYDifference = dy - GetHeightOffset();
m_Y += m_LastYDifference;
AdvertisePositionChanges();
}
virtual entity_pos_t GetHeightOffset()
{
return m_YOffset;
if (m_RelativeToGround)
return m_Y;
// not relative to the ground, so the height offset is m_Y - ground height
entity_pos_t baseY;
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
if (m_Floating)
{
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
if (cmpWaterManager)
baseY = std::max(baseY, cmpWaterManager->GetWaterLevel(m_X, m_Z));
}
return m_Y - baseY;
}
virtual void SetHeightFixed(entity_pos_t y)
{
if (m_RelativeToGround)
// subtract the absolute height and replace it with a new absolute height
m_LastYDifference = y - GetHeightFixed();
m_Y += m_LastYDifference;
AdvertisePositionChanges();
}
virtual entity_pos_t GetHeightFixed()
{
if (!m_RelativeToGround)
return m_Y;
// relative to the ground, so the fixed height = ground height + m_Y
entity_pos_t baseY;
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
if (m_Floating)
{
m_LastYOffset = m_YOffset = y;
m_RelativeToGround = false;
}
else
{
m_LastYOffset = m_YOffset;
m_YOffset = y;
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
if (cmpWaterManager)
baseY = std::max(baseY, cmpWaterManager->GetWaterLevel(m_X, m_Z));
}
return m_Y + baseY;
}
virtual bool IsHeightRelative()
{
return m_RelativeToGround;
}
virtual void SetHeightRelative(bool relative)
{
// move y to use the right offset (from terrain or from map origin)
m_Y = relative ? GetHeightOffset() : GetHeightFixed();
m_RelativeToGround = relative;
m_LastYDifference = entity_pos_t::Zero();
}
virtual bool IsFloating()
@ -316,6 +354,11 @@ public:
return m_Floating;
}
virtual void SetFloating(bool flag)
{
m_Floating = flag;
}
virtual CFixedVector3D GetPosition()
{
if (!m_InWorld)
@ -324,22 +367,7 @@ public:
return CFixedVector3D();
}
entity_pos_t baseY;
if (m_RelativeToGround)
{
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
if (m_Floating)
{
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
if (cmpWaterManager)
baseY = std::max(baseY, cmpWaterManager->GetWaterLevel(m_X, m_Z));
}
}
return CFixedVector3D(m_X, baseY + m_YOffset, m_Z);
return CFixedVector3D(m_X, GetHeightFixed(), m_Z);
}
virtual CFixedVector2D GetPosition2D()
@ -361,22 +389,7 @@ public:
return CFixedVector3D();
}
entity_pos_t baseY;
if (m_RelativeToGround)
{
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetGroundLevel(m_PrevX, m_PrevZ);
if (m_Floating)
{
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSystemEntity());
if (cmpWaterMan)
baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_PrevX, m_PrevZ));
}
}
return CFixedVector3D(m_PrevX, baseY + m_YOffset, m_PrevZ);
return CFixedVector3D(m_PrevX, GetHeightFixed(), m_PrevZ);
}
virtual CFixedVector2D GetPreviousPosition2D()
@ -472,23 +485,22 @@ public:
float x, z, rotY;
GetInterpolatedPosition2D(frameOffset, x, z, rotY);
float baseY = 0;
if (m_RelativeToGround)
{
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetExactGroundLevel(x, z);
float y = GetHeightFixed().ToFloat() + Interpolate(0.f, m_LastYDifference.ToFloat(), frameOffset);
if (m_Floating || forceFloating)
if (forceFloating)
{
// if the actor has a <float/> flag, it shouldn't be serialized,
// so it's handled here separately
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
if (cmpTerrain && cmpWaterManager)
{
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
if (cmpWaterManager)
baseY = std::max(baseY, cmpWaterManager->GetExactWaterLevel(x, z));
float diff = (cmpWaterManager->GetWaterLevel(m_X, m_Z) - cmpTerrain->GetGroundLevel(m_X, m_Z)).ToFloat();
if (diff > 0.f)
y += diff;
}
}
float y = baseY + Interpolate(m_LastYOffset.ToFloat(), m_YOffset.ToFloat(), frameOffset);
CMatrix3D m;
// linear interpolation is good enough (for RotX/Z).
@ -560,7 +572,7 @@ public:
m_LastX = m_X;
m_LastZ = m_Z;
m_LastYOffset = m_YOffset;
m_LastYDifference = entity_pos_t::Zero();
// warn when a position change also causes a territory change under the entity

View File

@ -30,7 +30,11 @@ DEFINE_INTERFACE_METHOD_2("JumpTo", void, ICmpPosition, JumpTo, entity_pos_t, en
DEFINE_INTERFACE_METHOD_1("SetHeightOffset", void, ICmpPosition, SetHeightOffset, entity_pos_t)
DEFINE_INTERFACE_METHOD_0("GetHeightOffset", entity_pos_t, ICmpPosition, GetHeightOffset)
DEFINE_INTERFACE_METHOD_1("SetHeightFixed", void, ICmpPosition, SetHeightFixed, entity_pos_t)
DEFINE_INTERFACE_METHOD_0("GetHeightFixed", entity_pos_t, ICmpPosition, GetHeightFixed)
DEFINE_INTERFACE_METHOD_0("IsHeightRelative", bool, ICmpPosition, IsHeightRelative)
DEFINE_INTERFACE_METHOD_1("SetHeightRelative", void, ICmpPosition, SetHeightRelative, bool)
DEFINE_INTERFACE_METHOD_0("IsFloating", bool, ICmpPosition, IsFloating)
DEFINE_INTERFACE_METHOD_1("SetFloating", void, ICmpPosition, SetFloating, bool)
DEFINE_INTERFACE_METHOD_0("GetPosition", CFixedVector3D, ICmpPosition, GetPosition)
DEFINE_INTERFACE_METHOD_0("GetPosition2D", CFixedVector2D, ICmpPosition, GetPosition2D)
DEFINE_INTERFACE_METHOD_0("GetPreviousPosition", CFixedVector3D, ICmpPosition, GetPreviousPosition)

View File

@ -94,16 +94,36 @@ public:
virtual entity_pos_t GetHeightOffset() = 0;
/**
* Set the vertical position as a fixed, absolute value.
* Will stay at this height until the next call to SetHeightFixed or SetHeightOffset.
* Set the vertical position above the map zero point
*/
virtual void SetHeightFixed(entity_pos_t y) = 0;
/**
* Returns the vertical offset above the map zero point
*/
virtual entity_pos_t GetHeightFixed() = 0;
/**
* Returns true iff the entity will follow the terrain height (possibly with an offset)
*/
virtual bool IsHeightRelative() = 0;
/**
* When set to true, the entity will follow the terrain height (possibly with an offset)
* When set to false, it's height won't change automatically
*/
virtual void SetHeightRelative(bool flag) = 0;
/**
* Returns whether the entity floats on water.
*/
virtual bool IsFloating() = 0;
/**
* Set the entity to float on water
*/
virtual void SetFloating(bool flag) = 0;
/**
* Returns the current x,y,z position (no interpolation).
* Depends on the current terrain heightmap.

View File

@ -48,7 +48,11 @@ public:
virtual void SetHeightOffset(entity_pos_t UNUSED(dy)) { }
virtual entity_pos_t GetHeightOffset() { return entity_pos_t::Zero(); }
virtual void SetHeightFixed(entity_pos_t UNUSED(y)) { }
virtual entity_pos_t GetHeightFixed() { return entity_pos_t::Zero(); }
virtual bool IsHeightRelative() { return true; }
virtual void SetHeightRelative(bool UNUSED(relative)) { }
virtual bool IsFloating() { return false; }
virtual void SetFloating(bool UNUSED(flag)) { }
virtual CFixedVector3D GetPosition() { return CFixedVector3D(); }
virtual CFixedVector2D GetPosition2D() { return CFixedVector2D(); }
virtual CFixedVector3D GetPreviousPosition() { return CFixedVector3D(); }