aboutsummaryrefslogtreecommitdiff
path: root/mp/src/public/keyframe/keyframe.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/public/keyframe/keyframe.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/public/keyframe/keyframe.cpp')
-rw-r--r--mp/src/public/keyframe/keyframe.cpp1002
1 files changed, 501 insertions, 501 deletions
diff --git a/mp/src/public/keyframe/keyframe.cpp b/mp/src/public/keyframe/keyframe.cpp
index 0079881b..1e08b0a3 100644
--- a/mp/src/public/keyframe/keyframe.cpp
+++ b/mp/src/public/keyframe/keyframe.cpp
@@ -1,501 +1,501 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $Workfile: $
-// $Date: $
-// $NoKeywords: $
-//=============================================================================//
-
-#include <stdio.h>
-#include <memory.h>
-#include <math.h>
-#include <string.h>
-
-typedef unsigned char byte;
-#pragma warning(disable:4244)
-
-#include "tier0/dbg.h"
-#include "mathlib/vector.h"
-#include "keyframe.h"
-#include "mathlib/mathlib.h"
-#include "rope_shared.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-//-----------------------------------------------------------------------------
-//
-// Implementation of keyframe.h interface
-//
-//-----------------------------------------------------------------------------
-
-
-//-----------------------------------------------------------------------------
-// Key Frames
-//-----------------------------------------------------------------------------
-#define HIGHEST_KEYFRAME 3
-#define LOWEST_KEYFRAME -3
-
-#define TOTAL_KEYFRAMES (HIGHEST_KEYFRAME - LOWEST_KEYFRAME + 1)
-
-//
-
-struct KeyFrame_t
-{
- Vector vPos;
- Quaternion qRot;
-};
-
-
-KeyFrame_t g_KeyFrames[ TOTAL_KEYFRAMES ];
-KeyFrame_t *g_KeyFramePtr = &g_KeyFrames[ -LOWEST_KEYFRAME ]; // points to the middle keyframe, keyframe 0
-
-bool Motion_SetKeyAngles( int keyNum, Quaternion &quatAngles )
-{
- if ( keyNum > HIGHEST_KEYFRAME || keyNum < LOWEST_KEYFRAME )
- return false;
-
- g_KeyFramePtr[keyNum].qRot = quatAngles;
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// Time Modifier function enumeration & implementation
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-typedef float (*TimeModifierFunc_t)(float);
-
-typedef struct
-{
- const char *szName;
- TimeModifierFunc_t pFunc;
-
-} TimeModifier_t;
-
-float TimeModifierFunc_Linear( float time )
-{
- return time;
-}
-
-float TimeModifierFunc_Cosine( float time )
-{
- return ( cos((time+1) * M_PI) * 0.5 ) + 0.5;
-}
-
-float TimeModifierFunc_TimeSquared( float time )
-{
- return (time * time);
-}
-
-TimeModifier_t g_TimeModifiers[] =
-{
- { "Linear", TimeModifierFunc_Linear },
- { "Accel/Deaccel (cosine)", TimeModifierFunc_Cosine },
- { "Accel (time*time)", TimeModifierFunc_TimeSquared },
-};
-
-int Motion_GetNumberOfTimeModifiers( void )
-{
- return ARRAYSIZE(g_TimeModifiers);
-}
-
-bool Motion_GetTimeModifierDetails( int timeInterpNum, const char **outName )
-{
- if ( timeInterpNum < 0 || timeInterpNum >= Motion_GetNumberOfTimeModifiers() )
- {
- return false;
- }
-
- if ( !g_TimeModifiers[0].szName || !g_TimeModifiers[0].pFunc )
- {
- return false;
- }
-
- if ( outName )
- *outName = g_TimeModifiers[0].szName;
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : time -
-// timeModifierFuncNum -
-// *outNewTime -
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool Motion_CalculateModifiedTime( float time, int timeModifierFuncNum, float *outNewTime )
-{
- *outNewTime = g_TimeModifiers[timeModifierFuncNum].pFunc( time );
- return true;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// Position interpolator function enumeration & implementation
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-// ------------------------------------------------------------------------------------ //
-// Linear position interpolator.
-// ------------------------------------------------------------------------------------ //
-
-class CPositionInterpolator_Linear : public IPositionInterpolator
-{
-public:
- virtual void Release();
- virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
- virtual void SetKeyPosition( int keyNum, Vector const &vPos );
- virtual void InterpolatePosition( float time, Vector &vOut );
- virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; }
-};
-
-CPositionInterpolator_Linear g_LinearInterpolator;
-
-IPositionInterpolator* GetLinearInterpolator()
-{
- return &g_LinearInterpolator;
-}
-
-void CPositionInterpolator_Linear::Release()
-{
-}
-
-void CPositionInterpolator_Linear::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
-{
- *outName = "Linear";
- *outMinKeyReq = 0;
- *outMaxKeyReq = 1;
-}
-
-void CPositionInterpolator_Linear::SetKeyPosition( int keyNum, Vector const &vPos )
-{
- Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME );
- VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos );
-}
-
-void CPositionInterpolator_Linear::InterpolatePosition( float time, Vector &vOut )
-{
- VectorLerp( g_KeyFramePtr[0].vPos, g_KeyFramePtr[1].vPos, time, vOut );
-}
-
-
-
-
-
-// ------------------------------------------------------------------------------------ //
-// Catmull-Rom position interpolator.
-// ------------------------------------------------------------------------------------ //
-
-class CPositionInterpolator_CatmullRom : public IPositionInterpolator
-{
-public:
- virtual void Release();
- virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
- virtual void SetKeyPosition( int keyNum, Vector const &vPos );
- virtual void InterpolatePosition( float time, Vector &vOut );
- virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; }
-};
-
-CPositionInterpolator_CatmullRom g_CatmullRomInterpolator;
-
-IPositionInterpolator* GetCatmullRomInterpolator()
-{
- return &g_CatmullRomInterpolator;
-}
-
-void CPositionInterpolator_CatmullRom::Release()
-{
-}
-
-void CPositionInterpolator_CatmullRom::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
-{
- *outName = "Catmull-Rom Spline";
- *outMinKeyReq = -1;
- *outMaxKeyReq = 2;
-}
-
-void CPositionInterpolator_CatmullRom::SetKeyPosition( int keyNum, Vector const &vPos )
-{
- Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME );
- VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos );
-}
-
-void CPositionInterpolator_CatmullRom::InterpolatePosition( float time, Vector &vOut )
-{
- Catmull_Rom_Spline(
- g_KeyFramePtr[-1].vPos,
- g_KeyFramePtr[0].vPos,
- g_KeyFramePtr[1].vPos,
- g_KeyFramePtr[2].vPos,
- time,
- vOut );
-}
-
-
-
-// ------------------------------------------------------------------------------------ //
-// Rope interpolator.
-// ------------------------------------------------------------------------------------ //
-#include "rope_physics.h"
-
-class CRopeDelegate : public CSimplePhysics::IHelper
-{
-public:
- virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel );
- virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes );
-
-
-public:
- Vector m_CurEndPoints[2];
-};
-
-void CRopeDelegate::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel )
-{
- // Gravity.
- pAccel->Init( 0, 0, -1500 );
-}
-
-void CRopeDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
-{
- if( nNodes >= 2 )
- {
- pNodes[0].m_vPos = m_CurEndPoints[0];
- pNodes[nNodes-1].m_vPos = m_CurEndPoints[1];
- }
-}
-
-
-class CPositionInterpolator_Rope : public IPositionInterpolator
-{
-public:
- CPositionInterpolator_Rope();
-
- virtual void Release();
- virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
- virtual void SetKeyPosition( int keyNum, Vector const &vPos );
- virtual void InterpolatePosition( float time, Vector &vOut );
- virtual bool ProcessKey( char const *pName, char const *pValue );
-
-
-private:
- CRopePhysics<10> m_RopePhysics;
- CRopeDelegate m_Delegate;
-
- float m_flSlack; // Extra length of rope.
-
- bool m_bChange;
- int m_nSegments;
-};
-
-IPositionInterpolator* GetRopeInterpolator()
-{
- return new CPositionInterpolator_Rope;
-}
-
-
-CPositionInterpolator_Rope::CPositionInterpolator_Rope()
-{
- m_flSlack = 0;
- m_bChange = false;
- m_nSegments = 5;
-
- for( int i=0; i < 2; i++ )
- m_Delegate.m_CurEndPoints[i] = Vector( 1e24, 1e24, 1e24 );
-}
-
-void CPositionInterpolator_Rope::Release()
-{
- delete this;
-}
-
-void CPositionInterpolator_Rope::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
-{
- *outName = "Rope";
- *outMinKeyReq = 0;
- *outMinKeyReq = 1;
-}
-
-void CPositionInterpolator_Rope::SetKeyPosition( int keyNum, Vector const &vPos )
-{
- if( keyNum == 0 || keyNum == 1 )
- {
- if( vPos != m_Delegate.m_CurEndPoints[keyNum] )
- m_bChange = true;
-
- m_Delegate.m_CurEndPoints[keyNum] = vPos;
- }
-}
-
-void CPositionInterpolator_Rope::InterpolatePosition( float time, Vector &vOut )
-{
- // Check if we need to resimulate..
- if( m_bChange )
- {
- m_RopePhysics.SetNumNodes( m_nSegments );
-
- // Init all the nodes.
- for( int i=0; i < m_RopePhysics.NumNodes(); i++ )
- m_RopePhysics.GetNode(i)->m_vPos = m_RopePhysics.GetNode(i)->m_vPrevPos = m_Delegate.m_CurEndPoints[0];
-
- float flDist = (m_Delegate.m_CurEndPoints[0] - m_Delegate.m_CurEndPoints[1]).Length();
- flDist += m_flSlack;
-
- m_RopePhysics.Restart();
- m_RopePhysics.SetupSimulation( flDist / (m_RopePhysics.NumNodes() - 1), &m_Delegate );
-
- // Run the simulation for a while to let the rope settle down..
- m_RopePhysics.Simulate( 5 );
-
- m_bChange = false;
- }
-
- // Ok, now we have all the nodes setup..
- float flNode = time * (m_RopePhysics.NumNodes()-1);
- int iNode = (int)( flNode );
- VectorLerp(
- m_RopePhysics.GetNode(iNode)->m_vPredicted,
- m_RopePhysics.GetNode(iNode+1)->m_vPredicted,
- flNode - iNode,
- vOut );
-}
-
-bool CPositionInterpolator_Rope::ProcessKey( char const *pName, char const *pValue )
-{
- if( stricmp( pName, "Slack" ) == 0 )
- {
- m_flSlack = atof( pValue ) + ROPESLACK_FUDGEFACTOR;
- m_bChange = true;
- return true;
- }
- else if( stricmp( pName, "Type" ) == 0 )
- {
- int iType = atoi( pValue );
- if( iType == 0 )
- m_nSegments = ROPE_MAX_SEGMENTS;
- else if( iType == 1 )
- m_nSegments = ROPE_TYPE1_NUMSEGMENTS;
- else
- m_nSegments = ROPE_TYPE2_NUMSEGMENTS;
-
- m_bChange = true;
- return true;
- }
-
- return false;
-}
-
-
-
-// ------------------------------------------------------------------------------------ //
-// The global table of all the position interpolators.
-// ------------------------------------------------------------------------------------ //
-
-typedef IPositionInterpolator* (*PositionInterpolatorCreateFn)();
-PositionInterpolatorCreateFn g_PositionInterpolatorCreateFns[] =
-{
- GetLinearInterpolator,
- GetCatmullRomInterpolator,
- GetRopeInterpolator
-};
-
-int Motion_GetNumberOfPositionInterpolators( void )
-{
- return ARRAYSIZE(g_PositionInterpolatorCreateFns);
-}
-
-
-IPositionInterpolator* Motion_GetPositionInterpolator( int interpNum )
-{
- Assert( interpNum >= 0 && interpNum < Motion_GetNumberOfPositionInterpolators() );
- return g_PositionInterpolatorCreateFns[clamp( interpNum, 0, Motion_GetNumberOfPositionInterpolators() - 1 )]();
-}
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// Rotation interpolator function enumeration & implementation
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-typedef void (*RotationInterpolatorFunc_t)(float time, Quaternion &outRot);
-
-typedef struct
-{
- char *szName;
- RotationInterpolatorFunc_t pFunc;
-
- // defines the range of keys this interpolator needs to function
- int iMinReqKeyFrame;
- int iMaxReqKeyFrame;
-
-} RotationInterpolator_t;
-
-void RotationInterpolatorFunc_Linear( float time, Quaternion &outRot )
-{
- // basic 4D spherical linear interpolation
- QuaternionSlerp( g_KeyFramePtr[0].qRot, g_KeyFramePtr[1].qRot, time, outRot );
-}
-
-RotationInterpolator_t g_RotationInterpolators[] =
-{
- { "Linear", RotationInterpolatorFunc_Linear, 0, 1 },
-};
-
-int Motion_GetNumberOfRotationInterpolators( void )
-{
- return ARRAYSIZE(g_RotationInterpolators);
-}
-
-bool Motion_GetRotationInterpolatorDetails( int rotInterpNum, char **outName, int *outMinKeyReq, int *outMaxKeyReq )
-{
- if ( rotInterpNum < 0 || rotInterpNum >= Motion_GetNumberOfRotationInterpolators() )
- {
- return false;
- }
-
- if ( !g_RotationInterpolators[rotInterpNum].szName || !g_RotationInterpolators[rotInterpNum].pFunc )
- {
- return false;
- }
-
- if ( outName )
- *outName = g_RotationInterpolators[rotInterpNum].szName;
-
- if ( outMinKeyReq )
- *outMinKeyReq = g_RotationInterpolators[rotInterpNum].iMinReqKeyFrame;
-
- if ( outMaxKeyReq )
- *outMaxKeyReq = g_RotationInterpolators[rotInterpNum].iMaxReqKeyFrame;
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Interpolates a rotation
-// Time is assumed to have already been modified by the TimeModifyFunc (above)
-// Requires the keyframes be already set
-// Input : time - value from 0..1
-// interpFuncNum -
-// *outQuatRotation - result in quaternion form
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool Motion_InterpolateRotation( float time, int interpFuncNum, Quaternion &outQuatRotation )
-{
- if ( time < 0.0f || time > 1.0f )
- return false;
-
- g_RotationInterpolators[interpFuncNum].pFunc( time, outQuatRotation );
- return true;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//=============================================================================//
+
+#include <stdio.h>
+#include <memory.h>
+#include <math.h>
+#include <string.h>
+
+typedef unsigned char byte;
+#pragma warning(disable:4244)
+
+#include "tier0/dbg.h"
+#include "mathlib/vector.h"
+#include "keyframe.h"
+#include "mathlib/mathlib.h"
+#include "rope_shared.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+//
+// Implementation of keyframe.h interface
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Key Frames
+//-----------------------------------------------------------------------------
+#define HIGHEST_KEYFRAME 3
+#define LOWEST_KEYFRAME -3
+
+#define TOTAL_KEYFRAMES (HIGHEST_KEYFRAME - LOWEST_KEYFRAME + 1)
+
+//
+
+struct KeyFrame_t
+{
+ Vector vPos;
+ Quaternion qRot;
+};
+
+
+KeyFrame_t g_KeyFrames[ TOTAL_KEYFRAMES ];
+KeyFrame_t *g_KeyFramePtr = &g_KeyFrames[ -LOWEST_KEYFRAME ]; // points to the middle keyframe, keyframe 0
+
+bool Motion_SetKeyAngles( int keyNum, Quaternion &quatAngles )
+{
+ if ( keyNum > HIGHEST_KEYFRAME || keyNum < LOWEST_KEYFRAME )
+ return false;
+
+ g_KeyFramePtr[keyNum].qRot = quatAngles;
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Time Modifier function enumeration & implementation
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+typedef float (*TimeModifierFunc_t)(float);
+
+typedef struct
+{
+ const char *szName;
+ TimeModifierFunc_t pFunc;
+
+} TimeModifier_t;
+
+float TimeModifierFunc_Linear( float time )
+{
+ return time;
+}
+
+float TimeModifierFunc_Cosine( float time )
+{
+ return ( cos((time+1) * M_PI) * 0.5 ) + 0.5;
+}
+
+float TimeModifierFunc_TimeSquared( float time )
+{
+ return (time * time);
+}
+
+TimeModifier_t g_TimeModifiers[] =
+{
+ { "Linear", TimeModifierFunc_Linear },
+ { "Accel/Deaccel (cosine)", TimeModifierFunc_Cosine },
+ { "Accel (time*time)", TimeModifierFunc_TimeSquared },
+};
+
+int Motion_GetNumberOfTimeModifiers( void )
+{
+ return ARRAYSIZE(g_TimeModifiers);
+}
+
+bool Motion_GetTimeModifierDetails( int timeInterpNum, const char **outName )
+{
+ if ( timeInterpNum < 0 || timeInterpNum >= Motion_GetNumberOfTimeModifiers() )
+ {
+ return false;
+ }
+
+ if ( !g_TimeModifiers[0].szName || !g_TimeModifiers[0].pFunc )
+ {
+ return false;
+ }
+
+ if ( outName )
+ *outName = g_TimeModifiers[0].szName;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : time -
+// timeModifierFuncNum -
+// *outNewTime -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool Motion_CalculateModifiedTime( float time, int timeModifierFuncNum, float *outNewTime )
+{
+ *outNewTime = g_TimeModifiers[timeModifierFuncNum].pFunc( time );
+ return true;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Position interpolator function enumeration & implementation
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------------------ //
+// Linear position interpolator.
+// ------------------------------------------------------------------------------------ //
+
+class CPositionInterpolator_Linear : public IPositionInterpolator
+{
+public:
+ virtual void Release();
+ virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
+ virtual void SetKeyPosition( int keyNum, Vector const &vPos );
+ virtual void InterpolatePosition( float time, Vector &vOut );
+ virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; }
+};
+
+CPositionInterpolator_Linear g_LinearInterpolator;
+
+IPositionInterpolator* GetLinearInterpolator()
+{
+ return &g_LinearInterpolator;
+}
+
+void CPositionInterpolator_Linear::Release()
+{
+}
+
+void CPositionInterpolator_Linear::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
+{
+ *outName = "Linear";
+ *outMinKeyReq = 0;
+ *outMaxKeyReq = 1;
+}
+
+void CPositionInterpolator_Linear::SetKeyPosition( int keyNum, Vector const &vPos )
+{
+ Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME );
+ VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos );
+}
+
+void CPositionInterpolator_Linear::InterpolatePosition( float time, Vector &vOut )
+{
+ VectorLerp( g_KeyFramePtr[0].vPos, g_KeyFramePtr[1].vPos, time, vOut );
+}
+
+
+
+
+
+// ------------------------------------------------------------------------------------ //
+// Catmull-Rom position interpolator.
+// ------------------------------------------------------------------------------------ //
+
+class CPositionInterpolator_CatmullRom : public IPositionInterpolator
+{
+public:
+ virtual void Release();
+ virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
+ virtual void SetKeyPosition( int keyNum, Vector const &vPos );
+ virtual void InterpolatePosition( float time, Vector &vOut );
+ virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; }
+};
+
+CPositionInterpolator_CatmullRom g_CatmullRomInterpolator;
+
+IPositionInterpolator* GetCatmullRomInterpolator()
+{
+ return &g_CatmullRomInterpolator;
+}
+
+void CPositionInterpolator_CatmullRom::Release()
+{
+}
+
+void CPositionInterpolator_CatmullRom::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
+{
+ *outName = "Catmull-Rom Spline";
+ *outMinKeyReq = -1;
+ *outMaxKeyReq = 2;
+}
+
+void CPositionInterpolator_CatmullRom::SetKeyPosition( int keyNum, Vector const &vPos )
+{
+ Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME );
+ VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos );
+}
+
+void CPositionInterpolator_CatmullRom::InterpolatePosition( float time, Vector &vOut )
+{
+ Catmull_Rom_Spline(
+ g_KeyFramePtr[-1].vPos,
+ g_KeyFramePtr[0].vPos,
+ g_KeyFramePtr[1].vPos,
+ g_KeyFramePtr[2].vPos,
+ time,
+ vOut );
+}
+
+
+
+// ------------------------------------------------------------------------------------ //
+// Rope interpolator.
+// ------------------------------------------------------------------------------------ //
+#include "rope_physics.h"
+
+class CRopeDelegate : public CSimplePhysics::IHelper
+{
+public:
+ virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel );
+ virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes );
+
+
+public:
+ Vector m_CurEndPoints[2];
+};
+
+void CRopeDelegate::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel )
+{
+ // Gravity.
+ pAccel->Init( 0, 0, -1500 );
+}
+
+void CRopeDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
+{
+ if( nNodes >= 2 )
+ {
+ pNodes[0].m_vPos = m_CurEndPoints[0];
+ pNodes[nNodes-1].m_vPos = m_CurEndPoints[1];
+ }
+}
+
+
+class CPositionInterpolator_Rope : public IPositionInterpolator
+{
+public:
+ CPositionInterpolator_Rope();
+
+ virtual void Release();
+ virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
+ virtual void SetKeyPosition( int keyNum, Vector const &vPos );
+ virtual void InterpolatePosition( float time, Vector &vOut );
+ virtual bool ProcessKey( char const *pName, char const *pValue );
+
+
+private:
+ CRopePhysics<10> m_RopePhysics;
+ CRopeDelegate m_Delegate;
+
+ float m_flSlack; // Extra length of rope.
+
+ bool m_bChange;
+ int m_nSegments;
+};
+
+IPositionInterpolator* GetRopeInterpolator()
+{
+ return new CPositionInterpolator_Rope;
+}
+
+
+CPositionInterpolator_Rope::CPositionInterpolator_Rope()
+{
+ m_flSlack = 0;
+ m_bChange = false;
+ m_nSegments = 5;
+
+ for( int i=0; i < 2; i++ )
+ m_Delegate.m_CurEndPoints[i] = Vector( 1e24, 1e24, 1e24 );
+}
+
+void CPositionInterpolator_Rope::Release()
+{
+ delete this;
+}
+
+void CPositionInterpolator_Rope::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
+{
+ *outName = "Rope";
+ *outMinKeyReq = 0;
+ *outMinKeyReq = 1;
+}
+
+void CPositionInterpolator_Rope::SetKeyPosition( int keyNum, Vector const &vPos )
+{
+ if( keyNum == 0 || keyNum == 1 )
+ {
+ if( vPos != m_Delegate.m_CurEndPoints[keyNum] )
+ m_bChange = true;
+
+ m_Delegate.m_CurEndPoints[keyNum] = vPos;
+ }
+}
+
+void CPositionInterpolator_Rope::InterpolatePosition( float time, Vector &vOut )
+{
+ // Check if we need to resimulate..
+ if( m_bChange )
+ {
+ m_RopePhysics.SetNumNodes( m_nSegments );
+
+ // Init all the nodes.
+ for( int i=0; i < m_RopePhysics.NumNodes(); i++ )
+ m_RopePhysics.GetNode(i)->m_vPos = m_RopePhysics.GetNode(i)->m_vPrevPos = m_Delegate.m_CurEndPoints[0];
+
+ float flDist = (m_Delegate.m_CurEndPoints[0] - m_Delegate.m_CurEndPoints[1]).Length();
+ flDist += m_flSlack;
+
+ m_RopePhysics.Restart();
+ m_RopePhysics.SetupSimulation( flDist / (m_RopePhysics.NumNodes() - 1), &m_Delegate );
+
+ // Run the simulation for a while to let the rope settle down..
+ m_RopePhysics.Simulate( 5 );
+
+ m_bChange = false;
+ }
+
+ // Ok, now we have all the nodes setup..
+ float flNode = time * (m_RopePhysics.NumNodes()-1);
+ int iNode = (int)( flNode );
+ VectorLerp(
+ m_RopePhysics.GetNode(iNode)->m_vPredicted,
+ m_RopePhysics.GetNode(iNode+1)->m_vPredicted,
+ flNode - iNode,
+ vOut );
+}
+
+bool CPositionInterpolator_Rope::ProcessKey( char const *pName, char const *pValue )
+{
+ if( stricmp( pName, "Slack" ) == 0 )
+ {
+ m_flSlack = atof( pValue ) + ROPESLACK_FUDGEFACTOR;
+ m_bChange = true;
+ return true;
+ }
+ else if( stricmp( pName, "Type" ) == 0 )
+ {
+ int iType = atoi( pValue );
+ if( iType == 0 )
+ m_nSegments = ROPE_MAX_SEGMENTS;
+ else if( iType == 1 )
+ m_nSegments = ROPE_TYPE1_NUMSEGMENTS;
+ else
+ m_nSegments = ROPE_TYPE2_NUMSEGMENTS;
+
+ m_bChange = true;
+ return true;
+ }
+
+ return false;
+}
+
+
+
+// ------------------------------------------------------------------------------------ //
+// The global table of all the position interpolators.
+// ------------------------------------------------------------------------------------ //
+
+typedef IPositionInterpolator* (*PositionInterpolatorCreateFn)();
+PositionInterpolatorCreateFn g_PositionInterpolatorCreateFns[] =
+{
+ GetLinearInterpolator,
+ GetCatmullRomInterpolator,
+ GetRopeInterpolator
+};
+
+int Motion_GetNumberOfPositionInterpolators( void )
+{
+ return ARRAYSIZE(g_PositionInterpolatorCreateFns);
+}
+
+
+IPositionInterpolator* Motion_GetPositionInterpolator( int interpNum )
+{
+ Assert( interpNum >= 0 && interpNum < Motion_GetNumberOfPositionInterpolators() );
+ return g_PositionInterpolatorCreateFns[clamp( interpNum, 0, Motion_GetNumberOfPositionInterpolators() - 1 )]();
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Rotation interpolator function enumeration & implementation
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+typedef void (*RotationInterpolatorFunc_t)(float time, Quaternion &outRot);
+
+typedef struct
+{
+ char *szName;
+ RotationInterpolatorFunc_t pFunc;
+
+ // defines the range of keys this interpolator needs to function
+ int iMinReqKeyFrame;
+ int iMaxReqKeyFrame;
+
+} RotationInterpolator_t;
+
+void RotationInterpolatorFunc_Linear( float time, Quaternion &outRot )
+{
+ // basic 4D spherical linear interpolation
+ QuaternionSlerp( g_KeyFramePtr[0].qRot, g_KeyFramePtr[1].qRot, time, outRot );
+}
+
+RotationInterpolator_t g_RotationInterpolators[] =
+{
+ { "Linear", RotationInterpolatorFunc_Linear, 0, 1 },
+};
+
+int Motion_GetNumberOfRotationInterpolators( void )
+{
+ return ARRAYSIZE(g_RotationInterpolators);
+}
+
+bool Motion_GetRotationInterpolatorDetails( int rotInterpNum, char **outName, int *outMinKeyReq, int *outMaxKeyReq )
+{
+ if ( rotInterpNum < 0 || rotInterpNum >= Motion_GetNumberOfRotationInterpolators() )
+ {
+ return false;
+ }
+
+ if ( !g_RotationInterpolators[rotInterpNum].szName || !g_RotationInterpolators[rotInterpNum].pFunc )
+ {
+ return false;
+ }
+
+ if ( outName )
+ *outName = g_RotationInterpolators[rotInterpNum].szName;
+
+ if ( outMinKeyReq )
+ *outMinKeyReq = g_RotationInterpolators[rotInterpNum].iMinReqKeyFrame;
+
+ if ( outMaxKeyReq )
+ *outMaxKeyReq = g_RotationInterpolators[rotInterpNum].iMaxReqKeyFrame;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Interpolates a rotation
+// Time is assumed to have already been modified by the TimeModifyFunc (above)
+// Requires the keyframes be already set
+// Input : time - value from 0..1
+// interpFuncNum -
+// *outQuatRotation - result in quaternion form
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool Motion_InterpolateRotation( float time, int interpFuncNum, Quaternion &outQuatRotation )
+{
+ if ( time < 0.0f || time > 1.0f )
+ return false;
+
+ g_RotationInterpolators[interpFuncNum].pFunc( time, outQuatRotation );
+ return true;
+}