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.

1509 lines
45 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. #endif
  15. #include "bone_utils_PS3.h"
  16. class CIKSolver_PS3
  17. {
  18. public:
  19. //-------- SOLVE TWO LINK INVERSE KINEMATICS -------------
  20. // Author: Ken Perlin
  21. //
  22. // Given a two link joint from [0,0,0] to end effector position P,
  23. // let link lengths be a and b, and let norm |P| = c. Clearly a+b <= c.
  24. //
  25. // Problem: find a "knee" position Q such that |Q| = a and |P-Q| = b.
  26. //
  27. // In the case of a point on the x axis R = [c,0,0], there is a
  28. // closed form solution S = [d,e,0], where |S| = a and |R-S| = b:
  29. //
  30. // d2+e2 = a2 -- because |S| = a
  31. // (c-d)2+e2 = b2 -- because |R-S| = b
  32. //
  33. // c2-2cd+d2+e2 = b2 -- combine the two equations
  34. // c2-2cd = b2 - a2
  35. // c-2d = (b2-a2)/c
  36. // d - c/2 = (a2-b2)/c / 2
  37. //
  38. // d = (c + (a2-b2/c) / 2 -- to solve for d and e.
  39. // e = sqrt(a2-d2)
  40. static float findD(float a, float b, float c) {
  41. return (c + (a*a-b*b)/c) / 2;
  42. }
  43. static float findE(float a, float d) { return sqrt(a*a-d*d); }
  44. // This leads to a solution to the more general problem:
  45. //
  46. // (1) R = Mfwd(P) -- rotate P onto the x axis
  47. // (2) Solve for S
  48. // (3) Q = Minv(S) -- rotate back again
  49. float Mfwd[3][3];
  50. float Minv[3][3];
  51. bool solve(float A, float B, float const P[], float const D[], float Q[]) {
  52. float R[3];
  53. defineM(P,D);
  54. rot(Minv,P,R);
  55. float r = length(R);
  56. float d = findD(A,B,r);
  57. float e = findE(A,d);
  58. float S[3] = {d,e,0};
  59. rot(Mfwd,S,Q);
  60. return d > (r - B) && d < A;
  61. }
  62. // If "knee" position Q needs to be as close as possible to some point D,
  63. // then choose M such that M(D) is in the y>0 half of the z=0 plane.
  64. //
  65. // Given that constraint, define the forward and inverse of M as follows:
  66. void defineM(float const P[], float const D[]) {
  67. float *X = Minv[0], *Y = Minv[1], *Z = Minv[2];
  68. // Minv defines a coordinate system whose x axis contains P, so X = unit(P).
  69. int i;
  70. for (i = 0 ; i < 3 ; i++)
  71. X[i] = P[i];
  72. normalize(X);
  73. // Its y axis is perpendicular to P, so Y = unit( E - X(E�X) ).
  74. float dDOTx = dot(D,X);
  75. for (i = 0 ; i < 3 ; i++)
  76. Y[i] = D[i] - dDOTx * X[i];
  77. normalize(Y);
  78. // Its z axis is perpendicular to both X and Y, so Z = X�Y.
  79. cross(X,Y,Z);
  80. // Mfwd = (Minv)T, since transposing inverts a rotation matrix.
  81. for (i = 0 ; i < 3 ; i++) {
  82. Mfwd[i][0] = Minv[0][i];
  83. Mfwd[i][1] = Minv[1][i];
  84. Mfwd[i][2] = Minv[2][i];
  85. }
  86. }
  87. //------------ GENERAL VECTOR MATH SUPPORT -----------
  88. static float dot(float const a[], float const b[]) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
  89. static float length(float const v[]) { return sqrt( dot(v,v) ); }
  90. static void normalize(float v[]) {
  91. float norm = length(v);
  92. for (int i = 0 ; i < 3 ; i++)
  93. v[i] /= norm;
  94. }
  95. static void cross(float const a[], float const b[], float c[]) {
  96. c[0] = a[1] * b[2] - a[2] * b[1];
  97. c[1] = a[2] * b[0] - a[0] * b[2];
  98. c[2] = a[0] * b[1] - a[1] * b[0];
  99. }
  100. static void rot(float const M[3][3], float const src[], float dst[]) {
  101. for (int i = 0 ; i < 3 ; i++)
  102. dst[i] = dot(M[i],src);
  103. }
  104. };
  105. //-----------------------------------------------------------------------------
  106. // Purpose: for a 2 bone chain, find the IK solution and reset the matrices
  107. //-----------------------------------------------------------------------------
  108. bool Studio_SolveIK_PS3( Vector &kneeDir0, int bone0, int bone1, int bone2, Vector &targetFoot, matrix3x4a_t *pBoneToWorld )
  109. {
  110. #if 0
  111. // see bone_ik.cpp - something with the CS models breaks this
  112. if( kneeDir0.LengthSqr() > 0.0f )
  113. {
  114. Vector targetKneeDir, targetKneePos;
  115. // FIXME: knee length should be as long as the legs
  116. Vector tmp = kneeDir0;
  117. VectorRotate_PS3( tmp, pBoneToWorld[ bone0 ], targetKneeDir );
  118. MatrixPosition_PS3( pBoneToWorld[ bone1 ], targetKneePos );
  119. return Studio_SolveIK_PS3( bone0, bone1, bone2, targetFoot, targetKneePos, targetKneeDir, pBoneToWorld );
  120. }
  121. else
  122. #endif
  123. {
  124. return Studio_SolveIK_PS3( bone0, bone1, bone2, targetFoot, pBoneToWorld );
  125. }
  126. }
  127. //-----------------------------------------------------------------------------
  128. //
  129. //-----------------------------------------------------------------------------
  130. float Studio_IKRuleWeight_PS3( mstudioikrule_t_PS3 &ikRule, int anim_numframes, float flCycle, int &iFrame, float &fraq )
  131. {
  132. if( ikRule.end > 1.0f && flCycle < ikRule.start )
  133. {
  134. flCycle = flCycle + 1.0f;
  135. }
  136. float value = 0.0f;
  137. fraq = (anim_numframes - 1) * (flCycle - ikRule.start) + ikRule.iStart;
  138. iFrame = (int)fraq;
  139. fraq = fraq - iFrame;
  140. if( flCycle < ikRule.start )
  141. {
  142. iFrame = ikRule.iStart;
  143. fraq = 0.0f;
  144. return 0.0f;
  145. }
  146. else if( flCycle < ikRule.peak )
  147. {
  148. value = (flCycle - ikRule.start) / (ikRule.peak - ikRule.start);
  149. }
  150. else if( flCycle < ikRule.tail )
  151. {
  152. return 1.0f;
  153. }
  154. else if( flCycle < ikRule.end )
  155. {
  156. value = 1.0f - ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail));
  157. }
  158. else
  159. {
  160. fraq = (anim_numframes - 1) * (ikRule.end - ikRule.start) + ikRule.iStart;
  161. iFrame = (int)fraq;
  162. fraq = fraq - iFrame;
  163. }
  164. return SimpleSpline_PS3( value );
  165. }
  166. //-----------------------------------------------------------------------------
  167. //
  168. //-----------------------------------------------------------------------------
  169. float Studio_IKRuleWeight_PS3( ikcontextikrule_t_PS3 &ikRule, float flCycle )
  170. {
  171. if( ikRule.end > 1.0f && flCycle < ikRule.start )
  172. {
  173. flCycle = flCycle + 1.0f;
  174. }
  175. float value = 0.0f;
  176. if( flCycle < ikRule.start )
  177. {
  178. return 0.0f;
  179. }
  180. else if( flCycle < ikRule.peak )
  181. {
  182. value = (flCycle - ikRule.start) / (ikRule.peak - ikRule.start);
  183. }
  184. else if( flCycle < ikRule.tail )
  185. {
  186. return 1.0f;
  187. }
  188. else if( flCycle < ikRule.end )
  189. {
  190. value = 1.0f - ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail));
  191. }
  192. return 3.0f * value * value - 2.0f * value * value * value;
  193. }
  194. //-----------------------------------------------------------------------------
  195. //
  196. //-----------------------------------------------------------------------------
  197. float Studio_IKTail_PS3( ikcontextikrule_t_PS3 &ikRule, float flCycle )
  198. {
  199. if( ikRule.end > 1.0f && flCycle < ikRule.start )
  200. {
  201. flCycle = flCycle + 1.0f;
  202. }
  203. if( flCycle <= ikRule.tail )
  204. {
  205. return 0.0f;
  206. }
  207. else if( flCycle < ikRule.end )
  208. {
  209. return ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail));
  210. }
  211. return 0.0f;
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Purpose:
  215. //-----------------------------------------------------------------------------
  216. bool Studio_IKShouldLatch_PS3( ikcontextikrule_t_PS3 &ikRule, float flCycle )
  217. {
  218. if( ikRule.end > 1.0f && flCycle < ikRule.start )
  219. {
  220. flCycle = flCycle + 1.0f;
  221. }
  222. if( flCycle < ikRule.peak )
  223. {
  224. return false;
  225. }
  226. else if( flCycle < ikRule.end )
  227. {
  228. return true;
  229. }
  230. return false;
  231. }
  232. //-----------------------------------------------------------------------------
  233. //
  234. //-----------------------------------------------------------------------------
  235. bool Studio_IKAnimationError_PS3( animData_SPU *panim, mstudioanimdesc_t_PS3 *pAnimdesc, void *pEA_IKRule, mstudioikrule_t_PS3 *pLS_IKRule, float flCycle, BoneVector &pos, BoneQuaternion &q, float &flWeight )
  236. {
  237. float fraq;
  238. int iFrame;
  239. if( !pEA_IKRule )
  240. return false;
  241. flWeight = Studio_IKRuleWeight_PS3( *pLS_IKRule, pAnimdesc->numframes, flCycle, iFrame, fraq );
  242. Assert( fraq >= 0.0f && fraq < 1.0f );
  243. Assert( flWeight >= 0.0f && flWeight <= 1.0f );
  244. // This shouldn't be necessary, but the Assert should help us catch whoever is screwing this up
  245. flWeight = clamp( flWeight, 0.0f, 1.0f );
  246. if( pLS_IKRule->type != IK_GROUND && flWeight < 0.0001f )
  247. return false;
  248. void *pEA_Error = (void *)pLS_IKRule->pError( pEA_IKRule, iFrame );
  249. if( pEA_Error != NULL )
  250. {
  251. mstudioikerror_t_PS3 error[ 3 ] ALIGN16;
  252. mstudioikerror_t_PS3 *pLS_Error;
  253. pLS_Error = (mstudioikerror_t_PS3 *)SPUmemcpy_UnalignedGet( error, (uint32)pEA_Error, 2*sizeof(mstudioikerror_t_PS3) );
  254. if( fraq < 0.001f )
  255. {
  256. q = pLS_Error[0].q;
  257. pos = pLS_Error[0].pos;
  258. }
  259. else
  260. {
  261. QuaternionBlend_PS3( pLS_Error[0].q, pLS_Error[1].q, fraq, q );
  262. pos = pLS_Error[0].pos * (1.0f - fraq) + pLS_Error[1].pos * fraq;
  263. }
  264. return true;
  265. }
  266. void *pEA_Compressed = (void *)pLS_IKRule->pCompressedError( pEA_IKRule );
  267. if( pEA_Compressed != NULL )
  268. {
  269. mstudiocompressedikerror_t_PS3 compressed[ 3 ] ALIGN16;
  270. mstudiocompressedikerror_t_PS3 *pLS_Compressed;
  271. pLS_Compressed = (mstudiocompressedikerror_t_PS3 *)SPUmemcpy_UnalignedGet( compressed, (uint32)pEA_Compressed, sizeof(mstudiocompressedikerror_t_PS3) );
  272. CalcDecompressedAnimation_PS3( pEA_Compressed, pLS_Compressed, iFrame - pLS_IKRule->iStart, fraq, pos, q );
  273. return true;
  274. }
  275. // no data, disable IK rule
  276. Assert( 0 );
  277. flWeight = 0.0f;
  278. return false;
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Purpose: For a specific sequence:rule, find where it starts, stops, and what
  282. // the estimated offset from the connection point is.
  283. // return true if the rule is within bounds.
  284. //-----------------------------------------------------------------------------
  285. bool Studio_IKSequenceError_PS3( accumposeentry_SPU *pPoseEntry, int iRule, const float poseParameter[], ikcontextikrule_t_PS3 &ikRule )
  286. {
  287. int i;
  288. memset( &ikRule, 0, sizeof(ikRule) );
  289. ikRule.start = ikRule.peak = ikRule.tail = ikRule.end = 0.0f;
  290. float prevStart = 0.0f;
  291. animData_SPU *pAnim0 = NULL;
  292. if( pPoseEntry->animIndices[0] != -1 )
  293. {
  294. pAnim0 = &pPoseEntry->anims[ pPoseEntry->animIndices[0] ];
  295. }
  296. //mstudioikrule_t_PS3 ikrule[4][2] ALIGN16;
  297. byte ikrule[4][ ROUNDUPTONEXT16B( sizeof(mstudioikrule_t_PS3) ) ] ALIGN16;
  298. //mstudioikrulezeroframe_t_PS3 ikrulezeroframe[4][2] ALIGN16;
  299. byte ikrulezeroframe[4][ ROUNDUPTONEXT16B( sizeof(mstudioikrulezeroframe_t_PS3) ) ] ALIGN16;
  300. //mstudioanimdesc_t_PS3 ls_animdesc[4][2] ALIGN16;
  301. byte ls_animdesc[4][ ROUNDUPTONEXT16B( sizeof(mstudioanimdesc_t_PS3) ) ] ALIGN16;
  302. mstudioikrule_t_PS3 *pLS_IKRule[4];
  303. mstudioikrulezeroframe_t_PS3 *pLS_IKRuleZeroFrame[4];
  304. mstudioanimdesc_t_PS3 *pLS_animdesc[4];
  305. float flCycle = pPoseEntry->cyclePoseSingle;
  306. // prefetch animdesc
  307. for( i = 0; i < 4; i++ )
  308. {
  309. int idx = pPoseEntry->animIndices[ i ];
  310. if( idx != -1 )
  311. {
  312. animData_SPU *pAnim = &pPoseEntry->anims[ idx ];
  313. pLS_animdesc[ idx ] = (mstudioanimdesc_t_PS3 *)SPUmemcpy_UnalignedGet_MustSync( ls_animdesc[ idx ], (uint32)pAnim->pEA_animdesc, sizeof(mstudioanimdesc_t_PS3), DMATAG_ANIM );
  314. }
  315. else
  316. {
  317. pLS_animdesc[ idx ] = NULL;
  318. }
  319. pLS_IKRule[ i ] = NULL;
  320. pLS_IKRuleZeroFrame[ i ] = NULL;
  321. }
  322. SPUmemcpy_Sync( 1<<DMATAG_ANIM );
  323. // find overall influence
  324. for( i = 0; i < 4; i++ )
  325. {
  326. int idx = pPoseEntry->animIndices[ i ];
  327. if( idx != -1 )
  328. {
  329. mstudioanimdesc_t_PS3 *pAnimdesc = pLS_animdesc[ idx ];
  330. animData_SPU *pAnim = &pPoseEntry->anims[ idx ];
  331. if( iRule >= pAnimdesc->numikrules || pAnimdesc->numikrules != pLS_animdesc[ pPoseEntry->animIndices[0] ]->numikrules )
  332. {
  333. Assert( 0 );
  334. return false;
  335. }
  336. //mstudioikrule_t_PS3 *pRule = panim[i]->pIKRule( iRule );
  337. if( pAnim->pEA_animdesc_ikrule )
  338. {
  339. pLS_IKRule[ idx ] = (mstudioikrule_t_PS3 *)SPUmemcpy_UnalignedGet( ikrule[ idx ], (uint32)((mstudioikrule_t_PS3 *)pAnim->pEA_animdesc_ikrule + iRule), sizeof(mstudioikrule_t_PS3) );
  340. mstudioikrule_t_PS3 *pIKRule = pLS_IKRule[ idx ];
  341. float dt = 0.0f;
  342. if( prevStart != 0.0f )
  343. {
  344. if( pIKRule->start - prevStart > 0.5f )
  345. {
  346. dt = -1.0f;
  347. }
  348. else if( pIKRule->start - prevStart < -0.5f )
  349. {
  350. dt = 1.0f;
  351. }
  352. }
  353. else
  354. {
  355. prevStart = pIKRule->start;
  356. }
  357. ikRule.start += (pIKRule->start + dt) * pAnim->seqdesc_weight;
  358. ikRule.peak += (pIKRule->peak + dt) * pAnim->seqdesc_weight;
  359. ikRule.tail += (pIKRule->tail + dt) * pAnim->seqdesc_weight;
  360. ikRule.end += (pIKRule->end + dt) * pAnim->seqdesc_weight;
  361. }
  362. else
  363. {
  364. //mstudioikrulezeroframe_t *pZeroFrameRule = panim[i]->pIKRuleZeroFrame( iRule );
  365. if( pAnim->pEA_animdesc_ikrulezeroframe )
  366. {
  367. pLS_IKRuleZeroFrame[ idx ] = (mstudioikrulezeroframe_t_PS3 *)SPUmemcpy_UnalignedGet( ikrulezeroframe[ idx ], (uint32)((mstudioikrulezeroframe_t_PS3 *)pAnim->pEA_animdesc_ikrulezeroframe + iRule), sizeof(mstudioikrulezeroframe_t_PS3) );
  368. mstudioikrulezeroframe_t_PS3 *pIKRule = pLS_IKRuleZeroFrame[ idx ];
  369. float dt = 0.0f;
  370. if (prevStart != 0.0f)
  371. {
  372. if( pIKRule->start.GetFloat() - prevStart > 0.5f )
  373. {
  374. dt = -1.0f;
  375. }
  376. else if( pIKRule->start.GetFloat() - prevStart < -0.5f )
  377. {
  378. dt = 1.0f;
  379. }
  380. }
  381. else
  382. {
  383. prevStart = pIKRule->start.GetFloat();
  384. }
  385. ikRule.start += (pIKRule->start.GetFloat() + dt) * pAnim->seqdesc_weight;
  386. ikRule.peak += (pIKRule->peak.GetFloat() + dt) * pAnim->seqdesc_weight;
  387. ikRule.tail += (pIKRule->tail.GetFloat() + dt) * pAnim->seqdesc_weight;
  388. ikRule.end += (pIKRule->end.GetFloat() + dt) * pAnim->seqdesc_weight;
  389. }
  390. else
  391. {
  392. // Msg("%s %s - IK Stall\n", pStudioHdr->name(), seqdesc.pszLabel() );
  393. return false;
  394. }
  395. }
  396. }
  397. }
  398. if( ikRule.start > 1.0f )
  399. {
  400. ikRule.start -= 1.0f;
  401. ikRule.peak -= 1.0f;
  402. ikRule.tail -= 1.0f;
  403. ikRule.end -= 1.0f;
  404. }
  405. else if( ikRule.start < 0.0f )
  406. {
  407. ikRule.start += 1.0f;
  408. ikRule.peak += 1.0f;
  409. ikRule.tail += 1.0f;
  410. ikRule.end += 1.0f;
  411. }
  412. ikRule.flWeight = Studio_IKRuleWeight_PS3( ikRule, flCycle );
  413. if( ikRule.flWeight <= 0.001f )
  414. {
  415. // go ahead and allow IK_GROUND rules a virtual looping section
  416. if( pAnim0->pEA_animdesc_ikrule == NULL )
  417. return false;
  418. int ikrule0_type;
  419. int idx0 = pPoseEntry->animIndices[ 0 ];
  420. if( idx0 != -1 )
  421. {
  422. if( pLS_IKRule[ idx0 ] == NULL )
  423. {
  424. pLS_IKRule[ idx0 ] = (mstudioikrule_t_PS3 *)SPUmemcpy_UnalignedGet( ikrule[ idx0 ], (uint32)((mstudioikrule_t_PS3 *)pAnim0->pEA_animdesc_ikrule + iRule), sizeof(mstudioikrule_t_PS3) );
  425. }
  426. ikrule0_type = pLS_IKRule[ idx0 ]->type;
  427. if( (pLS_animdesc[ idx0 ]->flags & STUDIO_LOOPING) && ikrule0_type == IK_GROUND && ikRule.end - ikRule.start > 0.75f )
  428. {
  429. ikRule.flWeight = 0.001f;
  430. //??
  431. flCycle = ikRule.end - 0.001f;
  432. }
  433. else
  434. {
  435. return false;
  436. }
  437. }
  438. }
  439. Assert( ikRule.flWeight > 0.0f );
  440. ikRule.pos.Init();
  441. ikRule.q.Init();
  442. // find target error
  443. float total = 0.0f;
  444. for( i = 0; i < 4; i++ )
  445. {
  446. int idx = pPoseEntry->animIndices[i];
  447. if( idx != -1 )
  448. {
  449. mstudioanimdesc_t_PS3 *pAnimdesc = pLS_animdesc[ idx ];
  450. animData_SPU *pAnim = &pPoseEntry->anims[ idx ];
  451. BoneVector pos1;
  452. BoneQuaternion q1;
  453. float w;
  454. // mstudioikrule_t *pRule = panim[i]->pIKRule( iRule );
  455. mstudioikrule_t_PS3 *pRule = pLS_IKRule[ idx ];
  456. if( pRule != NULL )
  457. {
  458. ikRule.chain = pRule->chain; // FIXME: this is anim local
  459. ikRule.bone = pRule->bone; // FIXME: this is anim local
  460. ikRule.type = pRule->type;
  461. ikRule.slot = pRule->slot;
  462. ikRule.height += pRule->height * pAnim->seqdesc_weight;
  463. ikRule.floor += pRule->floor * pAnim->seqdesc_weight;
  464. ikRule.radius += pRule->radius * pAnim->seqdesc_weight;
  465. ikRule.drop += pRule->drop * pAnim->seqdesc_weight;
  466. ikRule.top += pRule->top * pAnim->seqdesc_weight;
  467. }
  468. else
  469. {
  470. // look to see if there's a zeroframe version of the rule
  471. mstudioikrulezeroframe_t_PS3 *pZeroFrameRule = pLS_IKRuleZeroFrame[ idx ];//panim[i]->pIKRuleZeroFrame( iRule );
  472. if( pZeroFrameRule )
  473. {
  474. // zeroframe doesn't contain details, so force a IK_RELEASE
  475. ikRule.type = IK_RELEASE;
  476. ikRule.chain = pZeroFrameRule->chain;
  477. ikRule.slot = pZeroFrameRule->slot;
  478. ikRule.bone = -1;
  479. // Msg("IK_RELEASE %d %d : %.2f\n", ikRule.chain, ikRule.slot, ikRule.flWeight );
  480. }
  481. else
  482. {
  483. // Msg("%s %s - IK Stall\n", pStudioHdr->name(), seqdesc.pszLabel() );
  484. return false;
  485. }
  486. }
  487. // keep track of tail condition
  488. ikRule.release += Studio_IKTail_PS3( ikRule, flCycle ) * pAnim->seqdesc_weight;
  489. // only check rules with error values
  490. switch( ikRule.type )
  491. {
  492. case IK_SELF:
  493. case IK_WORLD:
  494. case IK_GROUND:
  495. case IK_ATTACHMENT:
  496. {
  497. mstudioikrule_t_PS3 *pEA_Rule = NULL;
  498. if( pAnim->pEA_animdesc_ikrule )
  499. {
  500. pEA_Rule = (mstudioikrule_t_PS3 *)pAnim->pEA_animdesc_ikrule + iRule;
  501. }
  502. int bResult = Studio_IKAnimationError_PS3( pAnim, pAnimdesc, (void *)pEA_Rule, pRule, flCycle, pos1, q1, w );
  503. if (bResult)
  504. {
  505. ikRule.pos = ikRule.pos + pos1 * pAnim->seqdesc_weight;
  506. QuaternionAccumulate_PS3( ikRule.q, pAnim->seqdesc_weight, q1, ikRule.q );
  507. total += pAnim->seqdesc_weight;
  508. }
  509. }
  510. break;
  511. default:
  512. total += pAnim->seqdesc_weight;
  513. break;
  514. }
  515. ikRule.latched = Studio_IKShouldLatch_PS3( ikRule, flCycle ) * ikRule.flWeight;
  516. if( ikRule.type == IK_ATTACHMENT )
  517. {
  518. // ikRule.szLabel = pRule->pszAttachment();
  519. }
  520. }
  521. }
  522. if( total <= 0.0001f )
  523. {
  524. return false;
  525. }
  526. if( total < 0.999f )
  527. {
  528. VectorScale_PS3( ikRule.pos, 1.0f / total, ikRule.pos );
  529. QuaternionScale_PS3( ikRule.q, 1.0f / total, ikRule.q );
  530. }
  531. if( ikRule.type == IK_SELF && ikRule.bone != -1 )
  532. {
  533. //ikRule.bone = pStudioHdr->RemapSeqBone( iSequence, ikRule.bone );
  534. if( pPoseEntry->pEA_seqgroup_masterBone )
  535. {
  536. int masterbone[6] ALIGN16;
  537. int *pLS_masterbone;
  538. pLS_masterbone = (int *)SPUmemcpy_UnalignedGet( masterbone, (uint32)((int *)pPoseEntry->pEA_seqgroup_masterBone + ikRule.bone), sizeof(int) );
  539. ikRule.bone = *pLS_masterbone;
  540. }
  541. if (ikRule.bone == -1)
  542. return false;
  543. }
  544. QuaternionNormalize_PS3( ikRule.q );
  545. return true;
  546. }
  547. CIKContext_PS3::CIKContext_PS3()
  548. {
  549. m_targetCount = 0;
  550. m_iFramecounter = -1;
  551. m_flTime = -1.0f;
  552. }
  553. void CIKContext_PS3::ClearTargets( void )
  554. {
  555. int i;
  556. for (i = 0; i < m_targetCount; i++)
  557. {
  558. m_target[ i ].latched.iFramecounter = -9999;
  559. }
  560. }
  561. void CIKContext_PS3::Init( bonejob_SPU *pBonejobSPU, const QAngle &angles, const Vector &pos, float flTime, int iFramecounter, int boneMask )
  562. {
  563. SNPROF_ANIM( "CIKContext_PS3::Init" );
  564. // m_pStudioHdr = pStudioHdr;
  565. // m_ikChainRule.RemoveAll(); // m_numikrules = 0;
  566. // if (pStudioHdr->numikchains())
  567. // {
  568. // m_ikChainRule.SetSize( pStudioHdr->numikchains() );
  569. //
  570. // // FIXME: Brutal hackery to prevent a crash
  571. // if (m_target.Count() == 0)
  572. // {
  573. // m_target.SetSize(12);
  574. // memset( m_target.Base(), 0, sizeof(m_target[0])*m_target.Count() );
  575. // ClearTargets();
  576. // }
  577. //
  578. // }
  579. // else
  580. // {
  581. // m_target.SetSize( 0 );
  582. // }
  583. if( pBonejobSPU->numikchains )
  584. {
  585. m_targetCount = 12;
  586. memset( m_target, 0, sizeof( m_target ) );
  587. ClearTargets();
  588. }
  589. else
  590. {
  591. m_targetCount = 0;
  592. }
  593. m_numTarget = 0;
  594. AngleMatrix_PS3( angles, pos, m_rootxform );
  595. m_iFramecounter = iFramecounter;
  596. m_flTime = flTime;
  597. m_boneMask = boneMask;
  598. }
  599. //-----------------------------------------------------------------------------
  600. // Purpose:
  601. //-----------------------------------------------------------------------------
  602. void AddDependencies_SPU( bonejob_SPU *pBonejobSPU, accumposeentry_SPU *pPoseEntry, float flWeight )
  603. {
  604. SNPROF_ANIM("AddDependencies_SPU");
  605. int i;
  606. if( pBonejobSPU->numikchains == 0 )
  607. return;
  608. if( pPoseEntry->seqdesc_numikrules == 0 )
  609. return;
  610. mstudioikchain_t_PS3 ikchain[2] ALIGN16;
  611. int boneIndex[4] ALIGN16;
  612. ikcontextikrule_t_PS3 ikrule;
  613. for( i = 0; i < pPoseEntry->seqdesc_numikrules; i++ )
  614. {
  615. if( !Studio_IKSequenceError_PS3( pPoseEntry, i, pBonejobSPU->poseparam, ikrule ) )
  616. continue;
  617. //int bone = m_pStudioHdr->pIKChain( ikrule.chain )->pLink( 2 )->bone;
  618. mstudioikchain_t_PS3 *pEA_ikchain = (mstudioikchain_t_PS3 *)pBonejobSPU->pEA_studiohdr_ikchains + ikrule.chain;
  619. // get chain
  620. mstudioikchain_t_PS3 *pLS_ikchain = (mstudioikchain_t_PS3 *)SPUmemcpy_UnalignedGet( ikchain, (uint32)pEA_ikchain, sizeof(mstudioikchain_t_PS3) );
  621. // get bone, bone is 1st in mstudioiklink
  622. int *pEA_bone = (int *)pLS_ikchain->pLink( pEA_ikchain, 2 );
  623. int *pbone = (int *)SPUmemcpy_UnalignedGet( boneIndex, (uint32)pEA_bone, sizeof(int) );
  624. // don't add rule if the bone isn't going to be calculated
  625. if( !(pBonejobSPU->boneFlags[ *pbone ] & pBonejobSPU->boneMask) )
  626. continue;
  627. // or if its relative bone isn't going to be calculated
  628. if( ikrule.bone >= 0 && !(pBonejobSPU->boneFlags[ ikrule.bone ] & pBonejobSPU->boneMask) )
  629. continue;
  630. #if !defined( _CERT )
  631. #if defined(__SPU__)
  632. if( g_addDep_numIKRules >= MAX_IKRULES )
  633. {
  634. spu_printf( "numIkRules:%d >= MAX_IKRULES:%d\n", g_addDep_numIKRules, MAX_IKRULES );
  635. __asm volatile ("stopd $0,$0,$0");
  636. }
  637. #else
  638. AssertFatal( g_addDep_numIKRules < MAX_IKRULES );
  639. #endif
  640. #endif // !_CERT
  641. ikrule.flRuleWeight = flWeight;
  642. // rest will be done on PPU, append to list of potential ikrules to add
  643. g_addDep_IKRules[ g_addDep_numIKRules++ ] = ikrule;
  644. }
  645. }
  646. //-----------------------------------------------------------------------------
  647. // Purpose: build boneToWorld transforms for a specific bone
  648. //-----------------------------------------------------------------------------
  649. void CIKContext_PS3::BuildBoneChain(
  650. const bonejob_SPU *pBonejob,
  651. const BoneVector pos[],
  652. const BoneQuaternion q[],
  653. int iBone,
  654. matrix3x4a_t *pBoneToWorld,
  655. CBoneBitList_PS3 &boneComputed )
  656. {
  657. ::BuildBoneChain_PS3( pBonejob->boneParent, m_rootxform, pos, q, iBone, pBoneToWorld, boneComputed );
  658. }
  659. //-----------------------------------------------------------------------------
  660. // Purpose: turn a specific bones boneToWorld transform into a pos and q in parents bonespace
  661. //-----------------------------------------------------------------------------
  662. void SolveBone_PS3(
  663. int *pBoneParent,
  664. int iBone,
  665. matrix3x4a_t *pBoneToWorld,
  666. BoneVector pos[],
  667. BoneQuaternion q[]
  668. )
  669. {
  670. int iParent = pBoneParent[ iBone ];
  671. matrix3x4a_t worldToBone;
  672. MatrixInvert_PS3( pBoneToWorld[iParent], worldToBone );
  673. matrix3x4a_t local;
  674. ConcatTransforms_Aligned_PS3( worldToBone, pBoneToWorld[iBone], local );
  675. MatrixAngles_PS3( local, q[iBone], pos[iBone] );
  676. }
  677. //-----------------------------------------------------------------------------
  678. // Purpose:
  679. //-----------------------------------------------------------------------------
  680. void CIKContext_PS3::AddAutoplayLocks( bonejob_SPU *pBonejob, BoneVector pos[], BoneQuaternion q[] )
  681. {
  682. SNPROF_ANIM("CIKContext_PS3::AddAutoplayLocks");
  683. // skip all array access if no autoplay locks.
  684. if( pBonejob->numikAutoplayLocks == 0 )
  685. {
  686. return;
  687. }
  688. byte ls_iklock[ ROUNDUPTONEXT16B( sizeof(mstudioiklock_t_PS3) ) ] ALIGN16;
  689. byte ls_ikchain[ ROUNDUPTONEXT16B( sizeof(mstudioikchain_t_PS3) ) ] ALIGN16;
  690. byte ls_iklink0[ ROUNDUPTONEXT16B( (sizeof(int) + sizeof(Vector)) ) ] ALIGN16;
  691. byte ls_bone1[ sizeof(int) + 0x10 ] ALIGN16;
  692. byte ls_bone2[ sizeof(int) + 0x10 ] ALIGN16;
  693. matrix3x4a_t *boneToWorld = (matrix3x4a_t *)PushLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  694. CBoneBitList_PS3 boneComputed;
  695. #if !defined( _CERT )
  696. #if defined(__SPU__)
  697. if( pBonejob->numikAutoplayLocks >= MAX_IKLOCKS )
  698. {
  699. spu_printf( "pBonejob->numikAutoplayLocks:%d >= MAX_IKLOCKS:%d\n", pBonejob->numikAutoplayLocks, MAX_IKLOCKS );
  700. __asm volatile ("stopd $0,$0,$0");
  701. }
  702. #else
  703. AssertFatal( pBonejob->numikAutoplayLocks < MAX_IKLOCKS );
  704. #endif
  705. #endif // !_CERT
  706. memset( m_ikLock, 0, sizeof( ikcontextikrule_t_PS3 ) * pBonejob->numikAutoplayLocks );
  707. for( int i = 0; i < pBonejob->numikAutoplayLocks; i++ )
  708. {
  709. mstudioiklock_t_PS3 *pLock = (mstudioiklock_t_PS3 *)SPUmemcpy_UnalignedGet( ls_iklock, (uint32)pBonejob->pEA_IKAutoplayLocks[i], sizeof(mstudioiklock_t_PS3) );
  710. mstudioikchain_t_PS3 *pEA_chain = (mstudioikchain_t_PS3 *)pBonejob->pEA_studiohdr_ikchains + pLock->chain;
  711. mstudioikchain_t_PS3 *pLS_chain = (mstudioikchain_t_PS3 *)SPUmemcpy_UnalignedGet( ls_ikchain, (uint32)pEA_chain, sizeof(mstudioikchain_t_PS3) );
  712. mstudioiklink_t_PS3 *pEA_iklink = pLS_chain->pLink( pEA_chain, 2 );
  713. int *pbone2 = (int *)SPUmemcpy_UnalignedGet( ls_bone2, (uint32)pEA_iklink, sizeof(int) );
  714. int bone = *pbone2;
  715. if( !( pBonejob->boneFlags[ bone ] & m_boneMask ) )
  716. continue;
  717. // eval current ik'd bone
  718. BuildBoneChain( pBonejob, pos, q, bone, boneToWorld, boneComputed );
  719. ikcontextikrule_t_PS3 &ikrule = m_ikLock[ i ];
  720. ikrule.chain = pLock->chain;
  721. ikrule.slot = i;
  722. ikrule.type = IK_WORLD;
  723. MatrixAngles_PS3( boneToWorld[ bone ], ikrule.q, ikrule.pos );
  724. pEA_iklink = pLS_chain->pLink( pEA_chain, 0 );
  725. mstudioiklink_t_PS3 *plink0 = (mstudioiklink_t_PS3 *)SPUmemcpy_UnalignedGet( ls_iklink0, (uint32)pEA_iklink, sizeof(int) + sizeof(Vector) );
  726. // save off current knee direction
  727. if( plink0->kneeDir.LengthSqr() > 0.0f )
  728. {
  729. pEA_iklink = pLS_chain->pLink( pEA_chain, 1 );
  730. int *pbone1 = (int *)SPUmemcpy_UnalignedGet_MustSync( ls_bone1, (uint32)pEA_iklink, sizeof(int), DMATAG_ANIM );
  731. VectorRotate_PS3( plink0->kneeDir, boneToWorld[ plink0->bone ], ikrule.kneeDir );
  732. SPUmemcpy_Sync( 1<<DMATAG_ANIM );
  733. MatrixPosition_PS3( boneToWorld[ *pbone1 ], ikrule.kneePos );
  734. }
  735. else
  736. {
  737. ikrule.kneeDir.Init( );
  738. }
  739. }
  740. PopLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  741. }
  742. //-----------------------------------------------------------------------------
  743. //
  744. //-----------------------------------------------------------------------------
  745. void CIKContext_PS3::AddSequenceLocks( bonejob_SPU *pBonejob, accumposeentry_SPU* pPoseEntry, BoneVector pos[], BoneQuaternion q[] )
  746. {
  747. SNPROF_ANIM("CIKContext_PS3::AddSequenceLocks");
  748. matrix3x4a_t *boneToWorld = (matrix3x4a_t *)PushLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  749. CBoneBitList_PS3 boneComputed;
  750. memset( m_ikLock, 0, sizeof( ikcontextikrule_t_PS3 ) * pPoseEntry->seqdesc_numiklocks );
  751. byte ls_ikchain[ ROUNDUPTONEXT16B( sizeof(mstudioikchain_t_PS3) ) ] ALIGN16;
  752. byte ls_iklink0[ ROUNDUPTONEXT16B( (sizeof(int) + sizeof(Vector)) ) ] ALIGN16;
  753. byte ls_bone2[ sizeof(int) + 0x10 ] ALIGN16;
  754. // fetch all iklocks
  755. byte ls_iklocks[ (ROUNDUPTONEXT16B( sizeof(mstudioiklock_t_PS3) ) * MAX_IKLOCKS) ] ALIGN16;
  756. mstudioiklock_t_PS3 *piklocks = (mstudioiklock_t_PS3 *)SPUmemcpy_UnalignedGet( ls_iklocks, (uint32)pPoseEntry->pEA_seqdesc_iklocks, sizeof(mstudioiklock_t_PS3) * pPoseEntry->seqdesc_numiklocks );
  757. for (int i = 0; i < pPoseEntry->seqdesc_numiklocks; i++)
  758. {
  759. mstudioiklock_t_PS3 *pLock = &piklocks[i]; //seqdesc.pIKLock( i );
  760. mstudioikchain_t_PS3 *pEA_chain = (mstudioikchain_t_PS3 *)pBonejob->pEA_studiohdr_ikchains + pLock->chain;
  761. mstudioikchain_t_PS3 *pLS_chain = (mstudioikchain_t_PS3 *)SPUmemcpy_UnalignedGet( ls_ikchain, (uint32)pEA_chain, sizeof(mstudioikchain_t_PS3) );
  762. mstudioiklink_t_PS3 *pEA_iklink = pLS_chain->pLink( pEA_chain, 2 );
  763. int *pbone = (int *)SPUmemcpy_UnalignedGet( ls_bone2, (uint32)pEA_iklink, sizeof(int) );
  764. int bone = *pbone;//pLS_chain->pLink( pEA_chain, 2 )->bone; //pPoseEntry->ikChains[ i ].bone2;
  765. if( !( pBonejob->boneFlags[ bone ] & m_boneMask ) )
  766. continue;
  767. // eval current ik'd bone
  768. BuildBoneChain( pBonejob, pos, q, bone, boneToWorld, boneComputed );
  769. ikcontextikrule_t_PS3 &ikrule = m_ikLock[ i ];
  770. ikrule.chain = i;
  771. ikrule.slot = i;
  772. ikrule.type = IK_WORLD;
  773. MatrixAngles_PS3( boneToWorld[ bone ], ikrule.q, ikrule.pos );
  774. pEA_iklink = pLS_chain->pLink( pEA_chain, 0 );
  775. mstudioiklink_t_PS3 *plink0 = (mstudioiklink_t_PS3 *)SPUmemcpy_UnalignedGet( ls_iklink0, (uint32)pEA_iklink, sizeof(int) + sizeof(Vector) );
  776. // save off current knee direction
  777. if( plink0->kneeDir.LengthSqr() > 0.0f )
  778. {
  779. VectorRotate_PS3( plink0->kneeDir, boneToWorld[ plink0->bone ], ikrule.kneeDir );
  780. }
  781. else
  782. {
  783. ikrule.kneeDir.Init( );
  784. }
  785. }
  786. PopLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  787. }
  788. //----------------------------------------------------------------------------------------------------------------------------------
  789. // SolveDependencies path for SPU not currently supported, code here for reference
  790. //----------------------------------------------------------------------------------------------------------------------------------
  791. #if 0
  792. matrix3x4a_t g_boneToWorld[ MAXSTUDIOBONES_PS3 ] ALIGN128;
  793. BoneVector g_pos[ MAXSTUDIOBONES_PS3 ] ALIGN128;
  794. BoneQuaternion g_q[ MAXSTUDIOBONES_PS3 ] ALIGN128;
  795. struct posq
  796. {
  797. Vector pos;
  798. Quaternion q;
  799. };
  800. void RunSolveDependenciesJob_SPU( bonejob_SPU_2 *pBonejob2 )
  801. {
  802. }
  803. void RunSolveDependenciesJob_PPU( bonejob_SPU_2 *pBonejob2 )
  804. {
  805. SNPROF_ANIM("RunSolveDependenciesJob_PPU");
  806. BoneVector *pos = (BoneVector *)pBonejob2->pEA_pos;
  807. BoneQuaternion *q = (BoneQuaternion *)pBonejob2->pEA_q;
  808. matrix3x4a_t *boneToWorld = (matrix3x4a_t *)pBonejob2->pEA_bones;
  809. CBoneBitList_PS3 boneComputed;
  810. // src
  811. memcpy( g_pos, pos, sizeof(BoneVector) * pBonejob2->studiohdr_numbones );
  812. memcpy( g_q, q, sizeof(BoneQuaternion) * pBonejob2->studiohdr_numbones );
  813. memcpy( &boneComputed.m_markedBones, pBonejob2->pEA_boneComputed, sizeof(byte) * pBonejob2->studiohdr_numbones );
  814. // just copy all bones for now, dma list later
  815. //memcpy( g_boneToWorld, boneToWorld, sizeof(matrix3x4a_t) * pBonejob2->studiohdr_numbones );
  816. int lp;
  817. // copy matrices that are up to date
  818. for( lp = 0; lp < pBonejob2->studiohdr_numbones; lp++ )
  819. {
  820. if( boneComputed.IsBoneMarked(lp) )
  821. {
  822. memcpy( &g_boneToWorld[lp], &boneToWorld[lp], sizeof(matrix3x4a_t) );
  823. }
  824. }
  825. SolveDependencies_SPU( pBonejob2, boneComputed );
  826. // copy results back (boneToWorld and boneComputed)
  827. memcpy( pBonejob2->pEA_boneComputed, &boneComputed.m_markedBones, sizeof(byte) * pBonejob2->studiohdr_numbones );
  828. // build dma list to only copy computed matrices
  829. for( lp = 0; lp < pBonejob2->studiohdr_numbones; lp++ )
  830. {
  831. if( boneComputed.IsBoneMarked(lp) )
  832. {
  833. memcpy( &boneToWorld[lp], &g_boneToWorld[lp], sizeof(matrix3x4a_t) );
  834. }
  835. }
  836. }
  837. void SolveDependencies_SPU( bonejob_SPU_2 *pBonejob2, CBoneBitList_PS3 &boneComputed )
  838. {
  839. SNPROF_ANIM( "SolveDependencies_SPU" );
  840. matrix3x4a_t worldTarget;
  841. int i, j;
  842. ikchainresult_t_PS3 chainResult[32];
  843. // assume all these structures contain valid data
  844. matrix3x4a_t *boneToWorld = g_boneToWorld;
  845. BoneVector *pos = g_pos;
  846. BoneQuaternion *q = g_q;
  847. // init chain rules
  848. for( i = 0; i < pBonejob2->studiohdr_numikchains; i++ )
  849. {
  850. int bone = pBonejob2->ikChains[ i ].bone2;
  851. ikchainresult_t_PS3 *pChainResult = &chainResult[ i ];
  852. pChainResult->target = -1;
  853. pChainResult->flWeight = 0.0f;
  854. // don't bother with chain if the bone isn't going to be calculated
  855. if( bone == -1 )
  856. continue;
  857. // eval current ik'd bone
  858. BuildBoneChain_PS3( pBonejob2->boneParent, pBonejob2->rootxform, pos, q, bone, boneToWorld, boneComputed );
  859. MatrixAngles_PS3( boneToWorld[bone], pChainResult->q, pChainResult->pos );
  860. }
  861. ikcontextikrule_t_PS3 ikrule[2] ALIGN16;
  862. for( i = 0; i < pBonejob2->numikchainElements; i++ )
  863. {
  864. void *pEA_Rule = pBonejob2->ikchainElement_rules[ i ];
  865. ikcontextikrule_t_PS3 *pRule = (ikcontextikrule_t_PS3 *)SPUmemcpy_UnalignedGet( ikrule, (uint32)pEA_Rule, sizeof(ikcontextikrule_t_PS3) );
  866. ikchainresult_t_PS3 *pChainResult = &chainResult[ pRule->chain ];
  867. pChainResult->target = -1;
  868. switch( pRule->type )
  869. {
  870. case IK_SELF:
  871. {
  872. // xform IK target error into world space
  873. matrix3x4a_t local;
  874. QuaternionMatrix_PS3( pRule->q, pRule->pos, local );
  875. // eval target bone space
  876. if (pRule->bone != -1)
  877. {
  878. BuildBoneChain_PS3( pBonejob2->boneParent, pBonejob2->rootxform, pos, q, pRule->bone, boneToWorld, boneComputed );
  879. ConcatTransforms_Aligned_PS3( boneToWorld[pRule->bone], local, worldTarget );
  880. }
  881. else
  882. {
  883. ConcatTransforms_Aligned_PS3( pBonejob2->rootxform, local, worldTarget );
  884. }
  885. float flWeight = pRule->flWeight * pRule->flRuleWeight;
  886. pChainResult->flWeight = pChainResult->flWeight * (1.0f - flWeight) + flWeight;
  887. BoneVector p2;
  888. BoneQuaternion q2;
  889. // target p and q
  890. MatrixAngles_PS3( worldTarget, q2, p2 );
  891. // debugLine( pChainResult->pos, p2, 0, 0, 255, true, 0.1 );
  892. // blend in position and angles
  893. pChainResult->pos = pChainResult->pos * (1.0f - flWeight) + p2 * flWeight;
  894. QuaternionSlerp_PS3( pChainResult->q, q2, flWeight, pChainResult->q );
  895. }
  896. break;
  897. case IK_RELEASE:
  898. {
  899. // move target back towards original location
  900. float flWeight = pRule->flWeight * pRule->flRuleWeight;
  901. int bone = pBonejob2->ikchainElement_bones[ i ];
  902. Vector p2;
  903. Quaternion q2;
  904. BuildBoneChain_PS3( pBonejob2->boneParent, pBonejob2->rootxform, pos, q, bone, boneToWorld, boneComputed );
  905. MatrixAngles_PS3( boneToWorld[bone], q2, p2 );
  906. // blend in position and angles
  907. pChainResult->pos = pChainResult->pos * (1.0f - flWeight) + p2 * flWeight;
  908. QuaternionSlerp_PS3( pChainResult->q, q2, flWeight, pChainResult->q );
  909. }
  910. break;
  911. default:
  912. break;
  913. }
  914. }
  915. CIKTarget_PS3 target[2] ALIGN16;
  916. for (i = 0; i < pBonejob2->iktargetcount; i++)
  917. {
  918. void *pEA_Target = pBonejob2->iktargets[ i ];
  919. CIKTarget_PS3 *pTarget = (CIKTarget_PS3 *)SPUmemcpy_UnalignedGet( target, (uint32)pEA_Target, sizeof(CIKTarget_PS3) );
  920. if( pTarget->est.flWeight > 0.0f )
  921. {
  922. matrix3x4a_t worldFootpad;
  923. matrix3x4a_t local;
  924. //mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( m_target[i].chain );
  925. ikchainresult_t_PS3 *pChainResult = &chainResult[ pTarget->chain ];
  926. AngleMatrix_PS3(pTarget->offset.q, pTarget->offset.pos, local );
  927. AngleMatrix_PS3( pTarget->est.q, pTarget->est.pos, worldFootpad );
  928. ConcatTransforms_Aligned_PS3( worldFootpad, local, worldTarget );
  929. BoneVector p2;
  930. BoneQuaternion q2;
  931. // target p and q
  932. MatrixAngles_PS3( worldTarget, q2, p2 );
  933. // MatrixAngles( worldTarget, pChainResult->q, pChainResult->pos );
  934. // blend in position and angles
  935. pChainResult->flWeight = pTarget->est.flWeight;
  936. pChainResult->pos = pChainResult->pos * (1.0f - pChainResult->flWeight ) + p2 * pChainResult->flWeight;
  937. QuaternionSlerp_PS3( pChainResult->q, q2, pChainResult->flWeight, pChainResult->q );
  938. }
  939. if( pTarget->latched.bNeedsLatch )
  940. {
  941. // keep track of latch position
  942. pTarget->latched.bHasLatch = true;
  943. pTarget->latched.q = pTarget->est.q;
  944. pTarget->latched.pos = pTarget->est.pos;
  945. }
  946. }
  947. for (i = 0; i < pBonejob2->studiohdr_numikchains; i++)
  948. {
  949. ikchainresult_t_PS3 *pChainResult = &chainResult[ i ];
  950. ikChain_SPU *pchain = &pBonejob2->ikChains[ i ];
  951. if( pChainResult->flWeight > 0.0f )
  952. {
  953. Vector tmp;
  954. MatrixPosition_PS3( boneToWorld[ pchain->bone2 ], tmp );
  955. // do exact IK solution
  956. // FIXME: once per link!
  957. if( Studio_SolveIK_PS3( pchain, pChainResult->pos, boneToWorld ) )
  958. {
  959. Vector p3;
  960. MatrixGetColumn_PS3( boneToWorld[ pchain->bone2 ], 3, p3 );
  961. QuaternionMatrix_PS3( pChainResult->q, p3, boneToWorld[ pchain->bone2 ] );
  962. // rebuild chain
  963. // FIXME: is this needed if everyone past this uses the boneToWorld array?
  964. SolveBone_PS3( pBonejob2->boneParent, pchain->bone2, boneToWorld, pos, q );
  965. SolveBone_PS3( pBonejob2->boneParent, pchain->bone1, boneToWorld, pos, q );
  966. SolveBone_PS3( pBonejob2->boneParent, pchain->bone0, boneToWorld, pos, q );
  967. }
  968. else
  969. {
  970. // FIXME: need to invalidate the targets that forced this...
  971. if( pChainResult->target != -1 )
  972. {
  973. byte *pEA_Target = (byte *)pBonejob2->iktargets[ pChainResult->target ];
  974. // only really need to get deltaPos, deltaQ
  975. posq deltaPosQ[ 2 ] ALIGN16;
  976. int offset_deltaPosQ = uint32(&target[0].latched.deltaPos) - uint32(&target[0]);
  977. posq *pTarget_deltaPosQ;
  978. pTarget_deltaPosQ = (posq *)SPUmemcpy_UnalignedGet( deltaPosQ, (uint32)(pEA_Target + offset_deltaPosQ), sizeof( posq ) );
  979. VectorScale_PS3( pTarget_deltaPosQ->pos, 0.8f, pTarget_deltaPosQ->pos );
  980. QuaternionScale_PS3( pTarget_deltaPosQ->q, 0.8f, pTarget_deltaPosQ->q );
  981. // only really need to push back deltaPos, deltaQ
  982. SPUmemcpy_UnalignedPut( pTarget_deltaPosQ, (uint32)(pEA_Target + offset_deltaPosQ), sizeof( posq ) );
  983. }
  984. }
  985. }
  986. }
  987. }
  988. #endif
  989. //-----------------------------------------------------------------------------
  990. // Purpose:
  991. //-----------------------------------------------------------------------------
  992. void CIKContext_PS3::SolveAutoplayLocks(
  993. bonejob_SPU *pBonejob,
  994. BoneVector pos[],
  995. BoneQuaternion q[]
  996. )
  997. {
  998. SNPROF_ANIM("CIKContext_PS3::SolveAutoplayLocks");
  999. matrix3x4a_t *boneToWorld = (matrix3x4a_t *)PushLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  1000. CBoneBitList_PS3 boneComputed;
  1001. int i;
  1002. byte ls_iklock[ ROUNDUPTONEXT16B( sizeof(mstudioiklock_t_PS3) ) ] ALIGN16;
  1003. for( i = 0; i < pBonejob->numikAutoplayLocks; i++ )
  1004. {
  1005. mstudioiklock_t_PS3 *pLock = (mstudioiklock_t_PS3 *)SPUmemcpy_UnalignedGet( ls_iklock, (uint32)pBonejob->pEA_IKAutoplayLocks[i], sizeof(mstudioiklock_t_PS3) );
  1006. SolveLock( pBonejob, pLock, i, pos, q, boneToWorld, boneComputed );
  1007. }
  1008. PopLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  1009. }
  1010. //-----------------------------------------------------------------------------
  1011. //
  1012. //-----------------------------------------------------------------------------
  1013. void CIKContext_PS3::SolveSequenceLocks(
  1014. bonejob_SPU *pBonejob,
  1015. accumposeentry_SPU* pPoseEntry,
  1016. BoneVector pos[],
  1017. BoneQuaternion q[]
  1018. )
  1019. {
  1020. SNPROF_ANIM("CIKContext_PS3::SolveSequenceLocks");
  1021. matrix3x4a_t *boneToWorld = (matrix3x4a_t *)PushLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  1022. CBoneBitList_PS3 boneComputed;
  1023. int i;
  1024. // fetch all iklocks
  1025. byte ls_iklocks[ (ROUNDUPTONEXT16B(sizeof(mstudioiklock_t_PS3)) * MAX_IKLOCKS) ] ALIGN16;
  1026. mstudioiklock_t_PS3 *piklocks = (mstudioiklock_t_PS3 *)SPUmemcpy_UnalignedGet( ls_iklocks, (uint32)pPoseEntry->pEA_seqdesc_iklocks, sizeof(mstudioiklock_t_PS3) * pPoseEntry->seqdesc_numiklocks );
  1027. for( i = 0; i < pPoseEntry->seqdesc_numiklocks; i++ )
  1028. {
  1029. //mstudioiklock_t_PS3 *pLock = &pPoseEntry->ikLocks[ i ];
  1030. mstudioiklock_t_PS3 *pLock = &piklocks[i];
  1031. SolveLock( pBonejob, pLock, i, pos, q, boneToWorld, boneComputed );
  1032. }
  1033. PopLSStack( sizeof(matrix3x4a_t) * pBonejob->maxBones );
  1034. }
  1035. //-----------------------------------------------------------------------------
  1036. // Purpose:
  1037. //-----------------------------------------------------------------------------
  1038. void CIKContext_PS3::SolveLock(
  1039. bonejob_SPU *pBonejob,
  1040. const mstudioiklock_t_PS3 *pLock,
  1041. int i,
  1042. BoneVector pos[],
  1043. BoneQuaternion q[],
  1044. matrix3x4a_t boneToWorld[],
  1045. CBoneBitList_PS3 &boneComputed
  1046. )
  1047. {
  1048. byte ls_ikchain[ ROUNDUPTONEXT16B(sizeof(mstudioikchain_t_PS3)) ] ALIGN16;
  1049. byte ls_iklink0[ ROUNDUPTONEXT16B( (sizeof(int) + sizeof(Vector)) ) ] ALIGN16;
  1050. byte ls_bone1[ sizeof(int) + 0x10 ] ALIGN16;
  1051. byte ls_bone2[ sizeof(int) + 0x10 ] ALIGN16;
  1052. mstudioikchain_t_PS3 *pEA_chain = (mstudioikchain_t_PS3 *)pBonejob->pEA_studiohdr_ikchains + pLock->chain;
  1053. mstudioikchain_t_PS3 *pLS_chain = (mstudioikchain_t_PS3 *)SPUmemcpy_UnalignedGet( ls_ikchain, (uint32)pEA_chain, sizeof(mstudioikchain_t_PS3) );
  1054. mstudioiklink_t_PS3 *pEA_iklink0 = pLS_chain->pLink( pEA_chain, 0 );
  1055. mstudioiklink_t_PS3 *pEA_iklink1 = pLS_chain->pLink( pEA_chain, 1 );
  1056. mstudioiklink_t_PS3 *pEA_iklink2 = pLS_chain->pLink( pEA_chain, 2 );
  1057. mstudioiklink_t_PS3 *plink0 = (mstudioiklink_t_PS3 *)SPUmemcpy_UnalignedGet_MustSync( ls_iklink0, (uint32)pEA_iklink0, sizeof(int) + sizeof(Vector), DMATAG_ANIM );
  1058. int *pbone1 = (int *)SPUmemcpy_UnalignedGet_MustSync( ls_bone1, (uint32)pEA_iklink1, sizeof(int), DMATAG_ANIM );
  1059. int *pbone2 = (int *)SPUmemcpy_UnalignedGet( ls_bone2, (uint32)pEA_iklink2, sizeof(int) );
  1060. int bone = *pbone2;//pChain->bone2;
  1061. // don't bother with iklock if the bone isn't going to be calculated
  1062. if( !( pBonejob->boneFlags[ bone ] & m_boneMask ) )
  1063. {
  1064. SPUmemcpy_Sync( 1<<DMATAG_ANIM );
  1065. return;
  1066. }
  1067. // eval current ik'd bone
  1068. BuildBoneChain( pBonejob, pos, q, bone, boneToWorld, boneComputed );
  1069. BoneVector p1, p2, p3;
  1070. BoneQuaternion q2, q3;
  1071. // current p and q
  1072. MatrixPosition_PS3( boneToWorld[ bone ], p1 );
  1073. // blend in position
  1074. p3 = p1 * (1.0f - pLock->flPosWeight ) + m_ikLock[ i ].pos * pLock->flPosWeight;
  1075. SPUmemcpy_Sync( 1<<DMATAG_ANIM );
  1076. // do exact IK solution
  1077. if( m_ikLock[ i ].kneeDir.LengthSqr() > 0.0f )
  1078. {
  1079. Studio_SolveIK_PS3( plink0->bone, *pbone1, *pbone2, p3, m_ikLock[ i ].kneePos, m_ikLock[ i ].kneeDir, boneToWorld );
  1080. }
  1081. else
  1082. {
  1083. Studio_SolveIK_PS3( plink0->kneeDir, plink0->bone, *pbone1, *pbone2, p3, boneToWorld );
  1084. }
  1085. // slam orientation
  1086. MatrixPosition_PS3( boneToWorld[ bone ], p3 );
  1087. QuaternionMatrix_PS3( m_ikLock[ i ].q, p3, boneToWorld[ bone ] );
  1088. // rebuild chain
  1089. q2 = q[ bone ];
  1090. SolveBone_PS3( pBonejob->boneParent, *pbone2, boneToWorld, pos, q );
  1091. QuaternionSlerp_PS3( q[ bone ], q2, pLock->flLocalQWeight, q[ bone ] );
  1092. SolveBone_PS3( pBonejob->boneParent, *pbone1, boneToWorld, pos, q );
  1093. SolveBone_PS3( pBonejob->boneParent, plink0->bone, boneToWorld, pos, q );
  1094. }
  1095. #define KNEEMAX_EPSILON (0.9998f) // (0.9998 is about 1 degree)
  1096. //-----------------------------------------------------------------------------
  1097. // Purpose: Solve Knee position for a known hip and foot location, but no specific knee direction preference
  1098. //-----------------------------------------------------------------------------
  1099. bool Studio_SolveIK_PS3( int8 iThigh, int8 iKnee, int8 iFoot, Vector &targetFoot, matrix3x4a_t *pBoneToWorld )
  1100. {
  1101. Vector worldFoot, worldKnee, worldThigh;
  1102. MatrixPosition_PS3( pBoneToWorld[ iThigh ], worldThigh );
  1103. MatrixPosition_PS3( pBoneToWorld[ iKnee ], worldKnee );
  1104. MatrixPosition_PS3( pBoneToWorld[ iFoot ], worldFoot );
  1105. Vector ikFoot, ikKnee;
  1106. ikFoot = targetFoot - worldThigh;
  1107. ikKnee = worldKnee - worldThigh;
  1108. float l1 = (worldKnee - worldThigh).Length();
  1109. float l2 = (worldFoot - worldKnee).Length();
  1110. float l3 = (worldFoot - worldThigh).Length();
  1111. // leg too straight to figure out knee?
  1112. if( l3 > (l1 + l2) * KNEEMAX_EPSILON )
  1113. {
  1114. return false;
  1115. }
  1116. Vector ikHalf;
  1117. ikHalf = (worldFoot - worldThigh) * (l1 / l3);
  1118. // FIXME: what to do when the knee completely straight?
  1119. Vector ikKneeDir;
  1120. ikKneeDir = ikKnee - ikHalf;
  1121. VectorNormalize_PS3( ikKneeDir );
  1122. return Studio_SolveIK_PS3( iThigh, iKnee, iFoot, targetFoot, worldKnee, ikKneeDir, pBoneToWorld );
  1123. }
  1124. //-----------------------------------------------------------------------------
  1125. // Purpose: Realign the matrix so that its X axis points along the desired axis.
  1126. //-----------------------------------------------------------------------------
  1127. void Studio_AlignIKMatrix_PS3( matrix3x4a_t &mMat, const Vector &vAlignTo )
  1128. {
  1129. Vector tmp1, tmp2, tmp3;
  1130. // Column 0 (X) becomes the vector.
  1131. tmp1 = vAlignTo;
  1132. VectorNormalize_PS3( tmp1 );
  1133. MatrixSetColumn_PS3( tmp1, 0, mMat );
  1134. // Column 1 (Y) is the cross of the vector and column 2 (Z).
  1135. MatrixGetColumn_PS3( mMat, 2, tmp3 );
  1136. tmp2 = tmp3.Cross( tmp1 );
  1137. VectorNormalize_PS3( tmp2 );
  1138. // FIXME: check for X being too near to Z
  1139. MatrixSetColumn_PS3( tmp2, 1, mMat );
  1140. // Column 2 (Z) is the cross of columns 0 (X) and 1 (Y).
  1141. tmp3 = tmp1.Cross( tmp2 );
  1142. MatrixSetColumn_PS3( tmp3, 2, mMat );
  1143. }
  1144. //-----------------------------------------------------------------------------
  1145. // Purpose: Solve Knee position for a known hip and foot location, and a known knee direction
  1146. //-----------------------------------------------------------------------------
  1147. bool Studio_SolveIK_PS3( int8 iThigh, int8 iKnee, int8 iFoot, Vector &targetFoot, Vector &targetKneePos, Vector &targetKneeDir, matrix3x4a_t *pBoneToWorld )
  1148. {
  1149. Vector worldFoot, worldKnee, worldThigh;
  1150. MatrixPosition_PS3( pBoneToWorld[ iThigh ], worldThigh );
  1151. MatrixPosition_PS3( pBoneToWorld[ iKnee ], worldKnee );
  1152. MatrixPosition_PS3( pBoneToWorld[ iFoot ], worldFoot );
  1153. Vector ikFoot, ikTargetKnee, ikKnee;
  1154. ikFoot = targetFoot - worldThigh;
  1155. ikKnee = targetKneePos - worldThigh;
  1156. float l1 = (worldKnee - worldThigh).Length();
  1157. float l2 = (worldFoot - worldKnee).Length();
  1158. // exaggerate knee targets for legs that are nearly straight
  1159. // FIXME: should be configurable, and the ikKnee should be from the original animation, not modifed
  1160. float d = (targetFoot-worldThigh).Length() - MIN( l1, l2 );
  1161. d = MAX( l1 + l2, d );
  1162. // FIXME: too short knee directions cause trouble
  1163. d = d * 100.0f;
  1164. ikTargetKnee = ikKnee + targetKneeDir * d;
  1165. // too far away? (0.9998 is about 1 degree)
  1166. if( ikFoot.Length() > (l1 + l2) * KNEEMAX_EPSILON )
  1167. {
  1168. VectorNormalize_PS3( ikFoot );
  1169. VectorScale_PS3( ikFoot, (l1 + l2) * KNEEMAX_EPSILON, ikFoot );
  1170. }
  1171. // too close?
  1172. // limit distance to about an 80 degree knee bend
  1173. float minDist = MAX( fabs(l1 - l2) * 1.15, MIN( l1, l2 ) * 0.15f );
  1174. if( ikFoot.Length() < minDist )
  1175. {
  1176. // too close to get an accurate vector, just use original vector
  1177. ikFoot = (worldFoot - worldThigh);
  1178. VectorNormalize_PS3( ikFoot );
  1179. VectorScale_PS3( ikFoot, minDist, ikFoot );
  1180. }
  1181. CIKSolver_PS3 ik;
  1182. if( ik.solve( l1, l2, ikFoot.Base(), ikTargetKnee.Base(), ikKnee.Base() ) )
  1183. {
  1184. matrix3x4a_t& mWorldThigh = pBoneToWorld[ iThigh ];
  1185. matrix3x4a_t& mWorldKnee = pBoneToWorld[ iKnee ];
  1186. matrix3x4a_t& mWorldFoot = pBoneToWorld[ iFoot ];
  1187. // build transformation matrix for thigh
  1188. Studio_AlignIKMatrix_PS3( mWorldThigh, ikKnee );
  1189. VectorAligned kneeToFoot;
  1190. kneeToFoot = ikFoot - ikKnee;
  1191. Studio_AlignIKMatrix_PS3( mWorldKnee, kneeToFoot );
  1192. mWorldKnee[0][3] = ikKnee.x + worldThigh.x;
  1193. mWorldKnee[1][3] = ikKnee.y + worldThigh.y;
  1194. mWorldKnee[2][3] = ikKnee.z + worldThigh.z;
  1195. mWorldFoot[0][3] = ikFoot.x + worldThigh.x;
  1196. mWorldFoot[1][3] = ikFoot.y + worldThigh.y;
  1197. mWorldFoot[2][3] = ikFoot.z + worldThigh.z;
  1198. return true;
  1199. }
  1200. else
  1201. {
  1202. return false;
  1203. }
  1204. }