# Smoother unit rotation.
Added m_orientation_smoothed to entities, which follows m_orientation but is limited to changing at a certain angular rate. This was SVN commit r4901.
This commit is contained in:
parent
b18f582d3e
commit
9ebe3b08f7
@ -10,7 +10,7 @@
|
||||
#define SQR(x) ((x) * (x))
|
||||
|
||||
template <typename T>
|
||||
T Interpolate(T& a, T& b, float l)
|
||||
T Interpolate(const T& a, const T& b, float l)
|
||||
{
|
||||
return a + (b - a) * l;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
extern int g_xres, g_yres;
|
||||
const float MAX_ROTATION_RATE = 2*PI; // radians per second
|
||||
|
||||
CEntity::CEntity( CEntityTemplate* base, CVector3D position, float orientation, const std::set<CStr8>& actorSelections, const CStrW* building )
|
||||
{
|
||||
@ -46,7 +46,7 @@ CEntity::CEntity( CEntityTemplate* base, CVector3D position, float orientation,
|
||||
m_ahead.x = sin( m_orientation.Y );
|
||||
m_ahead.y = cos( m_orientation.Y );
|
||||
m_position_previous = m_position;
|
||||
m_orientation_previous = m_orientation;
|
||||
m_orientation_smoothed = m_orientation_previous = m_orientation;
|
||||
m_player = NULL;
|
||||
|
||||
m_productionQueue = new CProductionQueue( this );
|
||||
@ -268,6 +268,7 @@ void CEntity::kill(bool keepActor)
|
||||
m_graphics_position = m_position;
|
||||
m_position_previous = m_position;
|
||||
m_graphics_orientation = m_orientation;
|
||||
m_orientation_smoothed = m_orientation;
|
||||
m_orientation_previous = m_orientation;
|
||||
|
||||
snapToGround();
|
||||
@ -373,7 +374,7 @@ void CEntity::update( size_t timestep )
|
||||
if( !m_extant ) return;
|
||||
|
||||
m_position_previous = m_position;
|
||||
m_orientation_previous = m_orientation;
|
||||
m_orientation_previous = m_orientation_smoothed;
|
||||
|
||||
CalculateRegen( timestep );
|
||||
|
||||
@ -401,6 +402,31 @@ void CEntity::update( size_t timestep )
|
||||
|
||||
PROFILE_END( "aura processing" );
|
||||
|
||||
updateOrders( timestep );
|
||||
|
||||
|
||||
// Calculate smoothed rotation: rotate around Y by at most MAX_ROTATION_RATE per second
|
||||
|
||||
float delta = m_orientation.Y - m_orientation_smoothed.Y;
|
||||
// Wrap delta to -PI..PI
|
||||
delta = fmod(delta + PI, 2*PI); // range -2PI..2PI
|
||||
if (delta < 0) delta += 2*PI; // range 0..2PI
|
||||
delta -= PI; // range -PI..PI
|
||||
// Clamp to max rate
|
||||
float deltaClamped = clamp(delta, -MAX_ROTATION_RATE*timestep/1000.f, +MAX_ROTATION_RATE*timestep/1000.f);
|
||||
// Calculate new orientation, in a peculiar way in order to make sure the
|
||||
// result gets close to m_orientation (rather than being n*2*PI out)
|
||||
float newY = m_orientation.Y + deltaClamped - delta;
|
||||
// Apply the smoothed rotation
|
||||
m_orientation_smoothed = CVector3D(
|
||||
m_orientation.X,
|
||||
newY,
|
||||
m_orientation.Z
|
||||
);
|
||||
}
|
||||
|
||||
void CEntity::updateOrders( size_t timestep )
|
||||
{
|
||||
// The process[...] functions return 'true' if the order at the top of the stack
|
||||
// still needs to be (re-)evaluated; else 'false' to terminate the processing of
|
||||
// this entity in this timestep.
|
||||
@ -846,7 +872,9 @@ void CEntity::repath()
|
||||
|
||||
void CEntity::reorient()
|
||||
{
|
||||
m_orientation = m_graphics_orientation;
|
||||
m_graphics_orientation = m_orientation;
|
||||
m_orientation_previous = m_orientation;
|
||||
m_orientation_smoothed = m_orientation;
|
||||
|
||||
m_ahead.x = sin( m_orientation.Y );
|
||||
m_ahead.y = cos( m_orientation.Y );
|
||||
@ -857,11 +885,16 @@ void CEntity::reorient()
|
||||
|
||||
void CEntity::teleport()
|
||||
{
|
||||
m_position = m_graphics_position;
|
||||
m_position_previous = m_position;
|
||||
m_graphics_position = m_position;
|
||||
m_bounds->setPosition( m_position.X, m_position.Z );
|
||||
updateActorTransforms();
|
||||
updateCollisionPatch();
|
||||
repath();
|
||||
|
||||
// TODO: repath breaks things - entities get sent to (0,0) if they're moved in
|
||||
// Atlas. I can't see teleport being used anywhere else important, so
|
||||
// hopefully it won't hurt to just remove it for now...
|
||||
// repath();
|
||||
}
|
||||
|
||||
void CEntity::stanceChanged()
|
||||
@ -940,7 +973,7 @@ void CEntity::interpolate( float relativeoffset )
|
||||
|
||||
updateXZOrientation();
|
||||
|
||||
m_graphics_orientation = Interpolate<CVector3D>( m_orientation_previous, m_orientation, relativeoffset );
|
||||
m_graphics_orientation = Interpolate<CVector3D>( m_orientation_previous, m_orientation_smoothed, relativeoffset );
|
||||
|
||||
// Mark the actor transform data as invalid if the entity has moved since
|
||||
// the last call to 'interpolate'.
|
||||
|
@ -181,7 +181,8 @@ public:
|
||||
|
||||
//-- Interpolated property
|
||||
CVector3D m_orientation;
|
||||
CVector3D m_orientation_previous;
|
||||
CVector3D m_orientation_smoothed; // used for slow graphical-only rotation - tends towards m_orientation
|
||||
CVector3D m_orientation_previous; // previous smoothed value
|
||||
CVector3D m_graphics_orientation;
|
||||
|
||||
CVector2D m_orientation_unclamped;
|
||||
@ -245,6 +246,8 @@ private:
|
||||
|
||||
bool shouldRun( float distance ); // Given our distance to a target, can we be running?
|
||||
|
||||
void updateOrders( size_t timestep_millis );
|
||||
|
||||
public:
|
||||
~CEntity();
|
||||
|
||||
|
@ -101,7 +101,7 @@ void CEntity::ScriptingInit()
|
||||
AddClassProperty( L"group", &CEntity::m_grouped, false, (NotifyFn)&CEntity::checkGroup );
|
||||
AddClassProperty( L"traits.extant", &CEntity::m_extant );
|
||||
AddClassProperty( L"actions.move.turningRadius", &CEntity::m_turningRadius );
|
||||
AddClassProperty( L"position", &CEntity::m_graphics_position, false, (NotifyFn)&CEntity::teleport );
|
||||
AddClassProperty( L"position", &CEntity::m_position, false, (NotifyFn)&CEntity::teleport );
|
||||
AddClassProperty( L"orientation", &CEntity::m_orientation, false, (NotifyFn)&CEntity::reorient );
|
||||
AddClassProperty( L"player", (GetFn)&CEntity::JSI_GetPlayer, (SetFn)&CEntity::JSI_SetPlayer );
|
||||
AddClassProperty( L"traits.health.curr", &CEntity::m_healthCurr );
|
||||
|
@ -577,13 +577,8 @@ BEGIN_COMMAND(MoveObject)
|
||||
|
||||
if (unit->GetEntity())
|
||||
{
|
||||
// Set the current position, and also set the previous position so
|
||||
// CEntity::interpolate puts the entity in the right place (without
|
||||
// having to call CEntity::update before it'll look right)
|
||||
unit->GetEntity()->m_position = pos;
|
||||
unit->GetEntity()->m_position_previous = pos;
|
||||
unit->GetEntity()->m_bounds->setPosition(pos.X, pos.Z);
|
||||
unit->GetEntity()->updateCollisionPatch();
|
||||
unit->GetEntity()->teleport();
|
||||
|
||||
if (unit->GetEntity()->m_base->m_isTerritoryCentre)
|
||||
g_Game->GetWorld()->GetTerritoryManager()->DelayedRecalculate();
|
||||
@ -679,8 +674,7 @@ BEGIN_COMMAND(RotateObject)
|
||||
if (unit->GetEntity())
|
||||
{
|
||||
unit->GetEntity()->m_orientation.Y = angle;
|
||||
// TODO: set bounds orientation? (but we'd have to work out whether
|
||||
// it's an orientable type first)
|
||||
unit->GetEntity()->reorient();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user