1
This commit is contained in:
658
game/server/movement.cpp
Normal file
658
game/server/movement.cpp
Normal file
@ -0,0 +1,658 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: MOVEMENT ENTITIES TEST
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "entitylist.h"
|
||||
#include "entityoutput.h"
|
||||
#include "keyframe/keyframe.h" // BUG: this needs to move if keyframe is a standard thing
|
||||
|
||||
#include "mathlib/mathlib.h" // FIXME: why do we still need this?
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Hack, sort of. These interpolators don't get to hold state, but the ones
|
||||
// that need state (like the rope simulator) should NOT be used as paths here.
|
||||
IPositionInterpolator *g_pPositionInterpolators[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
IPositionInterpolator* GetPositionInterpolator( int iInterp )
|
||||
{
|
||||
if( !g_pPositionInterpolators[iInterp] )
|
||||
g_pPositionInterpolators[iInterp] = Motion_GetPositionInterpolator( iInterp );
|
||||
|
||||
return g_pPositionInterpolators[iInterp];
|
||||
}
|
||||
|
||||
|
||||
static float Fix( float angle )
|
||||
{
|
||||
while ( angle < 0 )
|
||||
angle += 360;
|
||||
while ( angle > 360 )
|
||||
angle -= 360;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
void FixupAngles( QAngle &v )
|
||||
{
|
||||
v.x = Fix( v.x );
|
||||
v.y = Fix( v.y );
|
||||
v.z = Fix( v.z );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Contains a description of a keyframe
|
||||
// has no networked representation, so has to store origin, etc. itself
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CPathKeyFrame : public CLogicalEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CPathKeyFrame, CLogicalEntity );
|
||||
|
||||
void Spawn( void );
|
||||
void Activate( void );
|
||||
void Link( void );
|
||||
|
||||
Vector m_Origin;
|
||||
QAngle m_Angles; // euler angles PITCH YAW ROLL (Y Z X)
|
||||
Quaternion m_qAngle; // quaternion angle (generated from m_Angles)
|
||||
|
||||
string_t m_iNextKey;
|
||||
float m_flNextTime;
|
||||
|
||||
CPathKeyFrame *NextKey( int direction );
|
||||
CPathKeyFrame *PrevKey( int direction );
|
||||
|
||||
float Speed( void ) { return m_flSpeed; }
|
||||
void SetKeyAngles( QAngle angles );
|
||||
|
||||
CPathKeyFrame *InsertNewKey( Vector newPos, QAngle newAngles );
|
||||
void CalculateFrameDuration( void );
|
||||
|
||||
protected:
|
||||
CPathKeyFrame *m_pNextKey;
|
||||
CPathKeyFrame *m_pPrevKey;
|
||||
|
||||
float m_flSpeed;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( keyframe_track, CPathKeyFrame );
|
||||
|
||||
BEGIN_DATADESC( CPathKeyFrame )
|
||||
|
||||
DEFINE_FIELD( m_Origin, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_Angles, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_qAngle, FIELD_QUATERNION ),
|
||||
|
||||
DEFINE_KEYFIELD( m_iNextKey, FIELD_STRING, "NextKey" ),
|
||||
DEFINE_FIELD( m_flNextTime, FIELD_FLOAT ), // derived from speed
|
||||
DEFINE_KEYFIELD( m_flSpeed, FIELD_FLOAT, "MoveSpeed" ),
|
||||
DEFINE_FIELD( m_pNextKey, FIELD_CLASSPTR ),
|
||||
DEFINE_FIELD( m_pPrevKey, FIELD_CLASSPTR ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Converts inputed euler angles to internal angle format (quaternions)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPathKeyFrame::Spawn( void )
|
||||
{
|
||||
m_Origin = GetLocalOrigin();
|
||||
m_Angles = GetLocalAngles();
|
||||
|
||||
SetKeyAngles( m_Angles );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Adds the keyframe into the path after all the other keys have spawned
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPathKeyFrame::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
Link();
|
||||
|
||||
CalculateFrameDuration();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPathKeyFrame::CalculateFrameDuration( void )
|
||||
{
|
||||
// calculate time from speed
|
||||
if ( m_pNextKey && m_flSpeed > 0 )
|
||||
{
|
||||
m_flNextTime = (m_Origin - m_pNextKey->m_Origin).Length() / m_flSpeed;
|
||||
|
||||
// couldn't get time from distance, get it from rotation instead
|
||||
if ( !m_flNextTime )
|
||||
{
|
||||
// speed is in degrees per second
|
||||
// find the largest rotation component and use that
|
||||
QAngle ang = m_Angles - m_pNextKey->m_Angles;
|
||||
FixupAngles( ang );
|
||||
float x = 0;
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
{
|
||||
if ( abs(ang[i]) > x )
|
||||
{
|
||||
x = abs(ang[i]);
|
||||
}
|
||||
}
|
||||
|
||||
m_flNextTime = x / m_flSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Links the key frame into the key frame list
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPathKeyFrame::Link( void )
|
||||
{
|
||||
m_pNextKey = dynamic_cast<CPathKeyFrame*>( gEntList.FindEntityByName(NULL, m_iNextKey ) );
|
||||
|
||||
if ( m_pNextKey )
|
||||
{
|
||||
m_pNextKey->m_pPrevKey = this;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : angles -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPathKeyFrame::SetKeyAngles( QAngle angles )
|
||||
{
|
||||
m_Angles = angles;
|
||||
AngleQuaternion( m_Angles, m_qAngle );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : direction -
|
||||
// Output : CPathKeyFrame
|
||||
//-----------------------------------------------------------------------------
|
||||
CPathKeyFrame* CPathKeyFrame::NextKey( int direction )
|
||||
{
|
||||
if ( direction == 1 )
|
||||
{
|
||||
return m_pNextKey;
|
||||
}
|
||||
else if ( direction == -1 )
|
||||
{
|
||||
return m_pPrevKey;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : direction -
|
||||
// Output : CPathKeyFrame
|
||||
//-----------------------------------------------------------------------------
|
||||
CPathKeyFrame *CPathKeyFrame::PrevKey( int direction )
|
||||
{
|
||||
if ( direction == 1 )
|
||||
{
|
||||
return m_pPrevKey;
|
||||
}
|
||||
else if ( direction == -1 )
|
||||
{
|
||||
return m_pNextKey;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates and insterts a new keyframe into the sequence
|
||||
// Input : newPos -
|
||||
// newAngles -
|
||||
// Output : CPathKeyFrame
|
||||
//-----------------------------------------------------------------------------
|
||||
CPathKeyFrame *CPathKeyFrame::InsertNewKey( Vector newPos, QAngle newAngles )
|
||||
{
|
||||
CPathKeyFrame *newKey = CREATE_ENTITY( CPathKeyFrame, "keyframe_track" );
|
||||
|
||||
// copy data across
|
||||
newKey->SetKeyAngles( newAngles );
|
||||
newKey->m_Origin = newPos;
|
||||
newKey->m_flSpeed = m_flSpeed;
|
||||
newKey->SetEFlags( GetEFlags() );
|
||||
if ( m_iParent != NULL_STRING )
|
||||
{
|
||||
newKey->SetParent( m_iParent, NULL );
|
||||
}
|
||||
|
||||
// link forward
|
||||
newKey->m_pNextKey = m_pNextKey;
|
||||
m_pNextKey->m_pPrevKey = newKey;
|
||||
|
||||
// link back
|
||||
m_pNextKey = newKey;
|
||||
newKey->m_pPrevKey = this;
|
||||
|
||||
// calculate new times
|
||||
CalculateFrameDuration();
|
||||
newKey->CalculateFrameDuration();
|
||||
|
||||
return newKey;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Basic keyframed movement behavior
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBaseMoveBehavior : public CPathKeyFrame
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CBaseMoveBehavior, CPathKeyFrame );
|
||||
|
||||
void Spawn( void );
|
||||
void Activate( void );
|
||||
void MoveDone( void );
|
||||
float SetObjectPhysicsVelocity( float moveTime );
|
||||
|
||||
// methods
|
||||
virtual bool StartMoving( int direction );
|
||||
virtual void StopMoving( void );
|
||||
virtual bool IsMoving( void );
|
||||
|
||||
// derived classes should override this to get notification of arriving at new keyframes
|
||||
// virtual void ArrivedAtKeyFrame( CPathKeyFrame * ) {}
|
||||
|
||||
bool IsAtSequenceStart( void );
|
||||
bool IsAtSequenceEnd( void );
|
||||
|
||||
// interpolation functions
|
||||
// int m_iTimeModifier;
|
||||
int m_iPositionInterpolator;
|
||||
int m_iRotationInterpolator;
|
||||
|
||||
// animation vars
|
||||
float m_flAnimStartTime;
|
||||
float m_flAnimEndTime;
|
||||
float m_flAverageSpeedAcrossFrame; // for advancing time with speed (not the normal visa-versa)
|
||||
CPathKeyFrame *m_pCurrentKeyFrame; // keyframe currently moving from
|
||||
CPathKeyFrame *m_pTargetKeyFrame; // keyframe being moved to
|
||||
CPathKeyFrame *m_pPreKeyFrame, *m_pPostKeyFrame; // pre- and post-keyframe's for spline interpolation
|
||||
float m_flTimeIntoFrame;
|
||||
|
||||
int m_iDirection; // 1 for forward, -1 for backward, and 0 for at rest
|
||||
|
||||
float CalculateTimeAdvancementForSpeed( float moveTime, float speed );
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( move_keyframed, CBaseMoveBehavior );
|
||||
|
||||
BEGIN_DATADESC( CBaseMoveBehavior )
|
||||
|
||||
// DEFINE_KEYFIELD( m_iTimeModifier, FIELD_INTEGER, "TimeModifier" ),
|
||||
DEFINE_KEYFIELD( m_iPositionInterpolator, FIELD_INTEGER, "PositionInterpolator" ),
|
||||
DEFINE_KEYFIELD( m_iRotationInterpolator, FIELD_INTEGER, "RotationInterpolator" ),
|
||||
|
||||
DEFINE_FIELD( m_pCurrentKeyFrame, FIELD_CLASSPTR ),
|
||||
DEFINE_FIELD( m_pTargetKeyFrame, FIELD_CLASSPTR ),
|
||||
DEFINE_FIELD( m_pPreKeyFrame, FIELD_CLASSPTR ),
|
||||
DEFINE_FIELD( m_pPostKeyFrame, FIELD_CLASSPTR ),
|
||||
|
||||
DEFINE_FIELD( m_flAnimStartTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flAnimEndTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flAverageSpeedAcrossFrame, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flTimeIntoFrame, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_iDirection, FIELD_INTEGER ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
void CBaseMoveBehavior::Spawn( void )
|
||||
{
|
||||
m_pCurrentKeyFrame = this;
|
||||
m_flTimeIntoFrame = 0;
|
||||
SetMoveType( MOVETYPE_PUSH );
|
||||
|
||||
// a move behavior is also it's first keyframe
|
||||
m_Origin = GetLocalOrigin();
|
||||
m_Angles = GetLocalAngles();
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
void CBaseMoveBehavior::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
SetMoveDoneTime( 0.5 ); // start moving in 0.2 seconds time
|
||||
|
||||
// if we are just the basic keyframed entity, cycle our animation
|
||||
if ( !stricmp(GetClassname(), "move_keyframed") )
|
||||
{
|
||||
StartMoving( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Checks to see if the we're at the start of the keyframe sequence
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMoveBehavior::IsAtSequenceStart( void )
|
||||
{
|
||||
if ( !m_pCurrentKeyFrame )
|
||||
return true;
|
||||
|
||||
if ( m_flAnimStartTime && m_flAnimStartTime >= GetLocalTime() )
|
||||
{
|
||||
if ( !m_pCurrentKeyFrame->PrevKey(1) && !m_pTargetKeyFrame )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Checks to see if we're at the end of the keyframe sequence
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMoveBehavior::IsAtSequenceEnd( void )
|
||||
{
|
||||
if ( !m_pCurrentKeyFrame )
|
||||
return false;
|
||||
|
||||
if ( !m_pCurrentKeyFrame->NextKey(1) && !m_pTargetKeyFrame )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMoveBehavior::IsMoving( void )
|
||||
{
|
||||
if ( m_iDirection != 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Starts the object moving from it's current position, in the direction indicated
|
||||
// Input : direction - 1 is forward through the sequence, -1 is backwards, and 0 is stop
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMoveBehavior::StartMoving( int direction )
|
||||
{
|
||||
// 0 direction is to stop moving
|
||||
if ( direction == 0 )
|
||||
{
|
||||
StopMoving();
|
||||
return false;
|
||||
}
|
||||
|
||||
// check to see if we should keep moving in the current direction
|
||||
if ( m_iDirection == direction )
|
||||
{
|
||||
// if we're at the end of the current anim key, move to the next one
|
||||
if ( GetLocalTime() >= m_flAnimEndTime )
|
||||
{
|
||||
m_pCurrentKeyFrame = m_pTargetKeyFrame;
|
||||
m_flTimeIntoFrame = 0;
|
||||
|
||||
if ( !m_pTargetKeyFrame->NextKey(direction) )
|
||||
{
|
||||
// we've hit the end of the sequence
|
||||
m_flAnimEndTime = 0;
|
||||
m_flAnimStartTime = 0;
|
||||
StopMoving();
|
||||
return false;
|
||||
}
|
||||
|
||||
// advance the target keyframe
|
||||
m_pTargetKeyFrame = m_pTargetKeyFrame->NextKey(direction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're changing direction
|
||||
|
||||
// need to calculate current position in the frame
|
||||
// stop first, then start again
|
||||
if ( m_iDirection != 0 )
|
||||
{
|
||||
StopMoving();
|
||||
}
|
||||
|
||||
m_iDirection = direction;
|
||||
|
||||
// if we're going in reverse, swap the currentkey and targetkey (since we're going opposite dir)
|
||||
if ( direction == 1 )
|
||||
{
|
||||
m_pTargetKeyFrame = m_pCurrentKeyFrame->NextKey( direction );
|
||||
}
|
||||
else if ( direction == -1 )
|
||||
{
|
||||
if ( m_flTimeIntoFrame > 0 )
|
||||
{
|
||||
m_pTargetKeyFrame = m_pCurrentKeyFrame;
|
||||
m_pCurrentKeyFrame = m_pCurrentKeyFrame->NextKey( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTargetKeyFrame = m_pCurrentKeyFrame->PrevKey( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// recalculate our movement from the stored data
|
||||
if ( !m_pTargetKeyFrame )
|
||||
{
|
||||
StopMoving();
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate the keyframes before and after the keyframes we're interpolating between
|
||||
m_pPostKeyFrame = m_pTargetKeyFrame->NextKey( direction );
|
||||
if ( !m_pPostKeyFrame )
|
||||
{
|
||||
m_pPostKeyFrame = m_pTargetKeyFrame;
|
||||
}
|
||||
m_pPreKeyFrame = m_pCurrentKeyFrame->PrevKey( direction );
|
||||
if ( !m_pPreKeyFrame )
|
||||
{
|
||||
m_pPreKeyFrame = m_pCurrentKeyFrame;
|
||||
}
|
||||
}
|
||||
|
||||
// no target, can't move
|
||||
if ( !m_pTargetKeyFrame )
|
||||
return false;
|
||||
|
||||
// calculate start/end time
|
||||
// ->m_flNextTime is the time to traverse to the NEXT key, so we need the opposite if travelling backwards
|
||||
if ( m_iDirection == 1 )
|
||||
{
|
||||
m_flAnimStartTime = GetLocalTime() - m_flTimeIntoFrame;
|
||||
m_flAnimEndTime = GetLocalTime() + m_pCurrentKeyFrame->m_flNextTime - m_flTimeIntoFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
// flip the timing, since we're in reverse
|
||||
if ( m_flTimeIntoFrame )
|
||||
m_flTimeIntoFrame = m_pTargetKeyFrame->m_flNextTime - m_flTimeIntoFrame;
|
||||
|
||||
m_flAnimStartTime = GetLocalTime() - m_flTimeIntoFrame;
|
||||
m_flAnimEndTime = GetLocalTime() + m_pTargetKeyFrame->m_flNextTime - m_flTimeIntoFrame;
|
||||
}
|
||||
|
||||
// calculate the average speed at which we cross
|
||||
float animDuration = (m_flAnimEndTime - m_flAnimStartTime);
|
||||
float dist = (m_pCurrentKeyFrame->m_Origin - m_pTargetKeyFrame->m_Origin).Length();
|
||||
m_flAverageSpeedAcrossFrame = animDuration / dist;
|
||||
|
||||
SetMoveDoneTime( m_flAnimEndTime - GetLocalTime() );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: stops the object from moving
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseMoveBehavior::StopMoving( void )
|
||||
{
|
||||
// remember exactly where we are in the frame
|
||||
m_flTimeIntoFrame = 0;
|
||||
|
||||
if ( m_iDirection == 1 )
|
||||
{
|
||||
// record the time if we're not at the end of the frame
|
||||
if ( GetLocalTime() < m_flAnimEndTime )
|
||||
{
|
||||
m_flTimeIntoFrame = GetLocalTime() - m_flAnimStartTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're actually at the end
|
||||
if ( m_pTargetKeyFrame )
|
||||
{
|
||||
m_pCurrentKeyFrame = m_pTargetKeyFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( m_iDirection == -1 )
|
||||
{
|
||||
// store it only as a forward movement
|
||||
m_pCurrentKeyFrame = m_pTargetKeyFrame;
|
||||
|
||||
if ( GetLocalTime() < m_flAnimEndTime )
|
||||
{
|
||||
m_flTimeIntoFrame = m_flAnimEndTime - GetLocalTime();
|
||||
}
|
||||
}
|
||||
|
||||
// stop moving totally
|
||||
SetMoveDoneTime( -1 );
|
||||
m_iDirection = 0;
|
||||
m_flAnimStartTime = 0;
|
||||
m_flAnimEndTime = 0;
|
||||
m_pTargetKeyFrame = NULL;
|
||||
SetAbsVelocity(vec3_origin);
|
||||
SetLocalAngularVelocity( vec3_angle );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: We have just arrived at a key, move onto the next keyframe
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseMoveBehavior::MoveDone( void )
|
||||
{
|
||||
// if we're just a base then keep playing the anim
|
||||
if ( !stricmp(STRING(m_iClassname), "move_keyframed") )
|
||||
{
|
||||
int direction = m_iDirection;
|
||||
// start moving from the keyframe we've just reached
|
||||
if ( !StartMoving(direction) )
|
||||
{
|
||||
// try moving in the other direction
|
||||
StartMoving( -direction );
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::MoveDone();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Calculates a new moveTime based on the speed and the current point
|
||||
// in the animation.
|
||||
// used to advance keyframed objects that have dynamic speeds.
|
||||
// Input : moveTime -
|
||||
// Output : float - the new time in the keyframing sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
float CBaseMoveBehavior::CalculateTimeAdvancementForSpeed( float moveTime, float speed )
|
||||
{
|
||||
return (moveTime * speed * m_flAverageSpeedAcrossFrame);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// GetLocalTime() is the objects local current time
|
||||
// Input : destTime - new time that is being moved to
|
||||
// moveTime - amount of time to be advanced this frame
|
||||
// Output : float - the actual amount of time to move (usually moveTime)
|
||||
//-----------------------------------------------------------------------------
|
||||
float CBaseMoveBehavior::SetObjectPhysicsVelocity( float moveTime )
|
||||
{
|
||||
// make sure we have a valid set up
|
||||
if ( !m_pCurrentKeyFrame || !m_pTargetKeyFrame )
|
||||
return moveTime;
|
||||
|
||||
// if we're not moving, we're not moving
|
||||
if ( !IsMoving() )
|
||||
return moveTime;
|
||||
|
||||
float destTime = moveTime + GetLocalTime();
|
||||
|
||||
// work out where we want to be, using destTime
|
||||
m_flTimeIntoFrame = destTime - m_flAnimStartTime;
|
||||
float newTime = (destTime - m_flAnimStartTime) / (m_flAnimEndTime - m_flAnimStartTime);
|
||||
Vector newPos;
|
||||
QAngle newAngles;
|
||||
|
||||
IPositionInterpolator *pInterp = GetPositionInterpolator( m_iPositionInterpolator );
|
||||
if( pInterp )
|
||||
{
|
||||
// setup key frames
|
||||
pInterp->SetKeyPosition( -1, m_pPreKeyFrame->m_Origin );
|
||||
Motion_SetKeyAngles( -1, m_pPreKeyFrame->m_qAngle );
|
||||
|
||||
pInterp->SetKeyPosition( 0, m_pCurrentKeyFrame->m_Origin );
|
||||
Motion_SetKeyAngles( 0, m_pCurrentKeyFrame->m_qAngle );
|
||||
|
||||
pInterp->SetKeyPosition( 1, m_pTargetKeyFrame->m_Origin );
|
||||
Motion_SetKeyAngles( 1, m_pTargetKeyFrame->m_qAngle );
|
||||
|
||||
pInterp->SetKeyPosition( 2, m_pPostKeyFrame->m_Origin );
|
||||
Motion_SetKeyAngles( 2, m_pPostKeyFrame->m_qAngle );
|
||||
|
||||
// find new interpolated position & rotation
|
||||
pInterp->InterpolatePosition( newTime, newPos );
|
||||
}
|
||||
else
|
||||
{
|
||||
newPos.Init();
|
||||
}
|
||||
|
||||
Quaternion qRot;
|
||||
Motion_InterpolateRotation( newTime, m_iRotationInterpolator, qRot );
|
||||
QuaternionAngles( qRot, newAngles );
|
||||
|
||||
// find our velocity vector (newPos - currentPos) and scale velocity vector according to the movetime
|
||||
float oneOnMoveTime = 1 / moveTime;
|
||||
SetAbsVelocity( (newPos - GetLocalOrigin()) * oneOnMoveTime );
|
||||
SetLocalAngularVelocity( (newAngles - GetLocalAngles()) * oneOnMoveTime );
|
||||
|
||||
return moveTime;
|
||||
}
|
||||
|
Reference in New Issue
Block a user