Counter Strike : Global Offensive Source Code
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.

500 lines
14 KiB

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