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.

1681 lines
44 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include "tier0/dbg.h"
  9. #include "mathlib/mathlib.h"
  10. #include "bone_setup.h"
  11. #include <string.h>
  12. #include "collisionutils.h"
  13. #include "vstdlib/random.h"
  14. #include "tier0/vprof.h"
  15. #include "bone_accessor.h"
  16. #include "mathlib/ssequaternion.h"
  17. #include "bitvec.h"
  18. #include "datamanager.h"
  19. #include "convar.h"
  20. #include "tier0/tslist.h"
  21. #include "vphysics_interface.h"
  22. #include "datacache/idatacache.h"
  23. #include "tier0/miniprofiler.h"
  24. #ifdef CLIENT_DLL
  25. #include "posedebugger.h"
  26. #endif
  27. #include "bone_utils.h"
  28. // memdbgon must be the last include file in a .cpp file!!!
  29. #include "tier0/memdbgon.h"
  30. //-----------------------------------------------------------------------------
  31. // Purpose: return a sub frame rotation for a single bone
  32. //-----------------------------------------------------------------------------
  33. void ExtractAnimValue( int frame, mstudioanimvalue_t *panimvalue, float scale, float &v1, float &v2 )
  34. {
  35. BONE_PROFILE_FUNC();
  36. if ( !panimvalue )
  37. {
  38. v1 = v2 = 0;
  39. return;
  40. }
  41. // Avoids a crash reading off the end of the data
  42. // There is probably a better long-term solution; Ken is going to look into it.
  43. if ( ( panimvalue->num.total == 1 ) && ( panimvalue->num.valid == 1 ) )
  44. {
  45. v1 = v2 = panimvalue[1].value * scale;
  46. return;
  47. }
  48. int k = frame;
  49. // find the data list that has the frame
  50. while (panimvalue->num.total <= k)
  51. {
  52. k -= panimvalue->num.total;
  53. panimvalue += panimvalue->num.valid + 1;
  54. if ( panimvalue->num.total == 0 )
  55. {
  56. Assert( 0 ); // running off the end of the animation stream is bad
  57. v1 = v2 = 0;
  58. return;
  59. }
  60. }
  61. if (panimvalue->num.valid > k)
  62. {
  63. // has valid animation data
  64. v1 = panimvalue[k+1].value * scale;
  65. if (panimvalue->num.valid > k + 1)
  66. {
  67. // has valid animation blend data
  68. v2 = panimvalue[k+2].value * scale;
  69. }
  70. else
  71. {
  72. if (panimvalue->num.total > k + 1)
  73. {
  74. // data repeats, no blend
  75. v2 = v1;
  76. }
  77. else
  78. {
  79. // pull blend from first data block in next list
  80. v2 = panimvalue[panimvalue->num.valid+2].value * scale;
  81. }
  82. }
  83. }
  84. else
  85. {
  86. // get last valid data block
  87. v1 = panimvalue[panimvalue->num.valid].value * scale;
  88. if (panimvalue->num.total > k + 1)
  89. {
  90. // data repeats, no blend
  91. v2 = v1;
  92. }
  93. else
  94. {
  95. // pull blend from first data block in next list
  96. v2 = panimvalue[panimvalue->num.valid + 2].value * scale;
  97. }
  98. }
  99. }
  100. void ExtractAnimValue( int frame, mstudioanimvalue_t *panimvalue, float scale, float &v1 )
  101. {
  102. BONE_PROFILE_FUNC();
  103. if ( !panimvalue )
  104. {
  105. v1 = 0;
  106. return;
  107. }
  108. int k = frame;
  109. while (panimvalue->num.total <= k)
  110. {
  111. k -= panimvalue->num.total;
  112. panimvalue += panimvalue->num.valid + 1;
  113. if ( panimvalue->num.total == 0 )
  114. {
  115. Assert( 0 ); // running off the end of the animation stream is bad
  116. v1 = 0;
  117. return;
  118. }
  119. }
  120. if (panimvalue->num.valid > k)
  121. {
  122. v1 = panimvalue[k+1].value * scale;
  123. }
  124. else
  125. {
  126. // get last valid data block
  127. v1 = panimvalue[panimvalue->num.valid].value * scale;
  128. }
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose: return a sub frame rotation for a single bone
  132. //-----------------------------------------------------------------------------
  133. void CalcBoneQuaternion( int frame, float s,
  134. const Quaternion &baseQuat, const RadianEuler &baseRot, const Vector &baseRotScale,
  135. int iBaseFlags, const Quaternion &baseAlignment,
  136. const mstudio_rle_anim_t *panim, Quaternion &q )
  137. {
  138. BONE_PROFILE_FUNC();
  139. if ( panim->flags & STUDIO_ANIM_RAWROT )
  140. {
  141. q = *(panim->pQuat48());
  142. Assert( q.IsValid() );
  143. return;
  144. }
  145. if ( panim->flags & STUDIO_ANIM_RAWROT2 )
  146. {
  147. q = *(panim->pQuat64());
  148. Assert( q.IsValid() );
  149. return;
  150. }
  151. if ( !(panim->flags & STUDIO_ANIM_ANIMROT) )
  152. {
  153. if (panim->flags & STUDIO_ANIM_DELTA)
  154. {
  155. q.Init( 0.0f, 0.0f, 0.0f, 1.0f );
  156. }
  157. else
  158. {
  159. q = baseQuat;
  160. }
  161. return;
  162. }
  163. mstudioanim_valueptr_t *pValuesPtr = panim->pRotV();
  164. if (s > 0.001f)
  165. {
  166. QuaternionAligned q1, q2;
  167. RadianEuler angle1, angle2;
  168. ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 0 ), baseRotScale.x, angle1.x, angle2.x );
  169. ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 1 ), baseRotScale.y, angle1.y, angle2.y );
  170. ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 2 ), baseRotScale.z, angle1.z, angle2.z );
  171. if (!(panim->flags & STUDIO_ANIM_DELTA))
  172. {
  173. angle1.x = angle1.x + baseRot.x;
  174. angle1.y = angle1.y + baseRot.y;
  175. angle1.z = angle1.z + baseRot.z;
  176. angle2.x = angle2.x + baseRot.x;
  177. angle2.y = angle2.y + baseRot.y;
  178. angle2.z = angle2.z + baseRot.z;
  179. }
  180. Assert( angle1.IsValid() && angle2.IsValid() );
  181. if (angle1.x != angle2.x || angle1.y != angle2.y || angle1.z != angle2.z)
  182. {
  183. AngleQuaternion( angle1, q1 );
  184. AngleQuaternion( angle2, q2 );
  185. #ifdef _X360
  186. fltx4 q1simd, q2simd, qsimd;
  187. q1simd = LoadAlignedSIMD( q1 );
  188. q2simd = LoadAlignedSIMD( q2 );
  189. qsimd = QuaternionBlendSIMD( q1simd, q2simd, s );
  190. StoreUnalignedSIMD( q.Base(), qsimd );
  191. #else
  192. QuaternionBlend( q1, q2, s, q );
  193. #endif
  194. }
  195. else
  196. {
  197. AngleQuaternion( angle1, q );
  198. }
  199. }
  200. else
  201. {
  202. RadianEuler angle;
  203. ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 0 ), baseRotScale.x, angle.x );
  204. ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 1 ), baseRotScale.y, angle.y );
  205. ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 2 ), baseRotScale.z, angle.z );
  206. if (!(panim->flags & STUDIO_ANIM_DELTA))
  207. {
  208. angle.x = angle.x + baseRot.x;
  209. angle.y = angle.y + baseRot.y;
  210. angle.z = angle.z + baseRot.z;
  211. }
  212. Assert( angle.IsValid() );
  213. AngleQuaternion( angle, q );
  214. }
  215. Assert( q.IsValid() );
  216. // align to unified bone
  217. if (!(panim->flags & STUDIO_ANIM_DELTA) && (iBaseFlags & BONE_FIXED_ALIGNMENT))
  218. {
  219. QuaternionAlign( baseAlignment, q, q );
  220. }
  221. }
  222. inline void CalcBoneQuaternion( int frame, float s,
  223. const mstudiobone_t *pBone,
  224. const mstudiolinearbone_t *pLinearBones,
  225. const mstudio_rle_anim_t *panim, Quaternion &q )
  226. {
  227. if (pLinearBones)
  228. {
  229. CalcBoneQuaternion( frame, s, pLinearBones->quat(panim->bone), pLinearBones->rot(panim->bone), pLinearBones->rotscale(panim->bone), pLinearBones->flags(panim->bone), pLinearBones->qalignment(panim->bone), panim, q );
  230. }
  231. else
  232. {
  233. CalcBoneQuaternion( frame, s, pBone->quat, pBone->rot, pBone->rotscale, pBone->flags, pBone->qAlignment, panim, q );
  234. }
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Purpose: return a sub frame position for a single bone
  238. //-----------------------------------------------------------------------------
  239. void CalcBonePosition( int frame, float s,
  240. const Vector &basePos, const Vector &baseBoneScale,
  241. const mstudio_rle_anim_t *panim, BoneVector &pos )
  242. {
  243. BONE_PROFILE_FUNC();
  244. if (panim->flags & STUDIO_ANIM_RAWPOS)
  245. {
  246. pos = *(panim->pPos());
  247. Assert( pos.IsValid() );
  248. return;
  249. }
  250. else if (!(panim->flags & STUDIO_ANIM_ANIMPOS))
  251. {
  252. if (panim->flags & STUDIO_ANIM_DELTA)
  253. {
  254. pos.Init( 0.0f, 0.0f, 0.0f );
  255. }
  256. else
  257. {
  258. pos = basePos;
  259. }
  260. return;
  261. }
  262. mstudioanim_valueptr_t *pPosV = panim->pPosV();
  263. int j;
  264. if (s > 0.001f)
  265. {
  266. float v1, v2;
  267. for (j = 0; j < 3; j++)
  268. {
  269. ExtractAnimValue( frame, pPosV->pAnimvalue( j ), baseBoneScale[j], v1, v2 );
  270. pos[j] = v1 * (1.0 - s) + v2 * s;
  271. }
  272. }
  273. else
  274. {
  275. for (j = 0; j < 3; j++)
  276. {
  277. ExtractAnimValue( frame, pPosV->pAnimvalue( j ), baseBoneScale[j], pos[j] );
  278. }
  279. }
  280. if (!(panim->flags & STUDIO_ANIM_DELTA))
  281. {
  282. pos.x = pos.x + basePos.x;
  283. pos.y = pos.y + basePos.y;
  284. pos.z = pos.z + basePos.z;
  285. }
  286. Assert( pos.IsValid() );
  287. }
  288. inline void CalcBonePosition( int frame, float s,
  289. const mstudiobone_t *pBone,
  290. const mstudiolinearbone_t *pLinearBones,
  291. const mstudio_rle_anim_t *panim, BoneVector &pos )
  292. {
  293. if (pLinearBones)
  294. {
  295. CalcBonePosition( frame, s, pLinearBones->pos(panim->bone), pLinearBones->posscale(panim->bone), panim, pos );
  296. }
  297. else
  298. {
  299. CalcBonePosition( frame, s, pBone->pos, pBone->posscale, panim, pos );
  300. }
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose:
  304. //-----------------------------------------------------------------------------
  305. void CalcDecompressedAnimation( const mstudiocompressedikerror_t *pCompressed, int iFrame, float fraq, BoneVector &pos, BoneQuaternion &q )
  306. {
  307. BONE_PROFILE_FUNC();
  308. if (fraq > 0.0001f)
  309. {
  310. Vector p1, p2;
  311. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 0 ), pCompressed->scale[0], p1.x, p2.x );
  312. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 1 ), pCompressed->scale[1], p1.y, p2.y );
  313. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 2 ), pCompressed->scale[2], p1.z, p2.z );
  314. pos = p1 * (1 - fraq) + p2 * fraq;
  315. Quaternion q1, q2;
  316. RadianEuler angle1, angle2;
  317. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 3 ), pCompressed->scale[3], angle1.x, angle2.x );
  318. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 4 ), pCompressed->scale[4], angle1.y, angle2.y );
  319. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 5 ), pCompressed->scale[5], angle1.z, angle2.z );
  320. if (angle1.x != angle2.x || angle1.y != angle2.y || angle1.z != angle2.z)
  321. {
  322. AngleQuaternion( angle1, q1 );
  323. AngleQuaternion( angle2, q2 );
  324. QuaternionBlend( q1, q2, fraq, q );
  325. }
  326. else
  327. {
  328. AngleQuaternion( angle1, q );
  329. }
  330. }
  331. else
  332. {
  333. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 0 ), pCompressed->scale[0], pos.x );
  334. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 1 ), pCompressed->scale[1], pos.y );
  335. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 2 ), pCompressed->scale[2], pos.z );
  336. RadianEuler angle;
  337. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 3 ), pCompressed->scale[3], angle.x );
  338. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 4 ), pCompressed->scale[4], angle.y );
  339. ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 5 ), pCompressed->scale[5], angle.z );
  340. AngleQuaternion( angle, q );
  341. }
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Purpose: translate animations done in a non-standard parent space
  345. //-----------------------------------------------------------------------------
  346. static void CalcLocalHierarchyAnimation(
  347. const CStudioHdr *pStudioHdr,
  348. matrix3x4a_t *boneToWorld,
  349. CBoneBitList &boneComputed,
  350. BoneVector *pos,
  351. BoneQuaternion *q,
  352. //const mstudioanimdesc_t &animdesc,
  353. const mstudiobone_t *pbone,
  354. mstudiolocalhierarchy_t *pHierarchy,
  355. int iBone,
  356. int iNewParent,
  357. float cycle,
  358. int iFrame,
  359. float flFraq,
  360. int boneMask
  361. )
  362. {
  363. BONE_PROFILE_FUNC();
  364. BoneVector localPos;
  365. BoneQuaternion localQ;
  366. // make fake root transform
  367. static matrix3x4a_t rootXform;
  368. SetIdentityMatrix( rootXform );
  369. // FIXME: missing check to see if seq has a weight for this bone
  370. float weight = 1.0f;
  371. // check to see if there's a ramp on the influence
  372. if ( pHierarchy->tail - pHierarchy->peak < 1.0f )
  373. {
  374. float index = cycle;
  375. if (pHierarchy->end > 1.0f && index < pHierarchy->start)
  376. index += 1.0f;
  377. if (index < pHierarchy->start)
  378. return;
  379. if (index >= pHierarchy->end)
  380. return;
  381. if (index < pHierarchy->peak && pHierarchy->start != pHierarchy->peak)
  382. {
  383. weight = (index - pHierarchy->start) / (pHierarchy->peak - pHierarchy->start);
  384. }
  385. else if (index > pHierarchy->tail && pHierarchy->end != pHierarchy->tail)
  386. {
  387. weight = (pHierarchy->end - index) / (pHierarchy->end - pHierarchy->tail);
  388. }
  389. weight = SimpleSpline( weight );
  390. }
  391. CalcDecompressedAnimation( pHierarchy->pLocalAnim(), iFrame - pHierarchy->iStart, flFraq, localPos, localQ );
  392. // find first common root bone
  393. int iRoot1 = iBone;
  394. int iRoot2 = iNewParent;
  395. while (iRoot1 != iRoot2 && iRoot1 != -1)
  396. {
  397. if (iRoot1 > iRoot2)
  398. iRoot1 = pStudioHdr->boneParent( iRoot1 );
  399. else
  400. iRoot2 = pStudioHdr->boneParent( iRoot2 );
  401. }
  402. // BUGBUG: pos and q only valid if local weight
  403. BuildBoneChainPartial( pStudioHdr, rootXform, pos, q, iBone, boneToWorld, boneComputed, iRoot1 );
  404. BuildBoneChainPartial( pStudioHdr, rootXform, pos, q, iNewParent, boneToWorld, boneComputed, iRoot1 );
  405. matrix3x4a_t localXform;
  406. AngleMatrix( RadianEuler(localQ), localPos, localXform );
  407. ConcatTransforms_Aligned( boneToWorld[iNewParent], localXform, boneToWorld[iBone] );
  408. // back solve
  409. BoneVector p1;
  410. BoneQuaternion q1;
  411. int n = pbone[iBone].parent;
  412. if (n == -1)
  413. {
  414. if (weight == 1.0f)
  415. {
  416. MatrixAngles( boneToWorld[iBone], q[iBone], pos[iBone] );
  417. }
  418. else
  419. {
  420. MatrixAngles( boneToWorld[iBone], q1, p1 );
  421. QuaternionSlerp( q[iBone], q1, weight, q[iBone] );
  422. //pos[iBone] = Lerp( weight, p1, pos[iBone] );
  423. pos[iBone] = p1 + (pos[iBone] - p1) * weight;
  424. }
  425. }
  426. else
  427. {
  428. matrix3x4a_t worldToBone;
  429. MatrixInvert( boneToWorld[n], worldToBone );
  430. matrix3x4a_t local;
  431. ConcatTransforms_Aligned( worldToBone, boneToWorld[iBone], local );
  432. if (weight == 1.0f)
  433. {
  434. MatrixAngles( local, q[iBone], pos[iBone] );
  435. }
  436. else
  437. {
  438. MatrixAngles( local, q1, p1 );
  439. QuaternionSlerp( q[iBone], q1, weight, q[iBone] );
  440. //pos[iBone] = Lerp( weight, p1, pos[iBone] );
  441. pos[iBone] = p1 + (pos[iBone] - p1) * weight;
  442. }
  443. }
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Purpose: Calc Zeroframe Data
  447. //-----------------------------------------------------------------------------
  448. static void CalcZeroframeData( const CStudioHdr *pStudioHdr, const studiohdr_t *pAnimStudioHdr, const virtualgroup_t *pAnimGroup, const mstudiobone_t *pAnimbone, mstudioanimdesc_t &animdesc, float fFrame, BoneVector *pos, BoneQuaternion *q, int boneMask, float flWeight )
  449. {
  450. BONE_PROFILE_FUNC();
  451. byte *pData = animdesc.pZeroFrameData();
  452. if (!pData)
  453. return;
  454. int i, j;
  455. // Msg("zeroframe %s\n", animdesc.pszName() );
  456. if (animdesc.zeroframecount == 1)
  457. {
  458. for (j = 0; j < pAnimStudioHdr->numbones; j++)
  459. {
  460. if (pAnimGroup)
  461. i = pAnimGroup->masterBone[j];
  462. else
  463. i = j;
  464. if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_POS)
  465. {
  466. if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask))
  467. {
  468. Vector p = *(Vector48 *)pData;
  469. pos[i] = pos[i] * (1.0f - flWeight) + p * flWeight;
  470. Assert( pos[i].IsValid() );
  471. }
  472. pData += sizeof( Vector48 );
  473. }
  474. if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_ROT64)
  475. {
  476. if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask))
  477. {
  478. Quaternion q0 = *(Quaternion64 *)pData;
  479. QuaternionBlend( q[i], q0, flWeight, q[i] );
  480. Assert( q[i].IsValid() );
  481. }
  482. pData += sizeof( Quaternion64 );
  483. }
  484. else if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_ROT32)
  485. {
  486. if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask))
  487. {
  488. Quaternion q0 = *(Quaternion32 *)pData;
  489. QuaternionBlend( q[i], q0, flWeight, q[i] );
  490. Assert( q[i].IsValid() );
  491. }
  492. pData += sizeof( Quaternion32 );
  493. }
  494. }
  495. }
  496. else
  497. {
  498. float s1;
  499. int index = fFrame / animdesc.zeroframespan;
  500. if (index >= animdesc.zeroframecount - 1)
  501. {
  502. index = animdesc.zeroframecount - 2;
  503. s1 = 1.0f;
  504. }
  505. else
  506. {
  507. s1 = clamp( (fFrame - index * animdesc.zeroframespan) / animdesc.zeroframespan, 0.0f, 1.0f );
  508. }
  509. int i0 = MAX( index - 1, 0 );
  510. int i1 = index;
  511. int i2 = MIN( index + 1, animdesc.zeroframecount - 1 );
  512. for (j = 0; j < pAnimStudioHdr->numbones; j++)
  513. {
  514. if (pAnimGroup)
  515. i = pAnimGroup->masterBone[j];
  516. else
  517. i = j;
  518. if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_POS)
  519. {
  520. if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask))
  521. {
  522. Vector p0 = *(((Vector48 *)pData) + i0);
  523. Vector p1 = *(((Vector48 *)pData) + i1);
  524. Vector p2 = *(((Vector48 *)pData) + i2);
  525. if (flWeight == 1.0f)
  526. {
  527. // don't blend into an uninitialized value
  528. Hermite_Spline( p0, p1, p2, s1, pos[i] );
  529. }
  530. else
  531. {
  532. Vector p3;
  533. Hermite_Spline( p0, p1, p2, s1, p3 );
  534. pos[i] = pos[i] * (1.0f - flWeight) + p3 * flWeight;
  535. }
  536. Assert( pos[i].IsValid() );
  537. }
  538. pData += sizeof( Vector48 ) * animdesc.zeroframecount;
  539. }
  540. if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_ROT64)
  541. {
  542. if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask))
  543. {
  544. Quaternion q0 = *(((Quaternion64 *)pData) + i0);
  545. Quaternion q1 = *(((Quaternion64 *)pData) + i1);
  546. Quaternion q2 = *(((Quaternion64 *)pData) + i2);
  547. if (flWeight == 1.0f)
  548. {
  549. // don't blend into an uninitialized value
  550. Hermite_Spline( q0, q1, q2, s1, q[i] );
  551. }
  552. else
  553. {
  554. Quaternion q3;
  555. Hermite_Spline( q0, q1, q2, s1, q3 );
  556. QuaternionBlend( q[i], q3, flWeight, q[i] );
  557. }
  558. Assert( q[i].IsValid() );
  559. }
  560. pData += sizeof( Quaternion64 ) * animdesc.zeroframecount;
  561. }
  562. else if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_ROT32)
  563. {
  564. if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask))
  565. {
  566. Quaternion q0 = *(((Quaternion32 *)pData) + i0);
  567. Quaternion q1 = *(((Quaternion32 *)pData) + i1);
  568. Quaternion q2 = *(((Quaternion32 *)pData) + i2);
  569. if (flWeight == 1.0f)
  570. {
  571. // don't blend into an uninitialized value
  572. Hermite_Spline( q0, q1, q2, s1, q[i] );
  573. }
  574. else
  575. {
  576. Quaternion q3;
  577. Hermite_Spline( q0, q1, q2, s1, q3 );
  578. QuaternionBlend( q[i], q3, flWeight, q[i] );
  579. }
  580. Assert( q[i].IsValid() );
  581. }
  582. pData += sizeof( Quaternion32 ) * animdesc.zeroframecount;
  583. }
  584. }
  585. }
  586. }
  587. //-----------------------------------------------------------------------------
  588. // Purpose: Extract and blend two frames from a mstudio_frame_anim_t block of data
  589. //-----------------------------------------------------------------------------
  590. inline byte *ExtractTwoFrames( byte flags, float s, byte *RESTRICT pFrameData, byte *&pConstantData, int framelength, BoneQuaternion &q, BoneVector &pos, bool bIsDelta = false, const mstudiolinearbone_t *pLinearBones = NULL, int bone = 0 )
  591. {
  592. BONE_PROFILE_FUNC();
  593. #ifdef _GAMECONSOLE
  594. if (flags & STUDIO_FRAME_ANIM_ROT)
  595. {
  596. fltx4 q1 = UnpackQuaternion48SIMD( (Quaternion48 *)(pFrameData) );
  597. fltx4 q2 = UnpackQuaternion48SIMD( (Quaternion48 *)(pFrameData + framelength) );
  598. fltx4 qBlend = QuaternionBlendSIMD( q1, q2, s );
  599. StoreAlignedSIMD( (QuaternionAligned*)&q, qBlend );
  600. pFrameData += sizeof( Quaternion48 );
  601. }
  602. else if (flags & STUDIO_FRAME_ANIM_ROT2)
  603. {
  604. if ( false ) // slow/naive
  605. {
  606. Quaternion q1;
  607. Quaternion q2;
  608. q1 = *((Quaternion48S *)(pFrameData));
  609. q2 = *((Quaternion48S *)(pFrameData + framelength));
  610. QuaternionBlend( q1, q2, s, q );
  611. Assert( q.IsValid() );
  612. pFrameData += sizeof( Quaternion48S );
  613. }
  614. else // simd
  615. {
  616. fltx4 q1;
  617. fltx4 q2;
  618. q1 = *((Quaternion48S *)(pFrameData));
  619. q2 = *((Quaternion48S *)(pFrameData + framelength));
  620. StoreUnalignedSIMD( q.Base(), QuaternionBlendSIMD( q1, q2, s ) );
  621. Assert( q.IsValid() );
  622. pFrameData += sizeof( Quaternion48S );
  623. }
  624. }
  625. else if (flags & STUDIO_FRAME_CONST_ROT)
  626. {
  627. fltx4 flt = UnpackQuaternion48SIMD( (Quaternion48 *)(pConstantData) );
  628. StoreAlignedSIMD( (QuaternionAligned*)&q, flt );
  629. pConstantData += sizeof( Quaternion48 );
  630. }
  631. else if (flags & STUDIO_FRAME_CONST_ROT2)
  632. {
  633. if ( false ) // slow/naive
  634. {
  635. q = *((Quaternion48S *)(pConstantData));
  636. Assert( q.IsValid() );
  637. pConstantData += sizeof( Quaternion48S );
  638. }
  639. else
  640. {
  641. // q = *((Quaternion48S *)(pConstantData));
  642. StoreUnalignedSIMD( q.Base(), (fltx4) *((Quaternion48S *)(pConstantData)) );
  643. Assert( q.IsValid() );
  644. pConstantData += sizeof( Quaternion48S );
  645. }
  646. }
  647. // the non-virtual version needs initializers for no-animation
  648. else if (pLinearBones)
  649. {
  650. if (bIsDelta)
  651. {
  652. q.Init( 0.0f, 0.0f, 0.0f, 1.0f );
  653. }
  654. else
  655. {
  656. q = pLinearBones->quat( bone );
  657. }
  658. }
  659. if (flags & STUDIO_FRAME_ANIM_POS)
  660. {
  661. fltx4 p1 = UnpackVector48SIMD( (Vector48 *)(pFrameData) );
  662. fltx4 p2 = UnpackVector48SIMD( (Vector48 *)(pFrameData + framelength) );
  663. fltx4 f2 = ReplicateX4( s );
  664. fltx4 f1 = SubSIMD( Four_Ones, f2 );
  665. p2 = MulSIMD( p2, f2 );
  666. p1 = MaddSIMD( p1, f1, p2 );
  667. StoreUnaligned3SIMD( pos.Base(), p1 );
  668. pFrameData += sizeof( Vector48 );
  669. }
  670. else if (flags & STUDIO_FRAME_CONST_POS)
  671. {
  672. fltx4 flt = UnpackVector48SIMD( (Vector48 *)(pConstantData) );
  673. StoreUnaligned3SIMD( pos.Base(), flt );
  674. pConstantData += sizeof( Vector48 );
  675. }
  676. else if (flags & STUDIO_FRAME_ANIM_POS2)
  677. {
  678. fltx4 p1 = LoadUnaligned3SIMD( (float *)(pFrameData) );
  679. fltx4 p2 = LoadUnaligned3SIMD( (float *)(pFrameData + framelength) );
  680. fltx4 f2 = ReplicateX4( s );
  681. fltx4 f1 = SubSIMD( Four_Ones, f2 );
  682. p2 = MulSIMD( p2, f2 );
  683. p1 = MaddSIMD( p1, f1, p2 );
  684. StoreUnaligned3SIMD( pos.Base(), p1 );
  685. pFrameData += sizeof( Vector );
  686. }
  687. else if (flags & STUDIO_FRAME_CONST_POS2)
  688. {
  689. fltx4 flt = LoadUnaligned3SIMD( (float *)(pConstantData) );
  690. StoreUnaligned3SIMD( pos.Base(), flt );
  691. pConstantData += sizeof( Vector );
  692. }
  693. // the non-virtual version needs initializers for no-animation
  694. else if (pLinearBones)
  695. {
  696. if (bIsDelta)
  697. {
  698. pos.Init( 0.0f, 0.0f, 0.0f );
  699. }
  700. else
  701. {
  702. pos = pLinearBones->pos( bone );
  703. }
  704. }
  705. #else
  706. Quaternion q1, q2;
  707. // Making these aligned. Could be VectorAligned instead, but I don't want to change the behavior of this code.
  708. ALIGN16 Vector p1;
  709. ALIGN16 Vector p2;
  710. if (flags & STUDIO_FRAME_ANIM_ROT)
  711. {
  712. q1 = *((Quaternion48 *)(pFrameData));
  713. q2 = *((Quaternion48 *)(pFrameData + framelength));
  714. QuaternionBlend( q1, q2, s, q );
  715. Assert( q.IsValid() );
  716. pFrameData += sizeof( Quaternion48 );
  717. }
  718. else if (flags & STUDIO_FRAME_ANIM_ROT2)
  719. {
  720. q1 = *((Quaternion48S *)(pFrameData));
  721. q2 = *((Quaternion48S *)(pFrameData + framelength));
  722. QuaternionBlend( q1, q2, s, q );
  723. Assert( q.IsValid() );
  724. pFrameData += sizeof( Quaternion48S );
  725. }
  726. else if (flags & STUDIO_FRAME_CONST_ROT)
  727. {
  728. q = *((Quaternion48 *)(pConstantData));
  729. Assert( q.IsValid() );
  730. pConstantData += sizeof( Quaternion48 );
  731. }
  732. else if (flags & STUDIO_FRAME_CONST_ROT2)
  733. {
  734. q = *((Quaternion48S *)(pConstantData));
  735. Assert( q.IsValid() );
  736. pConstantData += sizeof( Quaternion48S );
  737. }
  738. // the non-virtual version needs initializers for no-animation
  739. else if (pLinearBones)
  740. {
  741. if (bIsDelta)
  742. {
  743. q.Init( 0.0f, 0.0f, 0.0f, 1.0f );
  744. }
  745. else
  746. {
  747. q = pLinearBones->quat( bone );
  748. }
  749. }
  750. if (flags & STUDIO_FRAME_ANIM_POS)
  751. {
  752. p1 = *((Vector48 *)(pFrameData));
  753. p2 = *((Vector48 *)(pFrameData + framelength));
  754. pos = p1 * (1.0 - s) + p2 * s;
  755. Assert( pos.IsValid() );
  756. pFrameData += sizeof( Vector48 );
  757. }
  758. else if (flags & STUDIO_FRAME_CONST_POS)
  759. {
  760. pos = *((Vector48 *)(pConstantData));
  761. Assert( pos.IsValid() );
  762. pConstantData += sizeof( Vector48 );
  763. }
  764. else if (flags & STUDIO_FRAME_ANIM_POS2)
  765. {
  766. // pFrameData has no alignment guarantees, so using V_memcpy.
  767. V_memcpy( &p1, pFrameData, sizeof( p1 ) );
  768. V_memcpy( &p2, pFrameData + framelength, sizeof( p2 ) );
  769. pos = p1 * (1.0 - s) + p2 * s;
  770. Assert( pos.IsValid() );
  771. pFrameData += sizeof( Vector );
  772. }
  773. else if (flags & STUDIO_FRAME_CONST_POS2)
  774. {
  775. // pFrameData has no alignment guarantees, so using V_memcpy.
  776. V_memcpy( &pos, pConstantData, sizeof( pos ) );
  777. Assert( pos.IsValid() );
  778. pConstantData += sizeof( Vector );
  779. }
  780. // the non-virtual version needs initializers for no-animation
  781. else if (pLinearBones)
  782. {
  783. if (bIsDelta)
  784. {
  785. pos.Init( 0.0f, 0.0f, 0.0f );
  786. }
  787. else
  788. {
  789. pos = pLinearBones->pos( bone );
  790. }
  791. }
  792. #endif
  793. return pFrameData;
  794. }
  795. //-----------------------------------------------------------------------------
  796. // Purpose: Extract one frame from a mstudio_frame_anim_t block of data
  797. //-----------------------------------------------------------------------------
  798. inline byte *ExtractSingleFrame( byte flags, byte *pFrameData, byte *&pConstantData, BoneQuaternion &q, BoneVector &pos, bool bIsDelta = false, const mstudiolinearbone_t *pLinearBones = NULL, int bone = 0 )
  799. {
  800. BONE_PROFILE_FUNC();
  801. #ifdef _GAMECONSOLE
  802. if (flags & STUDIO_FRAME_ANIM_ROT)
  803. {
  804. fltx4 flt = UnpackQuaternion48SIMD( (Quaternion48 *)(pFrameData) );
  805. StoreAlignedSIMD( (QuaternionAligned*)&q, flt );
  806. // FIXME: If this path needs to work on PS3, this might be the right line to replace the 360-specific code above.
  807. // StoreAlignedSIMD( ( QuaternionAligned * )&q, flt );
  808. pFrameData += sizeof( Quaternion48 );
  809. }
  810. else if (flags & STUDIO_FRAME_ANIM_ROT2)
  811. {
  812. if ( false ) // slow/naive
  813. {
  814. q = *((Quaternion48S *)(pFrameData));
  815. Assert( q.IsValid() );
  816. pFrameData += sizeof( Quaternion48S );
  817. }
  818. else
  819. {
  820. StoreUnalignedSIMD( q.Base(), (fltx4) *((Quaternion48S *)(pFrameData)) );
  821. Assert( q.IsValid() );
  822. Assert( QuaternionsAreEqual( q, (Quaternion) *((Quaternion48S *)(pFrameData)), 0.001f ) );
  823. pFrameData += sizeof( Quaternion48S );
  824. }
  825. }
  826. else if (flags & STUDIO_FRAME_CONST_ROT)
  827. {
  828. fltx4 flt = UnpackQuaternion48SIMD( (Quaternion48 *)(pConstantData) );
  829. StoreAlignedSIMD( (QuaternionAligned*)&q, flt );
  830. // FIXME: If this path needs to work on PS3, this might be the right line to replace the 360-specific code above.
  831. // StoreAlignedSIMD( ( QuaternionAligned * )&q, flt );
  832. pConstantData += sizeof( Quaternion48 );
  833. }
  834. else if (flags & STUDIO_FRAME_CONST_ROT2)
  835. {
  836. if ( false ) // slow/naive
  837. {
  838. q = *((Quaternion48S *)(pConstantData));
  839. Assert( q.IsValid() );
  840. pConstantData += sizeof( Quaternion48S );
  841. }
  842. else
  843. {
  844. StoreUnalignedSIMD( q.Base(), (fltx4) *((Quaternion48S *)(pConstantData)) );
  845. Assert( q.IsValid() );
  846. Assert( QuaternionsAreEqual( q, (Quaternion) *((Quaternion48S *)(pConstantData)), 0.001f ) );
  847. pConstantData += sizeof( Quaternion48S );
  848. }
  849. }
  850. // the non-virtual version needs initializers for no-animation
  851. else if (pLinearBones)
  852. {
  853. if (bIsDelta)
  854. {
  855. q.Init( 0.0f, 0.0f, 0.0f, 1.0f );
  856. }
  857. else
  858. {
  859. q = pLinearBones->quat( bone );
  860. }
  861. }
  862. if (flags & STUDIO_FRAME_ANIM_POS)
  863. {
  864. fltx4 flt = UnpackVector48SIMD( (Vector48 *)(pFrameData) );
  865. StoreUnaligned3SIMD( pos.Base(), flt );
  866. pFrameData += sizeof( Vector48 );
  867. }
  868. else if (flags & STUDIO_FRAME_CONST_POS)
  869. {
  870. fltx4 flt = UnpackVector48SIMD( (Vector48 *)(pConstantData) );
  871. StoreUnaligned3SIMD( pos.Base(), flt );
  872. pConstantData += sizeof( Vector48 );
  873. }
  874. else if (flags & STUDIO_FRAME_ANIM_POS2)
  875. {
  876. fltx4 flt = LoadUnaligned3SIMD( (float *)(pFrameData) );
  877. StoreUnaligned3SIMD( pos.Base(), flt );
  878. pFrameData += sizeof( Vector );
  879. }
  880. else if (flags & STUDIO_FRAME_CONST_POS2)
  881. {
  882. fltx4 flt = LoadUnaligned3SIMD( (float *)(pConstantData) );
  883. StoreUnaligned3SIMD( pos.Base(), flt );
  884. pConstantData += sizeof( Vector );
  885. }
  886. // the non-virtual version needs initializers for no-animation
  887. else if (pLinearBones)
  888. {
  889. if (bIsDelta)
  890. {
  891. pos.Init( 0.0f, 0.0f, 0.0f );
  892. }
  893. else
  894. {
  895. pos = pLinearBones->pos( bone );
  896. }
  897. }
  898. #else
  899. if (flags & STUDIO_FRAME_ANIM_ROT)
  900. {
  901. q = *((Quaternion48 *)(pFrameData));
  902. Assert( q.IsValid() );
  903. pFrameData += sizeof( Quaternion48 );
  904. }
  905. else if (flags & STUDIO_FRAME_ANIM_ROT2)
  906. {
  907. q = *((Quaternion48S *)(pFrameData));
  908. Assert( q.IsValid() );
  909. pFrameData += sizeof( Quaternion48S );
  910. }
  911. else if (flags & STUDIO_FRAME_CONST_ROT)
  912. {
  913. q = *((Quaternion48 *)(pConstantData));
  914. Assert( q.IsValid() );
  915. pConstantData += sizeof( Quaternion48 );
  916. }
  917. else if (flags & STUDIO_FRAME_CONST_ROT2)
  918. {
  919. q = *((Quaternion48S *)(pConstantData));
  920. Assert( q.IsValid() );
  921. pConstantData += sizeof( Quaternion48S );
  922. }
  923. // the non-virtual version needs initializers for no-animation
  924. else if (pLinearBones)
  925. {
  926. if (bIsDelta)
  927. {
  928. q.Init( 0.0f, 0.0f, 0.0f, 1.0f );
  929. }
  930. else
  931. {
  932. q = pLinearBones->quat( bone );
  933. }
  934. }
  935. if (flags & STUDIO_FRAME_ANIM_POS)
  936. {
  937. pos = *((Vector48 *)(pFrameData));
  938. Assert( pos.IsValid() );
  939. pFrameData += sizeof( Vector48 );
  940. }
  941. else if (flags & STUDIO_FRAME_CONST_POS)
  942. {
  943. pos = *((Vector48 *)(pConstantData));
  944. Assert( pos.IsValid() );
  945. pConstantData += sizeof( Vector48 );
  946. }
  947. else if (flags & STUDIO_FRAME_ANIM_POS2)
  948. {
  949. // pFrameData has no guarantee on alignment, so using V_memcpy.
  950. V_memcpy( &pos, pFrameData, sizeof( Vector ) );
  951. Assert( pos.IsValid() );
  952. pFrameData += sizeof( Vector );
  953. }
  954. else if (flags & STUDIO_FRAME_CONST_POS2)
  955. {
  956. // pFrameData has no guarantee on alignment, so using V_memcpy.
  957. V_memcpy( &pos, pConstantData, sizeof( Vector ) );
  958. Assert( pos.IsValid() );
  959. pConstantData += sizeof( Vector );
  960. }
  961. // the non-virtual version needs initializers for no-animation
  962. else if (pLinearBones)
  963. {
  964. if (bIsDelta)
  965. {
  966. pos.Init( 0.0f, 0.0f, 0.0f );
  967. }
  968. else
  969. {
  970. pos = pLinearBones->pos( bone );
  971. }
  972. }
  973. #endif
  974. return pFrameData;
  975. }
  976. //-----------------------------------------------------------------------------
  977. // Purpose: Skip forward to the next bone in a mstudio_frame_anim_t block of data
  978. //-----------------------------------------------------------------------------
  979. inline byte *SkipBoneFrame( byte flags, byte * RESTRICT pFrameData, byte *&pConstantData )
  980. {
  981. BONE_PROFILE_FUNC();
  982. if (flags & STUDIO_FRAME_ANIM_ROT)
  983. {
  984. pFrameData += sizeof( Quaternion48 );
  985. }
  986. else if (flags & STUDIO_FRAME_ANIM_ROT2)
  987. {
  988. pFrameData += sizeof( Quaternion48S );
  989. }
  990. else if (flags & STUDIO_FRAME_CONST_ROT)
  991. {
  992. pConstantData += sizeof( Quaternion48 );
  993. }
  994. else if (flags & STUDIO_FRAME_CONST_ROT2)
  995. {
  996. pConstantData += sizeof( Quaternion48S );
  997. }
  998. if (flags & STUDIO_FRAME_ANIM_POS)
  999. {
  1000. pFrameData += sizeof( Vector48 );
  1001. }
  1002. else if (flags & STUDIO_FRAME_CONST_POS)
  1003. {
  1004. pConstantData += sizeof( Vector48 );
  1005. }
  1006. else if (flags & STUDIO_FRAME_ANIM_POS2)
  1007. {
  1008. pFrameData += sizeof( Vector );
  1009. }
  1010. else if (flags & STUDIO_FRAME_CONST_POS2)
  1011. {
  1012. pConstantData += sizeof( Vector );
  1013. }
  1014. return pFrameData;
  1015. }
  1016. //-----------------------------------------------------------------------------
  1017. // Purpose: Extract a single bone of animation
  1018. //-----------------------------------------------------------------------------
  1019. void SetupSingleBoneMatrix(
  1020. CStudioHdr *pOwnerHdr,
  1021. int nSequence,
  1022. int iFrame,
  1023. int iBone,
  1024. matrix3x4_t &mBoneLocal )
  1025. {
  1026. BONE_PROFILE_FUNC();
  1027. // FIXME: why does anyone call this instead of just looking up that entities cached animation?
  1028. // Reading the callers, I don't see how what it returns is of any use
  1029. mstudioseqdesc_t &seqdesc = pOwnerHdr->pSeqdesc( nSequence );
  1030. mstudioanimdesc_t &animdesc = pOwnerHdr->pAnimdesc( seqdesc.anim( 0, 0 ) );
  1031. int iLocalFrame = iFrame;
  1032. float s = 0;
  1033. const mstudiobone_t *pbone = pOwnerHdr->pBone( iBone );
  1034. BoneQuaternion boneQuat;
  1035. BoneVector bonePos;
  1036. bool bFound = false;
  1037. if (animdesc.flags & STUDIO_FRAMEANIM)
  1038. {
  1039. /*
  1040. mstudio_frame_anim_t *pFrameanim = (mstudio_frame_anim_t *)animdesc.pAnim( &iLocalFrame );
  1041. if (pFrameanim)
  1042. {
  1043. byte *pBoneFlags = pFrameanim->pBoneFlags( );
  1044. byte *pConstantData = pFrameanim->pConstantData( );
  1045. byte *pFrameData = pFrameanim->pFrameData( iLocalFrame );
  1046. // FIXME: this is the local bone index, not the global bone index
  1047. for (int i = 0; i < iBone; i++, pBoneFlags++)
  1048. {
  1049. pFrameData = SkipBoneFrame( *pBoneFlags, pFrameData, pConstantData );
  1050. }
  1051. pFrameData = ExtractSingleFrame( *pBoneFlags, pFrameData, pConstantData, boneQuat, bonePos );
  1052. bFound = true;
  1053. }
  1054. */
  1055. }
  1056. else
  1057. {
  1058. mstudio_rle_anim_t *panim = (mstudio_rle_anim_t *)animdesc.pAnim( &iLocalFrame );
  1059. // search for bone
  1060. // FIXME: this is the local bone index, not the global bone index
  1061. while (panim && panim->bone != iBone)
  1062. {
  1063. panim = panim->pNext();
  1064. }
  1065. // look up animation if found, if not, initialize
  1066. if (panim && seqdesc.weight(iBone) > 0)
  1067. {
  1068. CalcBoneQuaternion( iLocalFrame, s, pbone, NULL, panim, boneQuat );
  1069. CalcBonePosition ( iLocalFrame, s, pbone, NULL, panim, bonePos );
  1070. bFound = true;
  1071. }
  1072. }
  1073. if (!bFound)
  1074. {
  1075. if (animdesc.flags & STUDIO_DELTA)
  1076. {
  1077. boneQuat.Init( 0.0f, 0.0f, 0.0f, 1.0f );
  1078. bonePos.Init( 0.0f, 0.0f, 0.0f );
  1079. }
  1080. else
  1081. {
  1082. boneQuat = pbone->quat;
  1083. bonePos = pbone->pos;
  1084. }
  1085. }
  1086. QuaternionMatrix( boneQuat, bonePos, mBoneLocal );
  1087. }
  1088. //-----------------------------------------------------------------------------
  1089. // Purpose: Find and decode a sub-frame of animation, remapping the skeleton bone indexes
  1090. //-----------------------------------------------------------------------------
  1091. static void CalcVirtualAnimation( virtualmodel_t *pVModel, const CStudioHdr *pStudioHdr, BoneVector *pos, BoneQuaternion *q,
  1092. mstudioseqdesc_t &seqdesc, int sequence, int animation,
  1093. float cycle, int boneMask )
  1094. {
  1095. BONE_PROFILE_FUNC(); // ex: x360: up to 1.4ms
  1096. SNPROF_ANIM("CalcVirtualAnimation");
  1097. int i, j, k;
  1098. const mstudiobone_t *pbone;
  1099. const virtualgroup_t *pSeqGroup;
  1100. const studiohdr_t *pSeqStudioHdr;
  1101. const mstudiolinearbone_t *pSeqLinearBones;
  1102. const mstudiobone_t *pSeqbone;
  1103. const studiohdr_t *pAnimStudioHdr;
  1104. const mstudiolinearbone_t *pAnimLinearBones;
  1105. const mstudiobone_t *pAnimbone;
  1106. const virtualgroup_t *pAnimGroup;
  1107. pSeqGroup = pVModel->pSeqGroup( sequence );
  1108. int baseanimation = pStudioHdr->iRelativeAnim( sequence, animation );
  1109. mstudioanimdesc_t &animdesc = ((CStudioHdr *)pStudioHdr)->pAnimdesc( baseanimation );
  1110. pSeqStudioHdr = ((CStudioHdr *)pStudioHdr)->pSeqStudioHdr( sequence );
  1111. pSeqLinearBones = pSeqStudioHdr->pLinearBones();
  1112. pSeqbone = pSeqStudioHdr->pBone( 0 );
  1113. pAnimGroup = pVModel->pAnimGroup( baseanimation );
  1114. pAnimStudioHdr = ((CStudioHdr *)pStudioHdr)->pAnimStudioHdr( baseanimation );
  1115. pAnimLinearBones = pAnimStudioHdr->pLinearBones();
  1116. pAnimbone = pAnimStudioHdr->pBone( 0 );
  1117. #if _DEBUG
  1118. extern IDataCache *g_pDataCache;
  1119. #ifndef _GAMECONSOLE
  1120. // Consoles don't need to lock the modeldata cache since it never flushes
  1121. static IDataCacheSection *pModelCache = g_pDataCache->FindSection( "ModelData" );
  1122. AssertOnce( pModelCache->IsFrameLocking() );
  1123. #endif
  1124. static IDataCacheSection *pAnimblockCache = g_pDataCache->FindSection( "AnimBlock" );
  1125. AssertOnce( pAnimblockCache->IsFrameLocking() );
  1126. #endif
  1127. int iFrame;
  1128. float s;
  1129. float fFrame = cycle * (animdesc.numframes - 1);
  1130. iFrame = (int)fFrame;
  1131. s = (fFrame - iFrame);
  1132. int iLocalFrame = iFrame;
  1133. float flStall;
  1134. const mstudio_rle_anim_t *panim = NULL;
  1135. const mstudio_frame_anim_t *pFrameanim = NULL;
  1136. byte *pBoneFlags = NULL;
  1137. byte *pConstantData = NULL;
  1138. byte *pFrameData = NULL;
  1139. byte *pFrameDataNext = NULL;
  1140. int framelength = 0;
  1141. if (animdesc.flags & STUDIO_FRAMEANIM)
  1142. {
  1143. pFrameanim = (mstudio_frame_anim_t *)animdesc.pAnim( &iLocalFrame, flStall );
  1144. if ( pFrameanim )
  1145. {
  1146. pBoneFlags = pFrameanim->pBoneFlags( );
  1147. pConstantData = pFrameanim->pConstantData( );
  1148. pFrameData = pFrameanim->pFrameData( iLocalFrame );
  1149. framelength = pFrameanim->framelength;
  1150. pFrameDataNext = pFrameData + framelength;
  1151. PREFETCH360( pBoneFlags, 0 );
  1152. PREFETCH360( pFrameData, 0 );
  1153. PREFETCH360( pConstantData, 0 );
  1154. PREFETCH360( pFrameDataNext, 0 );
  1155. }
  1156. }
  1157. else
  1158. {
  1159. panim = (mstudio_rle_anim_t *)animdesc.pAnim( &iLocalFrame, flStall );
  1160. }
  1161. float *pweight = seqdesc.pBoneweight( 0 );
  1162. pbone = pStudioHdr->pBone( 0 );
  1163. int nBoneList[MAXSTUDIOBONES];
  1164. int nBoneListCount = 0;
  1165. for (i = 0; i < pStudioHdr->numbones(); i++)
  1166. {
  1167. if (pStudioHdr->boneFlags(i) & boneMask)
  1168. {
  1169. int j = pSeqGroup->boneMap[i];
  1170. if (j >= 0 && pweight[j] > 0.0f)
  1171. {
  1172. nBoneList[nBoneListCount++] = i;
  1173. }
  1174. }
  1175. }
  1176. if ( animdesc.flags & STUDIO_DELTA )
  1177. {
  1178. for ( i = 0; i < nBoneListCount; i++ )
  1179. {
  1180. int nBone = nBoneList[i];
  1181. q[nBone].Init( 0.0f, 0.0f, 0.0f, 1.0f );
  1182. pos[nBone].Init( 0.0f, 0.0f, 0.0f );
  1183. }
  1184. }
  1185. else if (pSeqLinearBones)
  1186. {
  1187. const Quaternion *pLinearQuat = &pSeqLinearBones->quat( 0 );
  1188. const Vector *pLinearPos = &pSeqLinearBones->pos( 0 );
  1189. for ( i = 0; i < nBoneListCount; i++ )
  1190. {
  1191. int nBone = nBoneList[i];
  1192. int j = pSeqGroup->boneMap[nBone];
  1193. q[nBone] = pLinearQuat[j];
  1194. pos[nBone] = pLinearPos[j];
  1195. }
  1196. }
  1197. else
  1198. {
  1199. for ( i = 0; i < nBoneListCount; i++ )
  1200. {
  1201. int nBone = nBoneList[i];
  1202. int j = pSeqGroup->boneMap[nBone];
  1203. q[nBone] = pSeqbone[j].quat;
  1204. pos[nBone] = pSeqbone[j].pos;
  1205. }
  1206. }
  1207. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1208. pStudioHdr->m_nPerfUsedBones += nBoneListCount;
  1209. #endif
  1210. // decode frame animation
  1211. if (pFrameanim)
  1212. {
  1213. // byte *pBoneFlags = pFrameanim->pBoneFlags( );
  1214. // byte *pConstantData = pFrameanim->pConstantData( );
  1215. // byte *pFrameData = pFrameanim->pFrameData( iLocalFrame );
  1216. // int framelength = pFrameanim->framelength;
  1217. if (s > 0.0)
  1218. {
  1219. for (i = 0; i < pAnimStudioHdr->numbones; i++)
  1220. {
  1221. j = pAnimGroup->masterBone[i];
  1222. if ( j >= 0 && ( pStudioHdr->boneFlags(j) & boneMask ) )
  1223. {
  1224. pFrameData = ExtractTwoFrames( *pBoneFlags, s, pFrameData, pConstantData, framelength, q[j], pos[j] );
  1225. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1226. pStudioHdr->m_nPerfAnimatedBones++;
  1227. #endif
  1228. }
  1229. else
  1230. {
  1231. pFrameData = SkipBoneFrame( *pBoneFlags, pFrameData, pConstantData );
  1232. }
  1233. pBoneFlags++;
  1234. }
  1235. }
  1236. else
  1237. {
  1238. for (i = 0; i < pAnimStudioHdr->numbones; i++)
  1239. {
  1240. j = pAnimGroup->masterBone[i];
  1241. if ( j >= 0 && ( pStudioHdr->boneFlags(j) & boneMask ) )
  1242. {
  1243. pFrameData = ExtractSingleFrame( *pBoneFlags, pFrameData, pConstantData, q[j], pos[j] );
  1244. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1245. pStudioHdr->m_nPerfAnimatedBones++;
  1246. #endif
  1247. }
  1248. else
  1249. {
  1250. pFrameData = SkipBoneFrame( *pBoneFlags, pFrameData, pConstantData );
  1251. }
  1252. pBoneFlags++;
  1253. }
  1254. }
  1255. }
  1256. else if (panim)
  1257. {
  1258. // FIXME: change encoding so that bone -1 is never the case
  1259. while (panim && panim->bone < 255)
  1260. {
  1261. j = pAnimGroup->masterBone[panim->bone];
  1262. if ( j >= 0 && ( pStudioHdr->boneFlags(j) & boneMask ) )
  1263. {
  1264. k = pSeqGroup->boneMap[j];
  1265. if (k >= 0 && pweight[k] > 0.0f)
  1266. {
  1267. CalcBoneQuaternion( iLocalFrame, s, &pAnimbone[panim->bone], pAnimLinearBones, panim, q[j] );
  1268. CalcBonePosition ( iLocalFrame, s, &pAnimbone[panim->bone], pAnimLinearBones, panim, pos[j] );
  1269. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1270. pStudioHdr->m_nPerfAnimatedBones++;
  1271. #endif
  1272. }
  1273. }
  1274. panim = panim->pNext();
  1275. }
  1276. }
  1277. else
  1278. {
  1279. CalcZeroframeData( pStudioHdr, pAnimStudioHdr, pAnimGroup, pAnimbone, animdesc, fFrame, pos, q, boneMask, 1.0 );
  1280. return;
  1281. }
  1282. // cross fade in previous zeroframe data
  1283. if (flStall > 0.0f)
  1284. {
  1285. CalcZeroframeData( pStudioHdr, pAnimStudioHdr, pAnimGroup, pAnimbone, animdesc, fFrame, pos, q, boneMask, flStall );
  1286. }
  1287. // calculate a local hierarchy override
  1288. if (animdesc.numlocalhierarchy)
  1289. {
  1290. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  1291. CBoneBitList boneComputed;
  1292. int i;
  1293. for (i = 0; i < animdesc.numlocalhierarchy; i++)
  1294. {
  1295. mstudiolocalhierarchy_t *pHierarchy = animdesc.pHierarchy( i );
  1296. if ( !pHierarchy )
  1297. break;
  1298. int iBone = pAnimGroup->masterBone[pHierarchy->iBone];
  1299. if (iBone >= 0 && (pStudioHdr->boneFlags(iBone) & boneMask))
  1300. {
  1301. int iNewParent = pAnimGroup->masterBone[pHierarchy->iNewParent];
  1302. if (iNewParent >= 0 && (pStudioHdr->boneFlags(iNewParent) & boneMask))
  1303. {
  1304. CalcLocalHierarchyAnimation( pStudioHdr, boneToWorld, boneComputed, pos, q, pbone, pHierarchy, iBone, iNewParent, cycle, iFrame, s, boneMask );
  1305. }
  1306. }
  1307. }
  1308. g_MatrixPool.Free( boneToWorld );
  1309. }
  1310. }
  1311. //-----------------------------------------------------------------------------
  1312. // Purpose: Find and decode a sub-frame of animation
  1313. //-----------------------------------------------------------------------------
  1314. void CalcAnimation( const CStudioHdr *pStudioHdr, BoneVector *pos, BoneQuaternion *q,
  1315. mstudioseqdesc_t &seqdesc,
  1316. int sequence, int animation,
  1317. float cycle, int boneMask )
  1318. {
  1319. BONE_PROFILE_FUNC();
  1320. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1321. pStudioHdr->m_nPerfAnimationLayers++;
  1322. #endif
  1323. virtualmodel_t *pVModel = pStudioHdr->GetVirtualModel();
  1324. if (pVModel)
  1325. {
  1326. CalcVirtualAnimation( pVModel, pStudioHdr, pos, q, seqdesc, sequence, animation, cycle, boneMask );
  1327. return;
  1328. }
  1329. SNPROF_ANIM("CalcAnimation");
  1330. #if _DEBUG
  1331. extern IDataCache *g_pDataCache;
  1332. #ifndef _GAMECONSOLE
  1333. // Consoles don't need to lock the modeldata cache since it never flushes
  1334. static IDataCacheSection *pModelCache = g_pDataCache->FindSection( "ModelData" );
  1335. AssertOnce( pModelCache->IsFrameLocking() );
  1336. #endif
  1337. static IDataCacheSection *pAnimblockCache = g_pDataCache->FindSection( "AnimBlock" );
  1338. AssertOnce( pAnimblockCache->IsFrameLocking() );
  1339. #endif
  1340. mstudioanimdesc_t &animdesc = ((CStudioHdr *)pStudioHdr)->pAnimdesc( animation );
  1341. const mstudiobone_t *pbone = pStudioHdr->pBone( 0 );
  1342. const mstudiolinearbone_t *pLinearBones = pStudioHdr->pLinearBones();
  1343. int i;
  1344. int iFrame;
  1345. float s;
  1346. float fFrame = cycle * (animdesc.numframes - 1);
  1347. iFrame = (int)fFrame;
  1348. s = (fFrame - iFrame);
  1349. int iLocalFrame = iFrame;
  1350. float flStall = 0.0f;
  1351. const mstudio_rle_anim_t *panim = NULL;
  1352. const mstudio_frame_anim_t *pFrameanim = NULL;
  1353. byte *pBoneFlags = NULL;
  1354. byte *pConstantData = NULL;
  1355. byte *pFrameData = NULL;
  1356. byte *pFrameDataNext = NULL;
  1357. int framelength = NULL;
  1358. if (animdesc.flags & STUDIO_FRAMEANIM)
  1359. {
  1360. pFrameanim = (mstudio_frame_anim_t *)animdesc.pAnim( &iLocalFrame, flStall );
  1361. if ( pFrameanim )
  1362. {
  1363. pBoneFlags = pFrameanim->pBoneFlags( );
  1364. pConstantData = pFrameanim->pConstantData( );
  1365. pFrameData = pFrameanim->pFrameData( iLocalFrame );
  1366. framelength = pFrameanim->framelength;
  1367. pFrameDataNext = pFrameData + framelength;
  1368. PREFETCH360( pBoneFlags, 0 );
  1369. PREFETCH360( pFrameData, 0 );
  1370. PREFETCH360( pConstantData, 0 );
  1371. PREFETCH360( pFrameDataNext, 0 );
  1372. }
  1373. }
  1374. else
  1375. {
  1376. panim = (mstudio_rle_anim_t *)animdesc.pAnim( &iLocalFrame, flStall );
  1377. }
  1378. float *pweight = seqdesc.pBoneweight( 0 );
  1379. bool bIsDelta = (animdesc.flags & STUDIO_DELTA) != 0;
  1380. // if the animation isn't available, look for the zero frame cache
  1381. if (!panim && !pFrameanim)
  1382. {
  1383. // Msg("zeroframe %s\n", animdesc.pszName() );
  1384. // pre initialize
  1385. for (i = 0; i < pStudioHdr->numbones(); i++, pbone++, pweight++)
  1386. {
  1387. if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask))
  1388. {
  1389. if (bIsDelta)
  1390. {
  1391. q[i].Init( 0.0f, 0.0f, 0.0f, 1.0f );
  1392. pos[i].Init( 0.0f, 0.0f, 0.0f );
  1393. }
  1394. else
  1395. {
  1396. q[i] = pbone->quat;
  1397. pos[i] = pbone->pos;
  1398. }
  1399. }
  1400. }
  1401. CalcZeroframeData( pStudioHdr, pStudioHdr->GetRenderHdr(), NULL, pStudioHdr->pBone( 0 ), animdesc, fFrame, pos, q, boneMask, 1.0 );
  1402. return;
  1403. }
  1404. // decode frame animation
  1405. if (pFrameanim)
  1406. {
  1407. // byte *pBoneFlags = pFrameanim->pBoneFlags( );
  1408. // byte *pConstantData = pFrameanim->pConstantData( );
  1409. // byte *pFrameData = pFrameanim->pFrameData( iLocalFrame );
  1410. // int framelength = pFrameanim->framelength;
  1411. if (s > 0.0)
  1412. {
  1413. for (i = 0; i < pStudioHdr->numbones(); i++, pBoneFlags++, pweight++)
  1414. {
  1415. if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask))
  1416. {
  1417. pFrameData = ExtractTwoFrames( *pBoneFlags, s, pFrameData, pConstantData, framelength, q[i], pos[i], bIsDelta, pLinearBones, i );
  1418. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1419. pStudioHdr->m_nPerfAnimatedBones++;
  1420. #endif
  1421. }
  1422. else
  1423. {
  1424. pFrameData = SkipBoneFrame( *pBoneFlags, pFrameData, pConstantData );
  1425. }
  1426. pStudioHdr->m_nPerfUsedBones++;
  1427. }
  1428. }
  1429. else
  1430. {
  1431. for (i = 0; i < pStudioHdr->numbones(); i++, pBoneFlags++, pweight++)
  1432. {
  1433. if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask))
  1434. {
  1435. pFrameData = ExtractSingleFrame( *pBoneFlags, pFrameData, pConstantData, q[i], pos[i], bIsDelta, pLinearBones, i );
  1436. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1437. pStudioHdr->m_nPerfAnimatedBones++;
  1438. #endif
  1439. }
  1440. else
  1441. {
  1442. pFrameData = SkipBoneFrame( *pBoneFlags, pFrameData, pConstantData );
  1443. }
  1444. pStudioHdr->m_nPerfUsedBones++;
  1445. }
  1446. }
  1447. }
  1448. else
  1449. {
  1450. // BUGBUG: the sequence, the anim, and the model can have all different bone mappings.
  1451. for (i = 0; i < pStudioHdr->numbones(); i++, pbone++, pweight++)
  1452. {
  1453. if (panim && panim->bone == i)
  1454. {
  1455. if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask))
  1456. {
  1457. CalcBoneQuaternion( iLocalFrame, s, pbone, pLinearBones, panim, q[i] );
  1458. CalcBonePosition ( iLocalFrame, s, pbone, pLinearBones, panim, pos[i] );
  1459. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1460. pStudioHdr->m_nPerfAnimatedBones++;
  1461. pStudioHdr->m_nPerfUsedBones++;
  1462. #endif
  1463. }
  1464. panim = panim->pNext();
  1465. }
  1466. else if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask))
  1467. {
  1468. if (bIsDelta)
  1469. {
  1470. q[i].Init( 0.0f, 0.0f, 0.0f, 1.0f );
  1471. pos[i].Init( 0.0f, 0.0f, 0.0f );
  1472. }
  1473. else
  1474. {
  1475. q[i] = pbone->quat;
  1476. pos[i] = pbone->pos;
  1477. }
  1478. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  1479. pStudioHdr->m_nPerfUsedBones++;
  1480. #endif
  1481. }
  1482. }
  1483. }
  1484. // cross fade in previous zeroframe data
  1485. if (flStall > 0.0f)
  1486. {
  1487. CalcZeroframeData( pStudioHdr, pStudioHdr->GetRenderHdr(), NULL, pStudioHdr->pBone( 0 ), animdesc, fFrame, pos, q, boneMask, flStall );
  1488. }
  1489. if (animdesc.numlocalhierarchy)
  1490. {
  1491. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  1492. CBoneBitList boneComputed;
  1493. int i;
  1494. for (i = 0; i < animdesc.numlocalhierarchy; i++)
  1495. {
  1496. mstudiolocalhierarchy_t *pHierarchy = animdesc.pHierarchy( i );
  1497. if ( !pHierarchy )
  1498. break;
  1499. if (pStudioHdr->boneFlags(pHierarchy->iBone) & boneMask)
  1500. {
  1501. if (pStudioHdr->boneFlags(pHierarchy->iNewParent) & boneMask)
  1502. {
  1503. CalcLocalHierarchyAnimation( pStudioHdr, boneToWorld, boneComputed, pos, q, pbone, pHierarchy, pHierarchy->iBone, pHierarchy->iNewParent, cycle, iFrame, s, boneMask );
  1504. }
  1505. }
  1506. }
  1507. g_MatrixPool.Free( boneToWorld );
  1508. }
  1509. }