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.

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