Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

501 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #include <stdio.h>
  10. #include <memory.h>
  11. #include <math.h>
  12. #include <string.h>
  13. typedef unsigned char byte;
  14. #pragma warning(disable:4244)
  15. #include "tier0/dbg.h"
  16. #include "mathlib/vector.h"
  17. #include "keyframe.h"
  18. #include "mathlib/mathlib.h"
  19. #include "rope_shared.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. //-----------------------------------------------------------------------------
  23. //
  24. // Implementation of keyframe.h interface
  25. //
  26. //-----------------------------------------------------------------------------
  27. //-----------------------------------------------------------------------------
  28. // Key Frames
  29. //-----------------------------------------------------------------------------
  30. #define HIGHEST_KEYFRAME 3
  31. #define LOWEST_KEYFRAME -3
  32. #define TOTAL_KEYFRAMES (HIGHEST_KEYFRAME - LOWEST_KEYFRAME + 1)
  33. //
  34. struct KeyFrame_t
  35. {
  36. Vector vPos;
  37. Quaternion qRot;
  38. };
  39. KeyFrame_t g_KeyFrames[ TOTAL_KEYFRAMES ];
  40. KeyFrame_t *g_KeyFramePtr = &g_KeyFrames[ -LOWEST_KEYFRAME ]; // points to the middle keyframe, keyframe 0
  41. bool Motion_SetKeyAngles( int keyNum, Quaternion &quatAngles )
  42. {
  43. if ( keyNum > HIGHEST_KEYFRAME || keyNum < LOWEST_KEYFRAME )
  44. return false;
  45. g_KeyFramePtr[keyNum].qRot = quatAngles;
  46. return true;
  47. }
  48. //-----------------------------------------------------------------------------
  49. //-----------------------------------------------------------------------------
  50. //-----------------------------------------------------------------------------
  51. // Time Modifier function enumeration & implementation
  52. //-----------------------------------------------------------------------------
  53. //-----------------------------------------------------------------------------
  54. //-----------------------------------------------------------------------------
  55. typedef float (*TimeModifierFunc_t)(float);
  56. typedef struct
  57. {
  58. const char *szName;
  59. TimeModifierFunc_t pFunc;
  60. } TimeModifier_t;
  61. float TimeModifierFunc_Linear( float time )
  62. {
  63. return time;
  64. }
  65. float TimeModifierFunc_Cosine( float time )
  66. {
  67. return ( cos((time+1) * M_PI) * 0.5 ) + 0.5;
  68. }
  69. float TimeModifierFunc_TimeSquared( float time )
  70. {
  71. return (time * time);
  72. }
  73. TimeModifier_t g_TimeModifiers[] =
  74. {
  75. { "Linear", TimeModifierFunc_Linear },
  76. { "Accel/Deaccel (cosine)", TimeModifierFunc_Cosine },
  77. { "Accel (time*time)", TimeModifierFunc_TimeSquared },
  78. };
  79. int Motion_GetNumberOfTimeModifiers( void )
  80. {
  81. return ARRAYSIZE(g_TimeModifiers);
  82. }
  83. bool Motion_GetTimeModifierDetails( int timeInterpNum, const char **outName )
  84. {
  85. if ( timeInterpNum < 0 || timeInterpNum >= Motion_GetNumberOfTimeModifiers() )
  86. {
  87. return false;
  88. }
  89. if ( !g_TimeModifiers[0].szName || !g_TimeModifiers[0].pFunc )
  90. {
  91. return false;
  92. }
  93. if ( outName )
  94. *outName = g_TimeModifiers[0].szName;
  95. return true;
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose:
  99. // Input : time -
  100. // timeModifierFuncNum -
  101. // *outNewTime -
  102. // Output : Returns true on success, false on failure.
  103. //-----------------------------------------------------------------------------
  104. bool Motion_CalculateModifiedTime( float time, int timeModifierFuncNum, float *outNewTime )
  105. {
  106. *outNewTime = g_TimeModifiers[timeModifierFuncNum].pFunc( time );
  107. return true;
  108. }
  109. //-----------------------------------------------------------------------------
  110. //-----------------------------------------------------------------------------
  111. //-----------------------------------------------------------------------------
  112. // Position interpolator function enumeration & implementation
  113. //-----------------------------------------------------------------------------
  114. //-----------------------------------------------------------------------------
  115. //-----------------------------------------------------------------------------
  116. // ------------------------------------------------------------------------------------ //
  117. // Linear position interpolator.
  118. // ------------------------------------------------------------------------------------ //
  119. class CPositionInterpolator_Linear : public IPositionInterpolator
  120. {
  121. public:
  122. virtual void Release();
  123. virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
  124. virtual void SetKeyPosition( int keyNum, Vector const &vPos );
  125. virtual void InterpolatePosition( float time, Vector &vOut );
  126. virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; }
  127. };
  128. CPositionInterpolator_Linear g_LinearInterpolator;
  129. IPositionInterpolator* GetLinearInterpolator()
  130. {
  131. return &g_LinearInterpolator;
  132. }
  133. void CPositionInterpolator_Linear::Release()
  134. {
  135. }
  136. void CPositionInterpolator_Linear::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
  137. {
  138. *outName = "Linear";
  139. *outMinKeyReq = 0;
  140. *outMaxKeyReq = 1;
  141. }
  142. void CPositionInterpolator_Linear::SetKeyPosition( int keyNum, Vector const &vPos )
  143. {
  144. Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME );
  145. VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos );
  146. }
  147. void CPositionInterpolator_Linear::InterpolatePosition( float time, Vector &vOut )
  148. {
  149. VectorLerp( g_KeyFramePtr[0].vPos, g_KeyFramePtr[1].vPos, time, vOut );
  150. }
  151. // ------------------------------------------------------------------------------------ //
  152. // Catmull-Rom position interpolator.
  153. // ------------------------------------------------------------------------------------ //
  154. class CPositionInterpolator_CatmullRom : public IPositionInterpolator
  155. {
  156. public:
  157. virtual void Release();
  158. virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
  159. virtual void SetKeyPosition( int keyNum, Vector const &vPos );
  160. virtual void InterpolatePosition( float time, Vector &vOut );
  161. virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; }
  162. };
  163. CPositionInterpolator_CatmullRom g_CatmullRomInterpolator;
  164. IPositionInterpolator* GetCatmullRomInterpolator()
  165. {
  166. return &g_CatmullRomInterpolator;
  167. }
  168. void CPositionInterpolator_CatmullRom::Release()
  169. {
  170. }
  171. void CPositionInterpolator_CatmullRom::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
  172. {
  173. *outName = "Catmull-Rom Spline";
  174. *outMinKeyReq = -1;
  175. *outMaxKeyReq = 2;
  176. }
  177. void CPositionInterpolator_CatmullRom::SetKeyPosition( int keyNum, Vector const &vPos )
  178. {
  179. Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME );
  180. VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos );
  181. }
  182. void CPositionInterpolator_CatmullRom::InterpolatePosition( float time, Vector &vOut )
  183. {
  184. Catmull_Rom_Spline(
  185. g_KeyFramePtr[-1].vPos,
  186. g_KeyFramePtr[0].vPos,
  187. g_KeyFramePtr[1].vPos,
  188. g_KeyFramePtr[2].vPos,
  189. time,
  190. vOut );
  191. }
  192. // ------------------------------------------------------------------------------------ //
  193. // Rope interpolator.
  194. // ------------------------------------------------------------------------------------ //
  195. #include "rope_physics.h"
  196. class CRopeDelegate : public CSimplePhysics::IHelper
  197. {
  198. public:
  199. virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel );
  200. virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes );
  201. public:
  202. Vector m_CurEndPoints[2];
  203. };
  204. void CRopeDelegate::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel )
  205. {
  206. // Gravity.
  207. pAccel->Init( 0, 0, -1500 );
  208. }
  209. void CRopeDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
  210. {
  211. if( nNodes >= 2 )
  212. {
  213. pNodes[0].m_vPos = m_CurEndPoints[0];
  214. pNodes[nNodes-1].m_vPos = m_CurEndPoints[1];
  215. }
  216. }
  217. class CPositionInterpolator_Rope : public IPositionInterpolator
  218. {
  219. public:
  220. CPositionInterpolator_Rope();
  221. virtual void Release();
  222. virtual void GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq );
  223. virtual void SetKeyPosition( int keyNum, Vector const &vPos );
  224. virtual void InterpolatePosition( float time, Vector &vOut );
  225. virtual bool ProcessKey( char const *pName, char const *pValue );
  226. private:
  227. CRopePhysics<10> m_RopePhysics;
  228. CRopeDelegate m_Delegate;
  229. float m_flSlack; // Extra length of rope.
  230. bool m_bChange;
  231. int m_nSegments;
  232. };
  233. IPositionInterpolator* GetRopeInterpolator()
  234. {
  235. return new CPositionInterpolator_Rope;
  236. }
  237. CPositionInterpolator_Rope::CPositionInterpolator_Rope()
  238. {
  239. m_flSlack = 0;
  240. m_bChange = false;
  241. m_nSegments = 5;
  242. for( int i=0; i < 2; i++ )
  243. m_Delegate.m_CurEndPoints[i] = Vector( 1e24, 1e24, 1e24 );
  244. }
  245. void CPositionInterpolator_Rope::Release()
  246. {
  247. delete this;
  248. }
  249. void CPositionInterpolator_Rope::GetDetails( char **outName, int *outMinKeyReq, int *outMaxKeyReq )
  250. {
  251. *outName = "Rope";
  252. *outMinKeyReq = 0;
  253. *outMinKeyReq = 1;
  254. }
  255. void CPositionInterpolator_Rope::SetKeyPosition( int keyNum, Vector const &vPos )
  256. {
  257. if( keyNum == 0 || keyNum == 1 )
  258. {
  259. if( vPos != m_Delegate.m_CurEndPoints[keyNum] )
  260. m_bChange = true;
  261. m_Delegate.m_CurEndPoints[keyNum] = vPos;
  262. }
  263. }
  264. void CPositionInterpolator_Rope::InterpolatePosition( float time, Vector &vOut )
  265. {
  266. // Check if we need to resimulate..
  267. if( m_bChange )
  268. {
  269. m_RopePhysics.SetNumNodes( m_nSegments );
  270. // Init all the nodes.
  271. for( int i=0; i < m_RopePhysics.NumNodes(); i++ )
  272. m_RopePhysics.GetNode(i)->m_vPos = m_RopePhysics.GetNode(i)->m_vPrevPos = m_Delegate.m_CurEndPoints[0];
  273. float flDist = (m_Delegate.m_CurEndPoints[0] - m_Delegate.m_CurEndPoints[1]).Length();
  274. flDist += m_flSlack;
  275. m_RopePhysics.Restart();
  276. m_RopePhysics.SetupSimulation( flDist / (m_RopePhysics.NumNodes() - 1), &m_Delegate );
  277. // Run the simulation for a while to let the rope settle down..
  278. m_RopePhysics.Simulate( 5 );
  279. m_bChange = false;
  280. }
  281. // Ok, now we have all the nodes setup..
  282. float flNode = time * (m_RopePhysics.NumNodes()-1);
  283. int iNode = (int)( flNode );
  284. VectorLerp(
  285. m_RopePhysics.GetNode(iNode)->m_vPredicted,
  286. m_RopePhysics.GetNode(iNode+1)->m_vPredicted,
  287. flNode - iNode,
  288. vOut );
  289. }
  290. bool CPositionInterpolator_Rope::ProcessKey( char const *pName, char const *pValue )
  291. {
  292. if( stricmp( pName, "Slack" ) == 0 )
  293. {
  294. m_flSlack = atof( pValue ) + ROPESLACK_FUDGEFACTOR;
  295. m_bChange = true;
  296. return true;
  297. }
  298. else if( stricmp( pName, "Type" ) == 0 )
  299. {
  300. int iType = atoi( pValue );
  301. if( iType == 0 )
  302. m_nSegments = ROPE_MAX_SEGMENTS;
  303. else if( iType == 1 )
  304. m_nSegments = ROPE_TYPE1_NUMSEGMENTS;
  305. else
  306. m_nSegments = ROPE_TYPE2_NUMSEGMENTS;
  307. m_bChange = true;
  308. return true;
  309. }
  310. return false;
  311. }
  312. // ------------------------------------------------------------------------------------ //
  313. // The global table of all the position interpolators.
  314. // ------------------------------------------------------------------------------------ //
  315. typedef IPositionInterpolator* (*PositionInterpolatorCreateFn)();
  316. PositionInterpolatorCreateFn g_PositionInterpolatorCreateFns[] =
  317. {
  318. GetLinearInterpolator,
  319. GetCatmullRomInterpolator,
  320. GetRopeInterpolator
  321. };
  322. int Motion_GetNumberOfPositionInterpolators( void )
  323. {
  324. return ARRAYSIZE(g_PositionInterpolatorCreateFns);
  325. }
  326. IPositionInterpolator* Motion_GetPositionInterpolator( int interpNum )
  327. {
  328. Assert( interpNum >= 0 && interpNum < Motion_GetNumberOfPositionInterpolators() );
  329. return g_PositionInterpolatorCreateFns[clamp( interpNum, 0, Motion_GetNumberOfPositionInterpolators() - 1 )]();
  330. }
  331. //-----------------------------------------------------------------------------
  332. //-----------------------------------------------------------------------------
  333. //-----------------------------------------------------------------------------
  334. // Rotation interpolator function enumeration & implementation
  335. //-----------------------------------------------------------------------------
  336. //-----------------------------------------------------------------------------
  337. //-----------------------------------------------------------------------------
  338. typedef void (*RotationInterpolatorFunc_t)(float time, Quaternion &outRot);
  339. typedef struct
  340. {
  341. char *szName;
  342. RotationInterpolatorFunc_t pFunc;
  343. // defines the range of keys this interpolator needs to function
  344. int iMinReqKeyFrame;
  345. int iMaxReqKeyFrame;
  346. } RotationInterpolator_t;
  347. void RotationInterpolatorFunc_Linear( float time, Quaternion &outRot )
  348. {
  349. // basic 4D spherical linear interpolation
  350. QuaternionSlerp( g_KeyFramePtr[0].qRot, g_KeyFramePtr[1].qRot, time, outRot );
  351. }
  352. RotationInterpolator_t g_RotationInterpolators[] =
  353. {
  354. { "Linear", RotationInterpolatorFunc_Linear, 0, 1 },
  355. };
  356. int Motion_GetNumberOfRotationInterpolators( void )
  357. {
  358. return ARRAYSIZE(g_RotationInterpolators);
  359. }
  360. bool Motion_GetRotationInterpolatorDetails( int rotInterpNum, char **outName, int *outMinKeyReq, int *outMaxKeyReq )
  361. {
  362. if ( rotInterpNum < 0 || rotInterpNum >= Motion_GetNumberOfRotationInterpolators() )
  363. {
  364. return false;
  365. }
  366. if ( !g_RotationInterpolators[rotInterpNum].szName || !g_RotationInterpolators[rotInterpNum].pFunc )
  367. {
  368. return false;
  369. }
  370. if ( outName )
  371. *outName = g_RotationInterpolators[rotInterpNum].szName;
  372. if ( outMinKeyReq )
  373. *outMinKeyReq = g_RotationInterpolators[rotInterpNum].iMinReqKeyFrame;
  374. if ( outMaxKeyReq )
  375. *outMaxKeyReq = g_RotationInterpolators[rotInterpNum].iMaxReqKeyFrame;
  376. return true;
  377. }
  378. //-----------------------------------------------------------------------------
  379. // Purpose: Interpolates a rotation
  380. // Time is assumed to have already been modified by the TimeModifyFunc (above)
  381. // Requires the keyframes be already set
  382. // Input : time - value from 0..1
  383. // interpFuncNum -
  384. // *outQuatRotation - result in quaternion form
  385. // Output : Returns true on success, false on failure.
  386. //-----------------------------------------------------------------------------
  387. bool Motion_InterpolateRotation( float time, int interpFuncNum, Quaternion &outQuatRotation )
  388. {
  389. if ( time < 0.0f || time > 1.0f )
  390. return false;
  391. g_RotationInterpolators[interpFuncNum].pFunc( time, outQuatRotation );
  392. return true;
  393. }