1
0
forked from 0ad/0ad

# 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:
Ykkrosh 2007-02-11 22:04:54 +00:00
parent b18f582d3e
commit 9ebe3b08f7
5 changed files with 48 additions and 18 deletions

View File

@ -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;
}

View File

@ -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'.

View File

@ -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();

View File

@ -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 );

View File

@ -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
{