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.

2225 lines
63 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include "tier0/dbg.h"
  9. #include "mathlib/mathlib.h"
  10. #include "bone_setup.h"
  11. #if defined( _PS3 )
  12. #include "bone_setup_PS3.h"
  13. #endif
  14. #include <string.h>
  15. #include "collisionutils.h"
  16. #include "vstdlib/random.h"
  17. #include "tier0/vprof.h"
  18. #include "bone_accessor.h"
  19. #include "mathlib/ssequaternion.h"
  20. #include "bitvec.h"
  21. #include "datamanager.h"
  22. #include "convar.h"
  23. #include "tier0/tslist.h"
  24. #include "vphysics_interface.h"
  25. #include "datacache/idatacache.h"
  26. #include "tier0/miniprofiler.h"
  27. #include "bone_utils.h"
  28. // memdbgon must be the last include file in a .cpp file!!!
  29. #include "tier0/memdbgon.h"
  30. class CIKSolver
  31. {
  32. public:
  33. //-------- SOLVE TWO LINK INVERSE KINEMATICS -------------
  34. // Author: Ken Perlin
  35. //
  36. // Given a two link joint from [0,0,0] to end effector position P,
  37. // let link lengths be a and b, and let norm |P| = c. Clearly a+b <= c.
  38. //
  39. // Problem: find a "knee" position Q such that |Q| = a and |P-Q| = b.
  40. //
  41. // In the case of a point on the x axis R = [c,0,0], there is a
  42. // closed form solution S = [d,e,0], where |S| = a and |R-S| = b:
  43. //
  44. // d2+e2 = a2 -- because |S| = a
  45. // (c-d)2+e2 = b2 -- because |R-S| = b
  46. //
  47. // c2-2cd+d2+e2 = b2 -- combine the two equations
  48. // c2-2cd = b2 - a2
  49. // c-2d = (b2-a2)/c
  50. // d - c/2 = (a2-b2)/c / 2
  51. //
  52. // d = (c + (a2-b2/c) / 2 -- to solve for d and e.
  53. // e = sqrt(a2-d2)
  54. static float findD(float a, float b, float c) {
  55. return (c + (a*a-b*b)/c) / 2;
  56. }
  57. static float findE(float a, float d) { return sqrt(a*a-d*d); }
  58. // This leads to a solution to the more general problem:
  59. //
  60. // (1) R = Mfwd(P) -- rotate P onto the x axis
  61. // (2) Solve for S
  62. // (3) Q = Minv(S) -- rotate back again
  63. float Mfwd[3][3];
  64. float Minv[3][3];
  65. bool solve(float A, float B, float const P[], float const D[], float Q[]) {
  66. float R[3];
  67. defineM(P,D);
  68. rot(Minv,P,R);
  69. float r = length(R);
  70. float d = findD(A,B,r);
  71. float e = findE(A,d);
  72. float S[3] = {d,e,0};
  73. rot(Mfwd,S,Q);
  74. return d > (r - B) && d < A;
  75. }
  76. // If "knee" position Q needs to be as close as possible to some point D,
  77. // then choose M such that M(D) is in the y>0 half of the z=0 plane.
  78. //
  79. // Given that constraint, define the forward and inverse of M as follows:
  80. void defineM(float const P[], float const D[]) {
  81. float *X = Minv[0], *Y = Minv[1], *Z = Minv[2];
  82. // Minv defines a coordinate system whose x axis contains P, so X = unit(P).
  83. int i;
  84. for (i = 0 ; i < 3 ; i++)
  85. X[i] = P[i];
  86. normalize(X);
  87. // Its y axis is perpendicular to P, so Y = unit( E - X(E�X) ).
  88. float dDOTx = dot(D,X);
  89. for (i = 0 ; i < 3 ; i++)
  90. Y[i] = D[i] - dDOTx * X[i];
  91. normalize(Y);
  92. // Its z axis is perpendicular to both X and Y, so Z = X�Y.
  93. cross(X,Y,Z);
  94. // Mfwd = (Minv)T, since transposing inverts a rotation matrix.
  95. for (i = 0 ; i < 3 ; i++) {
  96. Mfwd[i][0] = Minv[0][i];
  97. Mfwd[i][1] = Minv[1][i];
  98. Mfwd[i][2] = Minv[2][i];
  99. }
  100. }
  101. //------------ GENERAL VECTOR MATH SUPPORT -----------
  102. static float dot(float const a[], float const b[]) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
  103. static float length(float const v[]) { return sqrt( dot(v,v) ); }
  104. static void normalize(float v[]) {
  105. float norm = length(v);
  106. for (int i = 0 ; i < 3 ; i++)
  107. v[i] /= norm;
  108. }
  109. static void cross(float const a[], float const b[], float c[]) {
  110. c[0] = a[1] * b[2] - a[2] * b[1];
  111. c[1] = a[2] * b[0] - a[0] * b[2];
  112. c[2] = a[0] * b[1] - a[1] * b[0];
  113. }
  114. static void rot(float const M[3][3], float const src[], float dst[]) {
  115. for (int i = 0 ; i < 3 ; i++)
  116. dst[i] = dot(M[i],src);
  117. }
  118. };
  119. //-----------------------------------------------------------------------------
  120. // Purpose: visual debugging code
  121. //-----------------------------------------------------------------------------
  122. #if 1
  123. inline void debugLine(const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest, float duration) { };
  124. #else
  125. extern void drawLine( const Vector &p1, const Vector &p2, int r = 0, int g = 0, int b = 1, bool noDepthTest = true, float duration = 0.1 );
  126. void debugLine(const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest, float duration)
  127. {
  128. drawLine( origin, dest, r, g, b, noDepthTest, duration );
  129. }
  130. #endif
  131. //-----------------------------------------------------------------------------
  132. // Purpose: for a 2 bone chain, find the IK solution and reset the matrices
  133. //-----------------------------------------------------------------------------
  134. bool Studio_SolveIK( mstudioikchain_t *pikchain, Vector &targetFoot, matrix3x4a_t *pBoneToWorld )
  135. {
  136. #if 0
  137. // FIXME: something with the CS models breaks this, why?
  138. if (pikchain->pLink(0)->kneeDir.LengthSqr() > 0.0)
  139. {
  140. Vector targetKneeDir, targetKneePos;
  141. // FIXME: knee length should be as long as the legs
  142. Vector tmp = pikchain->pLink( 0 )->kneeDir;
  143. VectorRotate( tmp, pBoneToWorld[ pikchain->pLink( 0 )->bone ], targetKneeDir );
  144. MatrixPosition( pBoneToWorld[ pikchain->pLink( 1 )->bone ], targetKneePos );
  145. return Studio_SolveIK( pikchain->pLink( 0 )->bone, pikchain->pLink( 1 )->bone, pikchain->pLink( 2 )->bone, targetFoot, targetKneePos, targetKneeDir, pBoneToWorld );
  146. }
  147. else
  148. #endif
  149. {
  150. return Studio_SolveIK( pikchain->pLink( 0 )->bone, pikchain->pLink( 1 )->bone, pikchain->pLink( 2 )->bone, targetFoot, pBoneToWorld );
  151. }
  152. }
  153. #define KNEEMAX_EPSILON 0.9998 // (0.9998 is about 1 degree)
  154. //-----------------------------------------------------------------------------
  155. // Purpose: Solve Knee position for a known hip and foot location, but no specific knee direction preference
  156. //-----------------------------------------------------------------------------
  157. bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, matrix3x4a_t *pBoneToWorld )
  158. {
  159. BONE_PROFILE_FUNC();
  160. Vector worldFoot, worldKnee, worldThigh;
  161. MatrixPosition( pBoneToWorld[ iThigh ], worldThigh );
  162. MatrixPosition( pBoneToWorld[ iKnee ], worldKnee );
  163. MatrixPosition( pBoneToWorld[ iFoot ], worldFoot );
  164. //debugLine( worldThigh, worldKnee, 0, 0, 255, true, 0 );
  165. //debugLine( worldKnee, worldFoot, 0, 0, 255, true, 0 );
  166. Vector ikFoot, ikKnee;
  167. ikFoot = targetFoot - worldThigh;
  168. ikKnee = worldKnee - worldThigh;
  169. float l1 = (worldKnee-worldThigh).Length();
  170. float l2 = (worldFoot-worldKnee).Length();
  171. float l3 = (worldFoot-worldThigh).Length();
  172. // leg too straight to figure out knee?
  173. if (l3 > (l1 + l2) * KNEEMAX_EPSILON)
  174. {
  175. return false;
  176. }
  177. // If any of the thigh to knee to foot bones are co-positional, then solving ik doesn't make sense.
  178. // We're probably looking at uninitialized bones or something
  179. if ( l1 <= 0 || l2 <= 0 || l3 <= 0 )
  180. {
  181. return false;
  182. }
  183. Vector ikHalf = (worldFoot-worldThigh) * (l1 / l3);
  184. // FIXME: what to do when the knee completely straight?
  185. Vector ikKneeDir = ikKnee - ikHalf;
  186. VectorNormalize( ikKneeDir );
  187. return Studio_SolveIK( iThigh, iKnee, iFoot, targetFoot, worldKnee, ikKneeDir, pBoneToWorld );
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Purpose: Realign the matrix so that its X axis points along the desired axis.
  191. //-----------------------------------------------------------------------------
  192. void Studio_AlignIKMatrix( matrix3x4a_t &mMat, const Vector &vAlignTo )
  193. {
  194. BONE_PROFILE_FUNC();
  195. Vector tmp1, tmp2, tmp3;
  196. // Column 0 (X) becomes the vector.
  197. tmp1 = vAlignTo;
  198. VectorNormalize( tmp1 );
  199. MatrixSetColumn( tmp1, 0, mMat );
  200. // Column 1 (Y) is the cross of the vector and column 2 (Z).
  201. MatrixGetColumn( mMat, 2, tmp3 );
  202. tmp2 = tmp3.Cross( tmp1 );
  203. VectorNormalize( tmp2 );
  204. // FIXME: check for X being too near to Z
  205. MatrixSetColumn( tmp2, 1, mMat );
  206. // Column 2 (Z) is the cross of columns 0 (X) and 1 (Y).
  207. tmp3 = tmp1.Cross( tmp2 );
  208. MatrixSetColumn( tmp3, 2, mMat );
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose: Solve Knee position for a known hip and foot location, and a known knee direction
  212. //-----------------------------------------------------------------------------
  213. bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, Vector &targetKneePos, Vector &targetKneeDir, matrix3x4a_t *pBoneToWorld )
  214. {
  215. BONE_PROFILE_FUNC();
  216. Vector worldFoot, worldKnee, worldThigh;
  217. MatrixPosition( pBoneToWorld[ iThigh ], worldThigh );
  218. MatrixPosition( pBoneToWorld[ iKnee ], worldKnee );
  219. MatrixPosition( pBoneToWorld[ iFoot ], worldFoot );
  220. //debugLine( worldThigh, worldKnee, 0, 0, 255, true, 0 );
  221. //debugLine( worldThigh, worldThigh + targetKneeDir, 0, 0, 255, true, 0 );
  222. // debugLine( worldKnee, targetKnee, 0, 0, 255, true, 0 );
  223. Vector ikFoot, ikTargetKnee, ikKnee;
  224. ikFoot = targetFoot - worldThigh;
  225. ikKnee = targetKneePos - worldThigh;
  226. float l1 = (worldKnee-worldThigh).Length();
  227. float l2 = (worldFoot-worldKnee).Length();
  228. // exaggerate knee targets for legs that are nearly straight
  229. // FIXME: should be configurable, and the ikKnee should be from the original animation, not modifed
  230. float d = (targetFoot-worldThigh).Length() - MIN( l1, l2 );
  231. d = MAX( l1 + l2, d );
  232. // FIXME: too short knee directions cause trouble
  233. d = d * 100;
  234. ikTargetKnee = ikKnee + targetKneeDir * d;
  235. // debugLine( worldKnee, worldThigh + ikTargetKnee, 0, 0, 255, true, 0 );
  236. int color[3] = { 0, 255, 0 };
  237. // too far away? (0.9998 is about 1 degree)
  238. if (ikFoot.Length() > (l1 + l2) * KNEEMAX_EPSILON)
  239. {
  240. VectorNormalize( ikFoot );
  241. VectorScale( ikFoot, (l1 + l2) * KNEEMAX_EPSILON, ikFoot );
  242. color[0] = 255; color[1] = 0; color[2] = 0;
  243. }
  244. // too close?
  245. // limit distance to about an 80 degree knee bend
  246. float minDist = MAX( fabs(l1 - l2) * 1.15, MIN( l1, l2 ) * 0.15 );
  247. if (ikFoot.Length() < minDist)
  248. {
  249. // too close to get an accurate vector, just use original vector
  250. ikFoot = (worldFoot - worldThigh);
  251. VectorNormalize( ikFoot );
  252. VectorScale( ikFoot, minDist, ikFoot );
  253. }
  254. CIKSolver ik;
  255. if (ik.solve( l1, l2, ikFoot.Base(), ikTargetKnee.Base(), ikKnee.Base() ))
  256. {
  257. matrix3x4a_t& mWorldThigh = pBoneToWorld[ iThigh ];
  258. matrix3x4a_t& mWorldKnee = pBoneToWorld[ iKnee ];
  259. matrix3x4a_t& mWorldFoot = pBoneToWorld[ iFoot ];
  260. //debugLine( worldThigh, ikKnee + worldThigh, 255, 0, 0, true, 0 );
  261. //debugLine( ikKnee + worldThigh, ikFoot + worldThigh, 255, 0, 0, true,0 );
  262. // debugLine( worldThigh, ikKnee + worldThigh, color[0], color[1], color[2], true, 0 );
  263. // debugLine( ikKnee + worldThigh, ikFoot + worldThigh, color[0], color[1], color[2], true,0 );
  264. // build transformation matrix for thigh
  265. Studio_AlignIKMatrix( mWorldThigh, ikKnee );
  266. Studio_AlignIKMatrix( mWorldKnee, ikFoot - ikKnee );
  267. mWorldKnee[0][3] = ikKnee.x + worldThigh.x;
  268. mWorldKnee[1][3] = ikKnee.y + worldThigh.y;
  269. mWorldKnee[2][3] = ikKnee.z + worldThigh.z;
  270. mWorldFoot[0][3] = ikFoot.x + worldThigh.x;
  271. mWorldFoot[1][3] = ikFoot.y + worldThigh.y;
  272. mWorldFoot[2][3] = ikFoot.z + worldThigh.z;
  273. return true;
  274. }
  275. else
  276. {
  277. /*
  278. debugLine( worldThigh, worldThigh + ikKnee, 255, 0, 0, true, 0 );
  279. debugLine( worldThigh + ikKnee, worldThigh + ikFoot, 255, 0, 0, true, 0 );
  280. debugLine( worldThigh + ikFoot, worldThigh, 255, 0, 0, true, 0 );
  281. debugLine( worldThigh + ikKnee, worldThigh + ikTargetKnee, 255, 0, 0, true, 0 );
  282. */
  283. return false;
  284. }
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Purpose:
  288. //-----------------------------------------------------------------------------
  289. float Studio_IKRuleWeight( mstudioikrule_t &ikRule, const mstudioanimdesc_t *panim, float flCycle, int &iFrame, float &fraq )
  290. {
  291. if (ikRule.end > 1.0f && flCycle < ikRule.start)
  292. {
  293. flCycle = flCycle + 1.0f;
  294. }
  295. float value = 0.0f;
  296. fraq = (panim->numframes - 1) * (flCycle - ikRule.start) + ikRule.iStart;
  297. iFrame = (int)fraq;
  298. fraq = fraq - iFrame;
  299. if (flCycle < ikRule.start)
  300. {
  301. iFrame = ikRule.iStart;
  302. fraq = 0.0f;
  303. return 0.0f;
  304. }
  305. else if (flCycle < ikRule.peak )
  306. {
  307. value = (flCycle - ikRule.start) / (ikRule.peak - ikRule.start);
  308. }
  309. else if (flCycle < ikRule.tail )
  310. {
  311. return 1.0f;
  312. }
  313. else if (flCycle < ikRule.end )
  314. {
  315. value = 1.0f - ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail));
  316. }
  317. else
  318. {
  319. fraq = (panim->numframes - 1) * (ikRule.end - ikRule.start) + ikRule.iStart;
  320. iFrame = (int)fraq;
  321. fraq = fraq - iFrame;
  322. }
  323. return SimpleSpline( value );
  324. }
  325. float Studio_IKRuleWeight( ikcontextikrule_t &ikRule, float flCycle )
  326. {
  327. if (ikRule.end > 1.0f && flCycle < ikRule.start)
  328. {
  329. flCycle = flCycle + 1.0f;
  330. }
  331. float value = 0.0f;
  332. if (flCycle < ikRule.start)
  333. {
  334. return 0.0f;
  335. }
  336. else if (flCycle < ikRule.peak )
  337. {
  338. value = (flCycle - ikRule.start) / (ikRule.peak - ikRule.start);
  339. }
  340. else if (flCycle < ikRule.tail )
  341. {
  342. return 1.0f;
  343. }
  344. else if (flCycle < ikRule.end )
  345. {
  346. value = 1.0f - ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail));
  347. }
  348. return 3.0f * value * value - 2.0f * value * value * value;
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose:
  352. //-----------------------------------------------------------------------------
  353. bool Studio_IKShouldLatch( ikcontextikrule_t &ikRule, float flCycle )
  354. {
  355. if (ikRule.end > 1.0f && flCycle < ikRule.start)
  356. {
  357. flCycle = flCycle + 1.0f;
  358. }
  359. if (flCycle < ikRule.peak )
  360. {
  361. return false;
  362. }
  363. else if (flCycle < ikRule.end )
  364. {
  365. return true;
  366. }
  367. return false;
  368. }
  369. //-----------------------------------------------------------------------------
  370. // Purpose:
  371. //-----------------------------------------------------------------------------
  372. float Studio_IKTail( ikcontextikrule_t &ikRule, float flCycle )
  373. {
  374. if (ikRule.end > 1.0f && flCycle < ikRule.start)
  375. {
  376. flCycle = flCycle + 1.0f;
  377. }
  378. if (flCycle <= ikRule.tail )
  379. {
  380. return 0.0f;
  381. }
  382. else if (flCycle < ikRule.end )
  383. {
  384. return ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail));
  385. }
  386. return 0.0;
  387. }
  388. //-----------------------------------------------------------------------------
  389. // Purpose:
  390. //-----------------------------------------------------------------------------
  391. bool Studio_IKAnimationError( const CStudioHdr *pStudioHdr, mstudioikrule_t *pRule, const mstudioanimdesc_t *panim, float flCycle, BoneVector &pos, BoneQuaternion &q, float &flWeight )
  392. {
  393. float fraq;
  394. int iFrame;
  395. if (!pRule)
  396. return false;
  397. flWeight = Studio_IKRuleWeight( *pRule, panim, flCycle, iFrame, fraq );
  398. Assert( fraq >= 0.0 && fraq < 1.0 );
  399. Assert( flWeight >= 0.0f && flWeight <= 1.0f );
  400. // This shouldn't be necessary, but the Assert should help us catch whoever is screwing this up
  401. flWeight = clamp( flWeight, 0.0f, 1.0f );
  402. if (pRule->type != IK_GROUND && flWeight < 0.0001)
  403. return false;
  404. mstudioikerror_t *pError = pRule->pError( iFrame );
  405. if (pError != NULL)
  406. {
  407. if (fraq < 0.001)
  408. {
  409. q = pError[0].q;
  410. pos = pError[0].pos;
  411. }
  412. else
  413. {
  414. QuaternionBlend( pError[0].q, pError[1].q, fraq, q );
  415. pos = pError[0].pos * (1.0f - fraq) + pError[1].pos * fraq;
  416. }
  417. return true;
  418. }
  419. mstudiocompressedikerror_t *pCompressed = pRule->pCompressedError();
  420. if (pCompressed != NULL)
  421. {
  422. CalcDecompressedAnimation( pCompressed, iFrame - pRule->iStart, fraq, pos, q );
  423. return true;
  424. }
  425. // no data, disable IK rule
  426. Assert( 0 );
  427. flWeight = 0.0f;
  428. return false;
  429. }
  430. //-----------------------------------------------------------------------------
  431. // Purpose: For a specific sequence:rule, find where it starts, stops, and what
  432. // the estimated offset from the connection point is.
  433. // return true if the rule is within bounds.
  434. //-----------------------------------------------------------------------------
  435. bool Studio_IKSequenceError( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, int iRule, const float poseParameter[], mstudioanimdesc_t *panim[4], float weight[4], ikcontextikrule_t &ikRule )
  436. {
  437. BONE_PROFILE_FUNC();
  438. int i;
  439. memset( &ikRule, 0, sizeof(ikRule) );
  440. ikRule.start = ikRule.peak = ikRule.tail = ikRule.end = 0;
  441. float prevStart = 0.0f;
  442. // find overall influence
  443. for (i = 0; i < 4; i++)
  444. {
  445. if (weight[i])
  446. {
  447. if (iRule >= panim[i]->numikrules || panim[i]->numikrules != panim[0]->numikrules)
  448. {
  449. Assert( 0 );
  450. return false;
  451. }
  452. mstudioikrule_t *pRule = panim[i]->pIKRule( iRule );
  453. if (pRule != NULL)
  454. {
  455. float dt = 0.0f;
  456. if (prevStart != 0.0f)
  457. {
  458. if (pRule->start - prevStart > 0.5)
  459. {
  460. dt = -1.0;
  461. }
  462. else if (pRule->start - prevStart < -0.5)
  463. {
  464. dt = 1.0;
  465. }
  466. }
  467. else
  468. {
  469. prevStart = pRule->start;
  470. }
  471. ikRule.start += (pRule->start + dt) * weight[i];
  472. ikRule.peak += (pRule->peak + dt) * weight[i];
  473. ikRule.tail += (pRule->tail + dt) * weight[i];
  474. ikRule.end += (pRule->end + dt) * weight[i];
  475. }
  476. else
  477. {
  478. mstudioikrulezeroframe_t *pZeroFrameRule = panim[i]->pIKRuleZeroFrame( iRule );
  479. if (pZeroFrameRule)
  480. {
  481. float dt = 0.0f;
  482. if (prevStart != 0.0f)
  483. {
  484. if (pZeroFrameRule->start.GetFloat() - prevStart > 0.5)
  485. {
  486. dt = -1.0;
  487. }
  488. else if (pZeroFrameRule->start.GetFloat() - prevStart < -0.5)
  489. {
  490. dt = 1.0;
  491. }
  492. }
  493. else
  494. {
  495. prevStart = pZeroFrameRule->start.GetFloat();
  496. }
  497. ikRule.start += (pZeroFrameRule->start.GetFloat() + dt) * weight[i];
  498. ikRule.peak += (pZeroFrameRule->peak.GetFloat() + dt) * weight[i];
  499. ikRule.tail += (pZeroFrameRule->tail.GetFloat() + dt) * weight[i];
  500. ikRule.end += (pZeroFrameRule->end.GetFloat() + dt) * weight[i];
  501. }
  502. else
  503. {
  504. // Msg("%s %s - IK Stall\n", pStudioHdr->name(), seqdesc.pszLabel() );
  505. return false;
  506. }
  507. }
  508. }
  509. }
  510. if (ikRule.start > 1.0)
  511. {
  512. ikRule.start -= 1.0;
  513. ikRule.peak -= 1.0;
  514. ikRule.tail -= 1.0;
  515. ikRule.end -= 1.0;
  516. }
  517. else if (ikRule.start < 0.0)
  518. {
  519. ikRule.start += 1.0;
  520. ikRule.peak += 1.0;
  521. ikRule.tail += 1.0;
  522. ikRule.end += 1.0;
  523. }
  524. ikRule.flWeight = Studio_IKRuleWeight( ikRule, flCycle );
  525. if (ikRule.flWeight <= 0.001f)
  526. {
  527. // go ahead and allow IK_GROUND rules a virtual looping section
  528. if ( weight[0] )
  529. {
  530. if ( panim[ 0 ]->pIKRule( iRule ) == NULL )
  531. return false;
  532. if ( ( panim[ 0 ]->flags & STUDIO_LOOPING ) && panim[ 0 ]->pIKRule( iRule )->type == IK_GROUND && ikRule.end - ikRule.start > 0.75 )
  533. {
  534. ikRule.flWeight = 0.001;
  535. flCycle = ikRule.end - 0.001;
  536. }
  537. else
  538. {
  539. return false;
  540. }
  541. }
  542. else
  543. {
  544. return false;
  545. }
  546. }
  547. Assert( ikRule.flWeight > 0.0f );
  548. ikRule.pos.Init();
  549. ikRule.q.Init();
  550. // find target error
  551. float total = 0.0f;
  552. for (i = 0; i < 4; i++)
  553. {
  554. if (weight[i])
  555. {
  556. BoneVector pos1;
  557. BoneQuaternion q1;
  558. float w;
  559. mstudioikrule_t *pRule = panim[i]->pIKRule( iRule );
  560. if (pRule != NULL)
  561. {
  562. ikRule.chain = pRule->chain; // FIXME: this is anim local
  563. ikRule.bone = pRule->bone; // FIXME: this is anim local
  564. ikRule.type = pRule->type;
  565. ikRule.slot = pRule->slot;
  566. ikRule.height += pRule->height * weight[i];
  567. ikRule.floor += pRule->floor * weight[i];
  568. ikRule.radius += pRule->radius * weight[i];
  569. ikRule.drop += pRule->drop * weight[i];
  570. ikRule.top += pRule->top * weight[i];
  571. }
  572. else
  573. {
  574. // look to see if there's a zeroframe version of the rule
  575. mstudioikrulezeroframe_t *pZeroFrameRule = panim[i]->pIKRuleZeroFrame( iRule );
  576. if (pZeroFrameRule)
  577. {
  578. // zeroframe doesn't contain details, so force a IK_RELEASE
  579. ikRule.type = IK_RELEASE;
  580. ikRule.chain = pZeroFrameRule->chain;
  581. ikRule.slot = pZeroFrameRule->slot;
  582. ikRule.bone = -1;
  583. // Msg("IK_RELEASE %d %d : %.2f\n", ikRule.chain, ikRule.slot, ikRule.flWeight );
  584. }
  585. else
  586. {
  587. // Msg("%s %s - IK Stall\n", pStudioHdr->name(), seqdesc.pszLabel() );
  588. return false;
  589. }
  590. }
  591. // keep track of tail condition
  592. ikRule.release += Studio_IKTail( ikRule, flCycle ) * weight[i];
  593. // only check rules with error values
  594. switch( ikRule.type )
  595. {
  596. case IK_SELF:
  597. case IK_WORLD:
  598. case IK_GROUND:
  599. case IK_ATTACHMENT:
  600. {
  601. int bResult = Studio_IKAnimationError( pStudioHdr, pRule, panim[i], flCycle, pos1, q1, w );
  602. if (bResult)
  603. {
  604. ikRule.pos = ikRule.pos + pos1 * weight[i];
  605. QuaternionAccumulate( ikRule.q, weight[i], q1, ikRule.q );
  606. total += weight[i];
  607. }
  608. }
  609. break;
  610. default:
  611. total += weight[i];
  612. break;
  613. }
  614. ikRule.latched = Studio_IKShouldLatch( ikRule, flCycle ) * ikRule.flWeight;
  615. if (ikRule.type == IK_ATTACHMENT)
  616. {
  617. ikRule.szLabel = pRule->pszAttachment();
  618. }
  619. }
  620. }
  621. if (total <= 0.0001f)
  622. {
  623. return false;
  624. }
  625. if (total < 0.999f)
  626. {
  627. VectorScale( ikRule.pos, 1.0f / total, ikRule.pos );
  628. QuaternionScale( ikRule.q, 1.0f / total, ikRule.q );
  629. }
  630. if (ikRule.type == IK_SELF && ikRule.bone != -1)
  631. {
  632. // FIXME: this is anim local, not seq local!
  633. ikRule.bone = pStudioHdr->RemapSeqBone( iSequence, ikRule.bone );
  634. if (ikRule.bone == -1)
  635. return false;
  636. }
  637. QuaternionNormalize( ikRule.q );
  638. return true;
  639. }
  640. //-----------------------------------------------------------------------------
  641. // Purpose:
  642. //-----------------------------------------------------------------------------
  643. CIKContext::CIKContext()
  644. {
  645. m_target.EnsureCapacity( 12 ); // FIXME: this sucks, shouldn't it be grown?
  646. m_iFramecounter = -1;
  647. m_pStudioHdr = NULL;
  648. m_flTime = -1.0f;
  649. m_target.SetSize( 0 );
  650. }
  651. void CIKContext::Init( const CStudioHdr *pStudioHdr, const QAngle &angles, const Vector &pos, float flTime, int iFramecounter, int boneMask )
  652. {
  653. BONE_PROFILE_FUNC();
  654. SNPROF_ANIM( "CIKContext::Init" );
  655. m_pStudioHdr = pStudioHdr;
  656. m_ikChainRule.RemoveAll(); // m_numikrules = 0;
  657. if (pStudioHdr->numikchains())
  658. {
  659. m_ikChainRule.SetSize( pStudioHdr->numikchains() );
  660. // FIXME: Brutal hackery to prevent a crash
  661. if (m_target.Count() == 0)
  662. {
  663. m_target.SetSize(12);
  664. memset( m_target.Base(), 0, sizeof(m_target[0])*m_target.Count() );
  665. ClearTargets();
  666. }
  667. }
  668. else
  669. {
  670. m_target.SetSize( 0 );
  671. }
  672. AngleMatrix( angles, pos, m_rootxform );
  673. m_iFramecounter = iFramecounter;
  674. m_flTime = flTime;
  675. m_boneMask = boneMask;
  676. }
  677. void CIKContext::AddDependencies( mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, const float poseParameters[], float flWeight )
  678. {
  679. BONE_PROFILE_FUNC(); // ex: x360: up to 1 ms
  680. SNPROF_ANIM("CIKContext::AddDependencies");
  681. int i;
  682. if ( m_pStudioHdr->numikchains() == 0)
  683. return;
  684. if (seqdesc.numikrules == 0)
  685. return;
  686. ikcontextikrule_t ikrule;
  687. Assert( flWeight >= 0.0f && flWeight <= 1.0f );
  688. // This shouldn't be necessary, but the Assert should help us catch whoever is screwing this up
  689. flWeight = clamp( flWeight, 0.0f, 1.0f );
  690. // unify this
  691. if (seqdesc.flags & STUDIO_REALTIME)
  692. {
  693. float cps = Studio_CPS( m_pStudioHdr, seqdesc, iSequence, poseParameters );
  694. flCycle = m_flTime * cps;
  695. flCycle = flCycle - (int)flCycle;
  696. }
  697. else if (flCycle < 0 || flCycle >= 1)
  698. {
  699. if (seqdesc.flags & STUDIO_LOOPING)
  700. {
  701. flCycle = flCycle - (int)flCycle;
  702. if (flCycle < 0) flCycle += 1;
  703. }
  704. else
  705. {
  706. flCycle = MAX( 0.0, MIN( flCycle, 0.9999 ) );
  707. }
  708. }
  709. mstudioanimdesc_t *panim[4];
  710. float weight[4];
  711. Studio_SeqAnims( m_pStudioHdr, seqdesc, iSequence, poseParameters, panim, weight );
  712. // FIXME: add proper number of rules!!!
  713. for (i = 0; i < seqdesc.numikrules; i++)
  714. {
  715. if ( !Studio_IKSequenceError( m_pStudioHdr, seqdesc, iSequence, flCycle, i, poseParameters, panim, weight, ikrule ) )
  716. continue;
  717. // don't add rule if the bone isn't going to be calculated
  718. int bone = m_pStudioHdr->pIKChain( ikrule.chain )->pLink( 2 )->bone;
  719. if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  720. continue;
  721. // or if its relative bone isn't going to be calculated
  722. if ( ikrule.bone >= 0 && !(m_pStudioHdr->boneFlags( ikrule.bone ) & m_boneMask))
  723. continue;
  724. // FIXME: Brutal hackery to prevent a crash
  725. if (m_target.Count() == 0)
  726. {
  727. m_target.SetSize(12);
  728. memset( m_target.Base(), 0, sizeof(m_target[0])*m_target.Count() );
  729. ClearTargets();
  730. }
  731. ikrule.flRuleWeight = flWeight;
  732. if (ikrule.flRuleWeight * ikrule.flWeight > 0.999)
  733. {
  734. if ( ikrule.type != IK_UNLATCH)
  735. {
  736. // clear out chain if rule is 100%
  737. m_ikChainRule.Element( ikrule.chain ).RemoveAll( );
  738. if ( ikrule.type == IK_RELEASE)
  739. {
  740. continue;
  741. }
  742. }
  743. }
  744. int nIndex = m_ikChainRule.Element( ikrule.chain ).AddToTail( );
  745. m_ikChainRule.Element( ikrule.chain ).Element( nIndex ) = ikrule;
  746. }
  747. }
  748. #if defined( _PS3 )
  749. //--------------------------------------------------------------------------------------
  750. // 2nd part of IKContext AddDependencies
  751. //
  752. // 1st part assumed to have run during a PS3 bonejob, building a list of IKRules to potentially add
  753. //--------------------------------------------------------------------------------------
  754. void CIKContext::AddAllDependencies_PS3( ikcontextikrule_t *ikRules, int numRules )
  755. {
  756. SNPROF_ANIM("CIKContext::AddAllDependencies_PS3");
  757. int i;
  758. // FIXME: add proper number of rules!!!
  759. for( i = 0; i < numRules; i++ )
  760. {
  761. ikcontextikrule_t &ikrule = ikRules[ i ];
  762. // no copy constructors generally allowed
  763. //memcpy( &ikrule, &ikRules[i], sizeof(ikcontextikrule_t) );
  764. // don't add rule if the bone isn't going to be calculated
  765. // int bone = m_pStudioHdr->pIKChain( ikrule.chain )->pLink( 2 )->bone;
  766. // if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  767. // continue;
  768. // or if its relative bone isn't going to be calculated
  769. // if ( ikrule.bone >= 0 && !(m_pStudioHdr->boneFlags( ikrule.bone ) & m_boneMask))
  770. // continue;
  771. // FIXME: Brutal hackery to prevent a crash
  772. if (m_target.Count() == 0)
  773. {
  774. m_target.SetSize(12);
  775. memset( m_target.Base(), 0, sizeof(m_target[0])*m_target.Count() );
  776. ClearTargets();
  777. }
  778. //ikrule.flRuleWeight = flWeight;
  779. if( ikrule.flRuleWeight * ikrule.flWeight > 0.999f )
  780. {
  781. if ( ikrule.type != IK_UNLATCH)
  782. {
  783. // clear out chain if rule is 100%
  784. m_ikChainRule.Element( ikrule.chain ).RemoveAll( );
  785. if ( ikrule.type == IK_RELEASE)
  786. {
  787. continue;
  788. }
  789. }
  790. }
  791. int nIndex = m_ikChainRule.Element( ikrule.chain ).AddToTail( );
  792. m_ikChainRule.Element( ikrule.chain ).Element( nIndex ) = ikrule;
  793. }
  794. }
  795. #endif
  796. //-----------------------------------------------------------------------------
  797. // Purpose:
  798. //-----------------------------------------------------------------------------
  799. void CIKContext::AddAutoplayLocks( BoneVector pos[], BoneQuaternion q[] )
  800. {
  801. BONE_PROFILE_FUNC();
  802. // skip all array access if no autoplay locks.
  803. if (m_pStudioHdr->GetNumIKAutoplayLocks() == 0)
  804. {
  805. return;
  806. }
  807. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  808. CBoneBitList boneComputed;
  809. int ikOffset = m_ikLock.AddMultipleToTail( m_pStudioHdr->GetNumIKAutoplayLocks() );
  810. memset( &m_ikLock[ikOffset], 0, sizeof(ikcontextikrule_t)*m_pStudioHdr->GetNumIKAutoplayLocks() );
  811. for (int i = 0; i < m_pStudioHdr->GetNumIKAutoplayLocks(); i++)
  812. {
  813. const mstudioiklock_t &lock = ((CStudioHdr *)m_pStudioHdr)->pIKAutoplayLock( i );
  814. mstudioikchain_t *pchain = ((CStudioHdr *)m_pStudioHdr)->pIKChain( lock.chain );
  815. int bone = pchain->pLink( 2 )->bone;
  816. // don't bother with iklock if the bone isn't going to be calculated
  817. if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  818. continue;
  819. // eval current ik'd bone
  820. BuildBoneChain( pos, q, bone, boneToWorld, boneComputed );
  821. ikcontextikrule_t &ikrule = m_ikLock[ i + ikOffset ];
  822. ikrule.chain = lock.chain;
  823. ikrule.slot = i;
  824. ikrule.type = IK_WORLD;
  825. MatrixAngles( boneToWorld[bone], ikrule.q, ikrule.pos );
  826. // save off current knee direction
  827. if (pchain->pLink(0)->kneeDir.LengthSqr() > 0.0)
  828. {
  829. Vector tmp = pchain->pLink( 0 )->kneeDir;
  830. VectorRotate( pchain->pLink( 0 )->kneeDir, boneToWorld[ pchain->pLink( 0 )->bone ], ikrule.kneeDir );
  831. MatrixPosition( boneToWorld[ pchain->pLink( 1 )->bone ], ikrule.kneePos );
  832. }
  833. else
  834. {
  835. ikrule.kneeDir.Init( );
  836. }
  837. }
  838. g_MatrixPool.Free( boneToWorld );
  839. }
  840. //-----------------------------------------------------------------------------
  841. // Purpose:
  842. //-----------------------------------------------------------------------------
  843. void CIKContext::AddSequenceLocks( mstudioseqdesc_t &seqdesc, BoneVector pos[], BoneQuaternion q[] )
  844. {
  845. BONE_PROFILE_FUNC(); // ex: x360:up to 0.98 ms
  846. SNPROF_ANIM("CIKContext::AddSequenceLocks");
  847. if ( m_pStudioHdr->numikchains() == 0)
  848. {
  849. return;
  850. }
  851. if ( seqdesc.numiklocks == 0 )
  852. {
  853. return;
  854. }
  855. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  856. CBoneBitList boneComputed;
  857. int ikOffset = m_ikLock.AddMultipleToTail( seqdesc.numiklocks );
  858. memset( &m_ikLock[ikOffset], 0, sizeof(ikcontextikrule_t) * seqdesc.numiklocks );
  859. for (int i = 0; i < seqdesc.numiklocks; i++)
  860. {
  861. mstudioiklock_t *plock = seqdesc.pIKLock( i );
  862. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( plock->chain );
  863. int bone = pchain->pLink( 2 )->bone;
  864. // don't bother with iklock if the bone isn't going to be calculated
  865. if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  866. continue;
  867. // eval current ik'd bone
  868. BuildBoneChain( pos, q, bone, boneToWorld, boneComputed );
  869. ikcontextikrule_t &ikrule = m_ikLock[i+ikOffset];
  870. ikrule.chain = i;
  871. ikrule.slot = i;
  872. ikrule.type = IK_WORLD;
  873. MatrixAngles( boneToWorld[bone], ikrule.q, ikrule.pos );
  874. // save off current knee direction
  875. if (pchain->pLink(0)->kneeDir.LengthSqr() > 0.0)
  876. {
  877. VectorRotate( pchain->pLink( 0 )->kneeDir, boneToWorld[ pchain->pLink( 0 )->bone ], ikrule.kneeDir );
  878. }
  879. else
  880. {
  881. ikrule.kneeDir.Init( );
  882. }
  883. }
  884. g_MatrixPool.Free( boneToWorld );
  885. }
  886. //-----------------------------------------------------------------------------
  887. // Purpose: build boneToWorld transforms for a specific bone
  888. //-----------------------------------------------------------------------------
  889. void CIKContext::BuildBoneChain(
  890. const BoneVector pos[],
  891. const BoneQuaternion q[],
  892. int iBone,
  893. matrix3x4a_t *pBoneToWorld,
  894. CBoneBitList &boneComputed )
  895. {
  896. Assert( m_pStudioHdr->boneFlags( iBone ) & m_boneMask );
  897. ::BuildBoneChain( m_pStudioHdr, m_rootxform, pos, q, iBone, pBoneToWorld, boneComputed );
  898. }
  899. //-----------------------------------------------------------------------------
  900. // Purpose: turn a specific bones boneToWorld transform into a pos and q in parents bonespace
  901. //-----------------------------------------------------------------------------
  902. void SolveBone(
  903. const CStudioHdr *pStudioHdr,
  904. int iBone,
  905. matrix3x4a_t *pBoneToWorld,
  906. BoneVector pos[],
  907. BoneQuaternion q[]
  908. )
  909. {
  910. int iParent = pStudioHdr->boneParent( iBone );
  911. matrix3x4a_t worldToBone;
  912. MatrixInvert( pBoneToWorld[iParent], worldToBone );
  913. matrix3x4a_t local;
  914. ConcatTransforms_Aligned( worldToBone, pBoneToWorld[iBone], local );
  915. MatrixAngles( local, q[iBone], pos[iBone] );
  916. }
  917. //-----------------------------------------------------------------------------
  918. // Purpose:
  919. //-----------------------------------------------------------------------------
  920. void CIKTarget::SetOwner( int entindex, const Vector &pos, const QAngle &angles )
  921. {
  922. latched.owner = entindex;
  923. latched.absOrigin = pos;
  924. latched.absAngles = angles;
  925. }
  926. //-----------------------------------------------------------------------------
  927. // Purpose:
  928. //-----------------------------------------------------------------------------
  929. void CIKTarget::ClearOwner( void )
  930. {
  931. latched.owner = -1;
  932. }
  933. //-----------------------------------------------------------------------------
  934. // Purpose:
  935. //-----------------------------------------------------------------------------
  936. int CIKTarget::GetOwner( void )
  937. {
  938. return latched.owner;
  939. }
  940. //-----------------------------------------------------------------------------
  941. // Purpose: update the latched IK values that are in a moving frame of reference
  942. //-----------------------------------------------------------------------------
  943. void CIKTarget::UpdateOwner( int entindex, const Vector &pos, const QAngle &angles )
  944. {
  945. if (pos == latched.absOrigin && angles == latched.absAngles)
  946. return;
  947. matrix3x4a_t in;
  948. matrix3x4a_t out;
  949. AngleMatrix( angles, pos, in );
  950. AngleIMatrix( latched.absAngles, latched.absOrigin, out );
  951. matrix3x4a_t tmp1;
  952. matrix3x4a_t tmp2;
  953. QuaternionMatrix( latched.q, latched.pos, tmp1 );
  954. ConcatTransforms_Aligned( out, tmp1, tmp2 );
  955. ConcatTransforms_Aligned( in, tmp2, tmp1 );
  956. MatrixAngles( tmp1, latched.q, latched.pos );
  957. }
  958. //-----------------------------------------------------------------------------
  959. // Purpose: sets the ground position of an ik target
  960. //-----------------------------------------------------------------------------
  961. void CIKTarget::SetPos( const Vector &pos )
  962. {
  963. est.pos = pos;
  964. }
  965. //-----------------------------------------------------------------------------
  966. // Purpose: sets the ground "identity" orientation of an ik target
  967. //-----------------------------------------------------------------------------
  968. void CIKTarget::SetAngles( const QAngle &angles )
  969. {
  970. AngleQuaternion( angles, est.q );
  971. }
  972. //-----------------------------------------------------------------------------
  973. // Purpose: sets the ground "identity" orientation of an ik target
  974. //-----------------------------------------------------------------------------
  975. void CIKTarget::SetQuaternion( const Quaternion &q )
  976. {
  977. est.q = q;
  978. }
  979. //-----------------------------------------------------------------------------
  980. // Purpose: calculates a ground "identity" orientation based on the surface
  981. // normal of the ground and the desired ground identity orientation
  982. //-----------------------------------------------------------------------------
  983. void CIKTarget::SetNormal( const Vector &normal )
  984. {
  985. // recalculate foot angle based on slope of surface
  986. matrix3x4a_t m1;
  987. Vector forward, right;
  988. QuaternionMatrix( est.q, m1 );
  989. MatrixGetColumn( m1, 1, right );
  990. forward = CrossProduct( right, normal );
  991. right = CrossProduct( normal, forward );
  992. MatrixSetColumn( forward, 0, m1 );
  993. MatrixSetColumn( right, 1, m1 );
  994. MatrixSetColumn( normal, 2, m1 );
  995. QAngle a1;
  996. Vector p1;
  997. MatrixAngles( m1, est.q, p1 );
  998. }
  999. //-----------------------------------------------------------------------------
  1000. // Purpose: estimates the ground impact at the center location assuming a the edge of
  1001. // an Z axis aligned disc collided with it the surface.
  1002. //-----------------------------------------------------------------------------
  1003. void CIKTarget::SetPosWithNormalOffset( const Vector &pos, const Vector &normal )
  1004. {
  1005. // assume it's a disc edge intersecting with the floor, so try to estimate the z location of the center
  1006. est.pos = pos;
  1007. if (normal.z > 0.9999)
  1008. {
  1009. return;
  1010. }
  1011. // clamp at 45 degrees
  1012. else if (normal.z > 0.707)
  1013. {
  1014. // tan == sin / cos
  1015. float tan = sqrt( 1 - normal.z * normal.z ) / normal.z;
  1016. est.pos.z = est.pos.z - est.radius * tan;
  1017. }
  1018. else
  1019. {
  1020. est.pos.z = est.pos.z - est.radius;
  1021. }
  1022. }
  1023. //-----------------------------------------------------------------------------
  1024. // Purpose:
  1025. //-----------------------------------------------------------------------------
  1026. void CIKTarget::SetOnWorld( bool bOnWorld )
  1027. {
  1028. est.onWorld = bOnWorld;
  1029. }
  1030. //-----------------------------------------------------------------------------
  1031. // Purpose:
  1032. //-----------------------------------------------------------------------------
  1033. bool CIKTarget::IsActive()
  1034. {
  1035. return (est.flWeight > 0.0f);
  1036. }
  1037. //-----------------------------------------------------------------------------
  1038. // Purpose:
  1039. //-----------------------------------------------------------------------------
  1040. void CIKTarget::IKFailed( void )
  1041. {
  1042. latched.deltaPos.Init();
  1043. latched.deltaQ.Init();
  1044. latched.pos = ideal.pos;
  1045. latched.q = ideal.q;
  1046. est.latched = 0.0;
  1047. est.flWeight = 0.0;
  1048. est.onWorld = false;
  1049. }
  1050. //-----------------------------------------------------------------------------
  1051. // Purpose:
  1052. //-----------------------------------------------------------------------------
  1053. void CIKTarget::MoveReferenceFrame( Vector &deltaPos, QAngle &deltaAngles )
  1054. {
  1055. est.pos -= deltaPos;
  1056. latched.pos -= deltaPos;
  1057. offset.pos -= deltaPos;
  1058. ideal.pos -= deltaPos;
  1059. }
  1060. //-----------------------------------------------------------------------------
  1061. // Purpose: Invalidate any IK locks.
  1062. //-----------------------------------------------------------------------------
  1063. void CIKContext::ClearTargets( void )
  1064. {
  1065. int i;
  1066. for (i = 0; i < m_target.Count(); i++)
  1067. {
  1068. m_target[i].latched.iFramecounter = -9999;
  1069. }
  1070. }
  1071. //-----------------------------------------------------------------------------
  1072. // Purpose: Run through the rules that survived and turn a specific bones boneToWorld
  1073. // transform into a pos and q in parents bonespace
  1074. //-----------------------------------------------------------------------------
  1075. void CIKContext::UpdateTargets( BoneVector pos[], BoneQuaternion q[], matrix3x4a_t boneToWorld[], CBoneBitList &boneComputed )
  1076. {
  1077. BONE_PROFILE_FUNC();
  1078. SNPROF_ANIM( "CIKContext::UpdateTargets" );
  1079. int i, j;
  1080. for (i = 0; i < m_target.Count(); i++)
  1081. {
  1082. m_target[i].est.flWeight = 0.0f;
  1083. m_target[i].est.latched = 1.0f;
  1084. m_target[i].est.release = 1.0f;
  1085. m_target[i].est.height = 0.0f;
  1086. m_target[i].est.floor = 0.0f;
  1087. m_target[i].est.radius = 0.0f;
  1088. m_target[i].offset.pos.Init();
  1089. m_target[i].offset.q.Init();
  1090. }
  1091. AutoIKRelease( );
  1092. for (j = 0; j < m_ikChainRule.Count(); j++)
  1093. {
  1094. for (i = 0; i < m_ikChainRule.Element( j ).Count(); i++)
  1095. {
  1096. ikcontextikrule_t *pRule = &m_ikChainRule.Element( j ).Element( i );
  1097. // ikchainresult_t *pChainRule = &chainRule[ m_ikRule[i].chain ];
  1098. switch( pRule->type )
  1099. {
  1100. case IK_ATTACHMENT:
  1101. case IK_GROUND:
  1102. // case IK_SELF:
  1103. {
  1104. matrix3x4a_t footTarget;
  1105. CIKTarget *pTarget = &m_target[pRule->slot];
  1106. pTarget->chain = pRule->chain;
  1107. pTarget->type = pRule->type;
  1108. if (pRule->type == IK_ATTACHMENT)
  1109. {
  1110. pTarget->offset.pAttachmentName = pRule->szLabel;
  1111. }
  1112. else
  1113. {
  1114. pTarget->offset.pAttachmentName = NULL;
  1115. }
  1116. if (pRule->flRuleWeight == 1.0f || pTarget->est.flWeight == 0.0f)
  1117. {
  1118. pTarget->offset.q = pRule->q;
  1119. pTarget->offset.pos = pRule->pos;
  1120. pTarget->est.height = pRule->height;
  1121. pTarget->est.floor = pRule->floor;
  1122. pTarget->est.radius = pRule->radius;
  1123. pTarget->est.latched = pRule->latched * pRule->flRuleWeight;
  1124. pTarget->est.release = pRule->release;
  1125. pTarget->est.flWeight = pRule->flWeight * pRule->flRuleWeight;
  1126. }
  1127. else
  1128. {
  1129. QuaternionSlerp( pTarget->offset.q, pRule->q, pRule->flRuleWeight, pTarget->offset.q );
  1130. pTarget->offset.pos = Lerp( pRule->flRuleWeight, pTarget->offset.pos, pRule->pos );
  1131. pTarget->est.height = Lerp( pRule->flRuleWeight, pTarget->est.height, pRule->height );
  1132. pTarget->est.floor = Lerp( pRule->flRuleWeight, pTarget->est.floor, pRule->floor );
  1133. pTarget->est.radius = Lerp( pRule->flRuleWeight, pTarget->est.radius, pRule->radius );
  1134. //pTarget->est.latched = Lerp( pRule->flRuleWeight, pTarget->est.latched, pRule->latched );
  1135. pTarget->est.latched = MIN( pTarget->est.latched, pRule->latched );
  1136. pTarget->est.release = Lerp( pRule->flRuleWeight, pTarget->est.release, pRule->release );
  1137. pTarget->est.flWeight = Lerp( pRule->flRuleWeight, pTarget->est.flWeight, pRule->flWeight );
  1138. }
  1139. if ( pRule->type == IK_GROUND )
  1140. {
  1141. pTarget->latched.deltaPos.z = 0;
  1142. pTarget->est.pos.z = pTarget->est.floor + m_rootxform[2][3];
  1143. }
  1144. }
  1145. break;
  1146. case IK_UNLATCH:
  1147. {
  1148. CIKTarget *pTarget = &m_target[pRule->slot];
  1149. if (pRule->latched > 0.0)
  1150. pTarget->est.latched = 0.0;
  1151. else
  1152. pTarget->est.latched = MIN( pTarget->est.latched, 1.0f - pRule->flWeight );
  1153. }
  1154. break;
  1155. case IK_RELEASE:
  1156. {
  1157. CIKTarget *pTarget = &m_target[pRule->slot];
  1158. if (pRule->latched > 0.0)
  1159. pTarget->est.latched = 0.0;
  1160. else
  1161. pTarget->est.latched = MIN( pTarget->est.latched, 1.0f - pRule->flWeight );
  1162. pTarget->est.flWeight = (pTarget->est.flWeight) * (1 - pRule->flWeight * pRule->flRuleWeight);
  1163. }
  1164. break;
  1165. }
  1166. }
  1167. }
  1168. for (i = 0; i < m_target.Count(); i++)
  1169. {
  1170. CIKTarget *pTarget = &m_target[i];
  1171. if (pTarget->est.flWeight > 0.0)
  1172. {
  1173. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( pTarget->chain );
  1174. // ikchainresult_t *pChainRule = &chainRule[ i ];
  1175. int bone = pchain->pLink( 2 )->bone;
  1176. // eval current ik'd bone
  1177. BuildBoneChain( pos, q, bone, boneToWorld, boneComputed );
  1178. // xform IK target error into world space
  1179. matrix3x4a_t local;
  1180. matrix3x4a_t worldFootpad;
  1181. QuaternionMatrix( pTarget->offset.q, pTarget->offset.pos, local );
  1182. MatrixInvert( local, local );
  1183. ConcatTransforms_Aligned( boneToWorld[bone], local, worldFootpad );
  1184. if (pTarget->est.latched == 1.0)
  1185. {
  1186. pTarget->latched.bNeedsLatch = true;
  1187. }
  1188. else
  1189. {
  1190. pTarget->latched.bNeedsLatch = false;
  1191. }
  1192. // disable latched position if it looks invalid
  1193. if (m_iFramecounter < 0 || pTarget->latched.iFramecounter < m_iFramecounter - 1 || pTarget->latched.iFramecounter > m_iFramecounter)
  1194. {
  1195. pTarget->latched.bHasLatch = false;
  1196. pTarget->latched.influence = 0.0;
  1197. }
  1198. pTarget->latched.iFramecounter = m_iFramecounter;
  1199. // find ideal contact position
  1200. MatrixAngles( worldFootpad, pTarget->ideal.q, pTarget->ideal.pos );
  1201. pTarget->est.q = pTarget->ideal.q;
  1202. pTarget->est.pos = pTarget->ideal.pos;
  1203. float latched = pTarget->est.latched;
  1204. if (pTarget->latched.bHasLatch)
  1205. {
  1206. if (pTarget->est.latched == 1.0)
  1207. {
  1208. // keep track of latch position error from ideal contact position
  1209. pTarget->latched.deltaPos = pTarget->latched.pos - pTarget->est.pos;
  1210. QuaternionSM( -1, pTarget->est.q, pTarget->latched.q, pTarget->latched.deltaQ );
  1211. pTarget->est.q = pTarget->latched.q;
  1212. pTarget->est.pos = pTarget->latched.pos;
  1213. }
  1214. else if (pTarget->est.latched > 0.0)
  1215. {
  1216. // ramp out latch differences during decay phase of rule
  1217. if (latched > 0 && latched < pTarget->latched.influence)
  1218. {
  1219. // latching has decreased
  1220. float dt = pTarget->latched.influence - latched;
  1221. if (pTarget->latched.influence > 0.0)
  1222. dt = dt / pTarget->latched.influence;
  1223. VectorScale( pTarget->latched.deltaPos, (1-dt), pTarget->latched.deltaPos );
  1224. QuaternionScale( pTarget->latched.deltaQ, (1-dt), pTarget->latched.deltaQ );
  1225. }
  1226. // move ideal contact position by latched error factor
  1227. pTarget->est.pos = pTarget->est.pos + pTarget->latched.deltaPos;
  1228. QuaternionMA( pTarget->est.q, 1, pTarget->latched.deltaQ, pTarget->est.q );
  1229. pTarget->latched.q = pTarget->est.q;
  1230. pTarget->latched.pos = pTarget->est.pos;
  1231. }
  1232. else
  1233. {
  1234. pTarget->latched.bHasLatch = false;
  1235. pTarget->latched.q = pTarget->est.q;
  1236. pTarget->latched.pos = pTarget->est.pos;
  1237. pTarget->latched.deltaPos.Init();
  1238. pTarget->latched.deltaQ.Init();
  1239. }
  1240. pTarget->latched.influence = latched;
  1241. }
  1242. // check for illegal requests
  1243. Vector p1, p2, p3;
  1244. MatrixPosition( boneToWorld[pchain->pLink( 0 )->bone], p1 ); // hip
  1245. MatrixPosition( boneToWorld[pchain->pLink( 1 )->bone], p2 ); // knee
  1246. MatrixPosition( boneToWorld[pchain->pLink( 2 )->bone], p3 ); // foot
  1247. float d1 = (p2 - p1).Length();
  1248. float d2 = (p3 - p2).Length();
  1249. if (pTarget->latched.bHasLatch)
  1250. {
  1251. //float d3 = (p3 - p1).Length();
  1252. float d4 = (p3 + pTarget->latched.deltaPos - p1).Length();
  1253. // unstick feet when distance is too great
  1254. if ((d4 < fabs( d1 - d2 ) || d4 * 0.95 > d1 + d2) && pTarget->est.latched > 0.2)
  1255. {
  1256. pTarget->error.flTime = m_flTime;
  1257. }
  1258. // unstick feet when angle is too great
  1259. if (pTarget->est.latched > 0.2)
  1260. {
  1261. float d = fabs( pTarget->latched.deltaQ.w ) * 2.0f - 1.0f; // QuaternionDotProduct( pTarget->latched.q, pTarget->est.q );
  1262. // FIXME: cos(45), make property of chain
  1263. if (d < 0.707)
  1264. {
  1265. pTarget->error.flTime = m_flTime;
  1266. }
  1267. }
  1268. }
  1269. Vector dt = pTarget->est.pos - p1;
  1270. pTarget->trace.hipToFoot = VectorNormalize( dt );
  1271. pTarget->trace.hipToKnee = d1;
  1272. pTarget->trace.kneeToFoot = d2;
  1273. pTarget->trace.hip = p1;
  1274. pTarget->trace.knee = p2;
  1275. pTarget->trace.closest = p1 + dt * (fabs( d1 - d2 ) * 1.01);
  1276. pTarget->trace.farthest = p1 + dt * (d1 + d2) * 0.99;
  1277. pTarget->trace.lowest = p1 + Vector( 0, 0, -1 ) * (d1 + d2) * 0.99;
  1278. // pTarget->trace.endpos = pTarget->est.pos;
  1279. }
  1280. }
  1281. }
  1282. //-----------------------------------------------------------------------------
  1283. // Purpose: insert release rules if the ik rules were in error
  1284. //-----------------------------------------------------------------------------
  1285. void CIKContext::AutoIKRelease( void )
  1286. {
  1287. BONE_PROFILE_FUNC();
  1288. int i;
  1289. for (i = 0; i < m_target.Count(); i++)
  1290. {
  1291. CIKTarget *pTarget = &m_target[i];
  1292. float dt = m_flTime - pTarget->error.flTime;
  1293. if (pTarget->error.bInError || dt < 0.5)
  1294. {
  1295. if (!pTarget->error.bInError)
  1296. {
  1297. pTarget->error.ramp = 0.0;
  1298. pTarget->error.flErrorTime = pTarget->error.flTime;
  1299. pTarget->error.bInError = true;
  1300. }
  1301. float ft = m_flTime - pTarget->error.flErrorTime;
  1302. if (dt < 0.25)
  1303. {
  1304. pTarget->error.ramp = MIN( pTarget->error.ramp + ft * 4.0, 1.0 );
  1305. }
  1306. else
  1307. {
  1308. pTarget->error.ramp = MAX( pTarget->error.ramp - ft * 4.0, 0.0 );
  1309. }
  1310. if (pTarget->error.ramp > 0.0)
  1311. {
  1312. ikcontextikrule_t ikrule;
  1313. ikrule.chain = pTarget->chain;
  1314. ikrule.bone = 0;
  1315. ikrule.type = IK_RELEASE;
  1316. ikrule.slot = i;
  1317. ikrule.flWeight = SimpleSpline( pTarget->error.ramp );
  1318. ikrule.flRuleWeight = 1.0;
  1319. ikrule.latched = dt < 0.25 ? 0.0 : ikrule.flWeight;
  1320. // don't bother with AutoIKRelease if the bone isn't going to be calculated
  1321. // this code is crashing for some unknown reason.
  1322. if ( pTarget->chain >= 0 && pTarget->chain < m_pStudioHdr->numikchains())
  1323. {
  1324. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( pTarget->chain );
  1325. if (pchain != NULL)
  1326. {
  1327. int bone = pchain->pLink( 2 )->bone;
  1328. if (bone >= 0 && bone < m_pStudioHdr->numbones())
  1329. {
  1330. const mstudiobone_t *pBone = m_pStudioHdr->pBone( bone );
  1331. if (pBone != NULL)
  1332. {
  1333. if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  1334. {
  1335. pTarget->error.bInError = false;
  1336. continue;
  1337. }
  1338. /*
  1339. char buf[256];
  1340. sprintf( buf, "dt %.4f ft %.4f weight %.4f latched %.4f\n", dt, ft, ikrule.flWeight, ikrule.latched );
  1341. OutputDebugString( buf );
  1342. */
  1343. int nIndex = m_ikChainRule.Element( ikrule.chain ).AddToTail( );
  1344. m_ikChainRule.Element( ikrule.chain ).Element( nIndex ) = ikrule;
  1345. }
  1346. else
  1347. {
  1348. DevWarning( 1, "AutoIKRelease (%s) got a NULL pBone %d\n", m_pStudioHdr->name(), bone );
  1349. }
  1350. }
  1351. else
  1352. {
  1353. DevWarning( 1, "AutoIKRelease (%s) got an out of range bone %d (%d)\n", m_pStudioHdr->name(), bone, m_pStudioHdr->numbones() );
  1354. }
  1355. }
  1356. else
  1357. {
  1358. DevWarning( 1, "AutoIKRelease (%s) got a NULL pchain %d\n", m_pStudioHdr->name(), pTarget->chain );
  1359. }
  1360. }
  1361. else
  1362. {
  1363. DevWarning( 1, "AutoIKRelease (%s) got an out of range chain %d (%d)\n", m_pStudioHdr->name(), pTarget->chain, m_pStudioHdr->numikchains());
  1364. }
  1365. }
  1366. else
  1367. {
  1368. pTarget->error.bInError = false;
  1369. }
  1370. pTarget->error.flErrorTime = m_flTime;
  1371. }
  1372. }
  1373. }
  1374. void CIKContext::SolveDependencies( BoneVector pos[], BoneQuaternion q[], matrix3x4a_t boneToWorld[], CBoneBitList &boneComputed )
  1375. {
  1376. BONE_PROFILE_FUNC(); // ex: x360: up to 1.16ms
  1377. // ASSERT_NO_REENTRY();
  1378. SNPROF_ANIM( "CIKContext::SolveDependencies" );
  1379. matrix3x4a_t worldTarget;
  1380. int i, j;
  1381. ikchainresult_t chainResult[32]; // allocate!!!
  1382. // init chain rules
  1383. for( i = 0; i < m_pStudioHdr->numikchains(); i++ )
  1384. {
  1385. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( i );
  1386. ikchainresult_t *pChainResult = &chainResult[ i ];
  1387. int bone = pchain->pLink( 2 )->bone;
  1388. pChainResult->target = -1;
  1389. pChainResult->flWeight = 0.0f;
  1390. // don't bother with chain if the bone isn't going to be calculated
  1391. if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  1392. continue;
  1393. // eval current ik'd bone
  1394. BuildBoneChain( pos, q, bone, boneToWorld, boneComputed );
  1395. MatrixAngles( boneToWorld[bone], pChainResult->q, pChainResult->pos );
  1396. }
  1397. for( j = 0; j < m_ikChainRule.Count(); j++ )
  1398. {
  1399. for( i = 0; i < m_ikChainRule.Element( j ).Count(); i++ )
  1400. {
  1401. ikcontextikrule_t *pRule = &m_ikChainRule.Element( j ).Element( i );
  1402. ikchainresult_t *pChainResult = &chainResult[ pRule->chain ];
  1403. pChainResult->target = -1;
  1404. switch( pRule->type )
  1405. {
  1406. case IK_SELF:
  1407. {
  1408. // xform IK target error into world space
  1409. matrix3x4a_t local;
  1410. QuaternionMatrix( pRule->q, pRule->pos, local );
  1411. // eval target bone space
  1412. if (pRule->bone != -1)
  1413. {
  1414. BuildBoneChain( pos, q, pRule->bone, boneToWorld, boneComputed );
  1415. ConcatTransforms_Aligned( boneToWorld[pRule->bone], local, worldTarget );
  1416. }
  1417. else
  1418. {
  1419. ConcatTransforms_Aligned( m_rootxform, local, worldTarget );
  1420. }
  1421. float flWeight = pRule->flWeight * pRule->flRuleWeight;
  1422. pChainResult->flWeight = pChainResult->flWeight * (1.0f - flWeight) + flWeight;
  1423. Vector p2;
  1424. Quaternion q2;
  1425. // target p and q
  1426. MatrixAngles( worldTarget, q2, p2 );
  1427. // debugLine( pChainResult->pos, p2, 0, 0, 255, true, 0.1 );
  1428. // blend in position and angles
  1429. pChainResult->pos = pChainResult->pos * (1.0f - flWeight) + p2 * flWeight;
  1430. QuaternionSlerp( pChainResult->q, q2, flWeight, pChainResult->q );
  1431. }
  1432. break;
  1433. case IK_WORLD:
  1434. Assert( 0 );
  1435. break;
  1436. case IK_ATTACHMENT:
  1437. break;
  1438. case IK_GROUND:
  1439. break;
  1440. case IK_RELEASE:
  1441. {
  1442. // move target back towards original location
  1443. float flWeight = pRule->flWeight * pRule->flRuleWeight;
  1444. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( pRule->chain );
  1445. int bone = pchain->pLink( 2 )->bone;
  1446. Vector p2;
  1447. Quaternion q2;
  1448. BuildBoneChain( pos, q, bone, boneToWorld, boneComputed );
  1449. MatrixAngles( boneToWorld[bone], q2, p2 );
  1450. // blend in position and angles
  1451. pChainResult->pos = pChainResult->pos * (1.0 - flWeight) + p2 * flWeight;
  1452. QuaternionSlerp( pChainResult->q, q2, flWeight, pChainResult->q );
  1453. }
  1454. break;
  1455. case IK_UNLATCH:
  1456. {
  1457. /*
  1458. pChainResult->flWeight = pChainResult->flWeight * (1 - pRule->flWeight) + pRule->flWeight;
  1459. pChainResult->pos = pChainResult->pos * (1.0 - pRule->flWeight ) + pChainResult->local.pos * pRule->flWeight;
  1460. QuaternionSlerp( pChainResult->q, pChainResult->local.q, pRule->flWeight, pChainResult->q );
  1461. */
  1462. }
  1463. break;
  1464. }
  1465. }
  1466. }
  1467. for (i = 0; i < m_target.Count(); i++)
  1468. {
  1469. CIKTarget *pTarget = &m_target[i];
  1470. if (m_target[i].est.flWeight > 0.0)
  1471. {
  1472. matrix3x4a_t worldFootpad;
  1473. matrix3x4a_t local;
  1474. //mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( m_target[i].chain );
  1475. ikchainresult_t *pChainResult = &chainResult[ pTarget->chain ];
  1476. AngleMatrix( RadianEuler(pTarget->offset.q), pTarget->offset.pos, local );
  1477. AngleMatrix( RadianEuler(pTarget->est.q), pTarget->est.pos, worldFootpad );
  1478. ConcatTransforms_Aligned( worldFootpad, local, worldTarget );
  1479. Vector p2;
  1480. Quaternion q2;
  1481. // target p and q
  1482. MatrixAngles( worldTarget, q2, p2 );
  1483. // MatrixAngles( worldTarget, pChainResult->q, pChainResult->pos );
  1484. // blend in position and angles
  1485. pChainResult->flWeight = pTarget->est.flWeight;
  1486. pChainResult->pos = pChainResult->pos * (1.0 - pChainResult->flWeight ) + p2 * pChainResult->flWeight;
  1487. QuaternionSlerp( pChainResult->q, q2, pChainResult->flWeight, pChainResult->q );
  1488. }
  1489. if (pTarget->latched.bNeedsLatch)
  1490. {
  1491. // keep track of latch position
  1492. pTarget->latched.bHasLatch = true;
  1493. pTarget->latched.q = pTarget->est.q;
  1494. pTarget->latched.pos = pTarget->est.pos;
  1495. }
  1496. }
  1497. for (i = 0; i < m_pStudioHdr->numikchains(); i++)
  1498. {
  1499. ikchainresult_t *pChainResult = &chainResult[ i ];
  1500. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( i );
  1501. if (pChainResult->flWeight > 0.0)
  1502. {
  1503. Vector tmp;
  1504. MatrixPosition( boneToWorld[pchain->pLink( 2 )->bone], tmp );
  1505. // debugLine( pChainResult->pos, tmp, 255, 255, 255, true, 0.1 );
  1506. // do exact IK solution
  1507. // FIXME: once per link!
  1508. if (Studio_SolveIK(pchain, pChainResult->pos, boneToWorld ))
  1509. {
  1510. Vector p3;
  1511. MatrixGetColumn( boneToWorld[pchain->pLink( 2 )->bone], 3, p3 );
  1512. QuaternionMatrix( pChainResult->q, p3, boneToWorld[pchain->pLink( 2 )->bone] );
  1513. // rebuild chain
  1514. // FIXME: is this needed if everyone past this uses the boneToWorld array?
  1515. SolveBone( m_pStudioHdr, pchain->pLink( 2 )->bone, boneToWorld, pos, q );
  1516. SolveBone( m_pStudioHdr, pchain->pLink( 1 )->bone, boneToWorld, pos, q );
  1517. SolveBone( m_pStudioHdr, pchain->pLink( 0 )->bone, boneToWorld, pos, q );
  1518. }
  1519. else
  1520. {
  1521. // FIXME: need to invalidate the targets that forced this...
  1522. if (pChainResult->target != -1)
  1523. {
  1524. CIKTarget *pTarget = &m_target[pChainResult->target];
  1525. VectorScale( pTarget->latched.deltaPos, 0.8, pTarget->latched.deltaPos );
  1526. QuaternionScale( pTarget->latched.deltaQ, 0.8, pTarget->latched.deltaQ );
  1527. }
  1528. }
  1529. }
  1530. }
  1531. #if 0
  1532. Vector p1, p2, p3;
  1533. Quaternion q1, q2, q3;
  1534. // current p and q
  1535. MatrixAngles( boneToWorld[bone], q1, p1 );
  1536. // target p and q
  1537. MatrixAngles( worldTarget, q2, p2 );
  1538. // blend in position and angles
  1539. p3 = p1 * (1.0 - m_ikRule[i].flWeight ) + p2 * m_ikRule[i].flWeight;
  1540. // do exact IK solution
  1541. // FIXME: once per link!
  1542. Studio_SolveIK(pchain, p3, boneToWorld );
  1543. // force angle (bad?)
  1544. QuaternionSlerp( q1, q2, m_ikRule[i].flWeight, q3 );
  1545. MatrixGetColumn( boneToWorld[bone], 3, p3 );
  1546. QuaternionMatrix( q3, p3, boneToWorld[bone] );
  1547. // rebuild chain
  1548. SolveBone( m_pStudioHdr, pchain->pLink( 2 )->bone, boneToWorld, pos, q );
  1549. SolveBone( m_pStudioHdr, pchain->pLink( 1 )->bone, boneToWorld, pos, q );
  1550. SolveBone( m_pStudioHdr, pchain->pLink( 0 )->bone, boneToWorld, pos, q );
  1551. #endif
  1552. }
  1553. #if 0
  1554. //-----------------------------------------------------------------------------------------------------------------------
  1555. //
  1556. // SolveDependencies path abandoned for now, code here for reference
  1557. // in order for this to be efficient (multiple pass bone setup) we need to find a more appropriate
  1558. // point at which to perform multiple passes over baseanimating jobs (i.e. after each generation)
  1559. //
  1560. //-----------------------------------------------------------------------------------------------------------------------
  1561. //-----------------------------------------------------------------------------------------------------------------------
  1562. // Pass1/2 here (PPU) - Pass2/2 done on SPU
  1563. // Fill bonejob data
  1564. //-----------------------------------------------------------------------------------------------------------------------
  1565. void CIKContext::SolveDependencies_PS3( bonejob_SPU_2 *pBonejob, CBoneBitList &boneComputed )
  1566. {
  1567. SNPROF_ANIM( "CIKContext::SolveDependencies_PS3" );
  1568. int i, j;
  1569. pBonejob->rootxform = m_rootxform;
  1570. // copy over computed
  1571. pBonejob->boneComputed.ResetMarkedBones( m_pStudioHdr->numbones() );
  1572. for( i = 0; i < m_pStudioHdr->numbones(); i++ )
  1573. {
  1574. if( boneComputed.IsBoneMarked( i ) )
  1575. {
  1576. // mark bone
  1577. pBonejob->boneComputed.MarkBone( i );
  1578. // copy matrix
  1579. //pBonejob->boneToWorld[ i ] = boneToWorld[ i ];
  1580. // could build a dma list so we only copy over valid matrices?
  1581. }
  1582. }
  1583. pBonejob->numikchainElements = 0;
  1584. pBonejob->studiohdr_numikchains = m_pStudioHdr->numikchains();
  1585. // init chain rules
  1586. for( i = 0; i < m_pStudioHdr->numikchains(); i++ )
  1587. {
  1588. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( i );
  1589. ikChain_SPU *pchain_SPU = &pBonejob->ikChains[ i ];
  1590. pchain_SPU->bone0 = pchain->pLink( 0 )->bone;
  1591. pchain_SPU->bone1 = pchain->pLink( 1 )->bone;
  1592. pchain_SPU->bone2 = pchain->pLink( 2 )->bone;
  1593. pchain_SPU->kneeDir0 = pchain->pLink( 0 )->kneeDir;
  1594. // don't bother with chain if the bone isn't going to be calculated
  1595. if ( !(m_pStudioHdr->boneFlags( pchain_SPU->bone2 ) & m_boneMask))
  1596. pchain_SPU->bone2 = -1;
  1597. }
  1598. for( j = 0; j < m_ikChainRule.Count(); j++ )
  1599. {
  1600. for( i = 0; i < m_ikChainRule.Element( j ).Count(); i++ )
  1601. {
  1602. ikcontextikrule_t *pRule = &m_ikChainRule.Element( j ).Element( i );
  1603. AssertFatal( pBonejob->numikchainElements >= MAX_IKCHAINELEMENTS );
  1604. switch( pRule->type )
  1605. {
  1606. case IK_SELF:
  1607. {
  1608. pBonejob->ikchainElement_rules[ pBonejob->numikchainElements++ ] = pRule;
  1609. }
  1610. break;
  1611. case IK_WORLD:
  1612. Assert( 0 );
  1613. break;
  1614. case IK_ATTACHMENT:
  1615. break;
  1616. case IK_GROUND:
  1617. break;
  1618. case IK_RELEASE:
  1619. {
  1620. // move target back towards original location
  1621. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( pRule->chain );
  1622. pBonejob->ikchainElement_rules[ pBonejob->numikchainElements ] = pRule;
  1623. pBonejob->ikchainElement_bones[ pBonejob->numikchainElements ] = pchain->pLink( 2 )->bone;
  1624. pBonejob->numikchainElements++;
  1625. }
  1626. break;
  1627. case IK_UNLATCH:
  1628. {
  1629. /*
  1630. pChainResult->flWeight = pChainResult->flWeight * (1 - pRule->flWeight) + pRule->flWeight;
  1631. pChainResult->pos = pChainResult->pos * (1.0 - pRule->flWeight ) + pChainResult->local.pos * pRule->flWeight;
  1632. QuaternionSlerp( pChainResult->q, pChainResult->local.q, pRule->flWeight, pChainResult->q );
  1633. */
  1634. }
  1635. break;
  1636. }
  1637. }
  1638. }
  1639. pBonejob->iktargetcount = m_target.Count();
  1640. for (i = 0; i < m_target.Count(); i++)
  1641. {
  1642. CIKTarget *pTarget = &m_target[i];
  1643. pBonejob->iktargets[ i ] = pTarget;
  1644. }
  1645. }
  1646. #endif
  1647. //-----------------------------------------------------------------------------
  1648. // Purpose:
  1649. //-----------------------------------------------------------------------------
  1650. void CIKContext::SolveAutoplayLocks(
  1651. BoneVector pos[],
  1652. BoneQuaternion q[]
  1653. )
  1654. {
  1655. BONE_PROFILE_FUNC(); // ex: x360: 2.44ms
  1656. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  1657. CBoneBitList boneComputed;
  1658. int i;
  1659. for (i = 0; i < m_ikLock.Count(); i++)
  1660. {
  1661. const mstudioiklock_t &lock = ((CStudioHdr *)m_pStudioHdr)->pIKAutoplayLock( i );
  1662. SolveLock( &lock, i, pos, q, boneToWorld, boneComputed );
  1663. }
  1664. g_MatrixPool.Free( boneToWorld );
  1665. }
  1666. //-----------------------------------------------------------------------------
  1667. // Purpose:
  1668. //-----------------------------------------------------------------------------
  1669. void CIKContext::SolveSequenceLocks(
  1670. mstudioseqdesc_t &seqdesc,
  1671. BoneVector pos[],
  1672. BoneQuaternion q[]
  1673. )
  1674. {
  1675. BONE_PROFILE_FUNC();
  1676. SNPROF_ANIM("CIKContext::SolveSequenceLocks");
  1677. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  1678. CBoneBitList boneComputed;
  1679. int i;
  1680. for (i = 0; i < m_ikLock.Count(); i++)
  1681. {
  1682. mstudioiklock_t *plock = seqdesc.pIKLock( i );
  1683. SolveLock( plock, i, pos, q, boneToWorld, boneComputed );
  1684. }
  1685. g_MatrixPool.Free( boneToWorld );
  1686. }
  1687. //-----------------------------------------------------------------------------
  1688. // Purpose:
  1689. //-----------------------------------------------------------------------------
  1690. void CIKContext::AddAllLocks( BoneVector pos[], BoneQuaternion q[] )
  1691. {
  1692. BONE_PROFILE_FUNC();
  1693. // skip all array access if no autoplay locks.
  1694. if (m_pStudioHdr->GetNumIKChains() == 0)
  1695. {
  1696. return;
  1697. }
  1698. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  1699. CBoneBitList boneComputed;
  1700. int ikOffset = m_ikLock.AddMultipleToTail( m_pStudioHdr->GetNumIKChains() );
  1701. memset( &m_ikLock[ikOffset], 0, sizeof(ikcontextikrule_t)*m_pStudioHdr->GetNumIKChains() );
  1702. for (int i = 0; i < m_pStudioHdr->GetNumIKChains(); i++)
  1703. {
  1704. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( i );
  1705. int bone = pchain->pLink( 2 )->bone;
  1706. // don't bother with iklock if the bone isn't going to be calculated
  1707. if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  1708. continue;
  1709. // eval current ik'd bone
  1710. BuildBoneChain( pos, q, bone, boneToWorld, boneComputed );
  1711. ikcontextikrule_t &ikrule = m_ikLock[ i + ikOffset ];
  1712. ikrule.chain = i;
  1713. ikrule.slot = i;
  1714. ikrule.type = IK_WORLD;
  1715. MatrixAngles( boneToWorld[bone], ikrule.q, ikrule.pos );
  1716. // save off current knee direction
  1717. if (pchain->pLink(0)->kneeDir.LengthSqr() > 0.0)
  1718. {
  1719. Vector tmp = pchain->pLink( 0 )->kneeDir;
  1720. VectorRotate( pchain->pLink( 0 )->kneeDir, boneToWorld[ pchain->pLink( 0 )->bone ], ikrule.kneeDir );
  1721. MatrixPosition( boneToWorld[ pchain->pLink( 1 )->bone ], ikrule.kneePos );
  1722. }
  1723. else
  1724. {
  1725. ikrule.kneeDir.Init( );
  1726. }
  1727. }
  1728. g_MatrixPool.Free( boneToWorld );
  1729. }
  1730. //-----------------------------------------------------------------------------
  1731. // Purpose:
  1732. //-----------------------------------------------------------------------------
  1733. void CIKContext::SolveAllLocks(
  1734. BoneVector pos[],
  1735. BoneQuaternion q[]
  1736. )
  1737. {
  1738. BONE_PROFILE_FUNC();
  1739. matrix3x4a_t *boneToWorld = g_MatrixPool.Alloc();
  1740. CBoneBitList boneComputed;
  1741. int i;
  1742. mstudioiklock_t lock;
  1743. for (i = 0; i < m_ikLock.Count(); i++)
  1744. {
  1745. lock.chain = i;
  1746. lock.flPosWeight = 1.0;
  1747. lock.flLocalQWeight = 0.0;
  1748. lock.flags = 0;
  1749. SolveLock( &lock, i, pos, q, boneToWorld, boneComputed );
  1750. }
  1751. g_MatrixPool.Free( boneToWorld );
  1752. }
  1753. //-----------------------------------------------------------------------------
  1754. // Purpose:
  1755. //-----------------------------------------------------------------------------
  1756. void CIKContext::SolveLock(
  1757. const mstudioiklock_t *plock,
  1758. int i,
  1759. BoneVector pos[],
  1760. BoneQuaternion q[],
  1761. matrix3x4a_t boneToWorld[],
  1762. CBoneBitList &boneComputed
  1763. )
  1764. {
  1765. BONE_PROFILE_FUNC(); // ex: x360:up to 1.18 ms
  1766. mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( plock->chain );
  1767. int bone = pchain->pLink( 2 )->bone;
  1768. // don't bother with iklock if the bone isn't going to be calculated
  1769. if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask))
  1770. return;
  1771. // eval current ik'd bone
  1772. BuildBoneChain( pos, q, bone, boneToWorld, boneComputed );
  1773. Vector p1, p2, p3;
  1774. Quaternion q2, q3;
  1775. // current p and q
  1776. MatrixPosition( boneToWorld[bone], p1 );
  1777. // blend in position
  1778. p3 = p1 * (1.0 - plock->flPosWeight ) + m_ikLock[i].pos * plock->flPosWeight;
  1779. // do exact IK solution
  1780. if (m_ikLock[i].kneeDir.LengthSqr() > 0)
  1781. {
  1782. Studio_SolveIK(pchain->pLink( 0 )->bone, pchain->pLink( 1 )->bone, pchain->pLink( 2 )->bone, p3, m_ikLock[i].kneePos, m_ikLock[i].kneeDir, boneToWorld );
  1783. }
  1784. else
  1785. {
  1786. Studio_SolveIK(pchain, p3, boneToWorld );
  1787. }
  1788. // slam orientation
  1789. MatrixPosition( boneToWorld[bone], p3 );
  1790. QuaternionMatrix( m_ikLock[i].q, p3, boneToWorld[bone] );
  1791. // rebuild chain
  1792. q2 = q[ bone ];
  1793. SolveBone( m_pStudioHdr, pchain->pLink( 2 )->bone, boneToWorld, pos, q );
  1794. QuaternionSlerp( q[bone], q2, plock->flLocalQWeight, q[bone] );
  1795. SolveBone( m_pStudioHdr, pchain->pLink( 1 )->bone, boneToWorld, pos, q );
  1796. SolveBone( m_pStudioHdr, pchain->pLink( 0 )->bone, boneToWorld, pos, q );
  1797. }
  1798. void CIKContext::CopyTo( CIKContext* pOther, const unsigned short * iRemapping )
  1799. {
  1800. if ( !pOther )
  1801. return;
  1802. // replace the ik rules and ik locks on the other ik context, and remap the bone chain indices to match
  1803. pOther->m_ikChainRule.RemoveAll();
  1804. pOther->m_ikLock.RemoveAll();
  1805. FOR_EACH_VEC( m_ikChainRule, n )
  1806. {
  1807. int nIndex = pOther->m_ikChainRule.AddToTail();
  1808. FOR_EACH_VEC( m_ikChainRule[n], m )
  1809. {
  1810. int nIKChainBone = m_ikChainRule[n][m].bone;
  1811. if ( iRemapping != NULL && m_ikChainRule[ n ][ m ].type != IK_RELEASE )
  1812. {
  1813. int nIKChainBoneRemapped = iRemapping[ nIKChainBone ];
  1814. if ( nIKChainBoneRemapped < 0 || nIKChainBoneRemapped >= MAXSTUDIOBONES )
  1815. continue; // don't copy this chain rule at all
  1816. nIKChainBone = nIKChainBoneRemapped;
  1817. }
  1818. int nSubIndex = pOther->m_ikChainRule[nIndex].AddToTail();
  1819. pOther->m_ikChainRule[nIndex][nSubIndex] = m_ikChainRule[n][m];
  1820. pOther->m_ikChainRule[nIndex][nSubIndex].bone = nIKChainBone; // this can be a remapped bone
  1821. }
  1822. }
  1823. FOR_EACH_VEC( m_ikLock, n )
  1824. {
  1825. int nIKChainBone = m_ikLock[n].bone;
  1826. if ( iRemapping != NULL && m_ikLock[ n ].type != IK_RELEASE )
  1827. {
  1828. int nIKChainBoneRemapped = iRemapping[ nIKChainBone ];
  1829. if ( nIKChainBoneRemapped < 0 || nIKChainBoneRemapped >= MAXSTUDIOBONES )
  1830. continue; // don't copy this ik lock at all
  1831. nIKChainBone = nIKChainBoneRemapped;
  1832. }
  1833. int nIndex = pOther->m_ikLock.AddToTail();
  1834. pOther->m_ikLock[nIndex] = m_ikLock[n];
  1835. pOther->m_ikLock[ nIndex ].bone = nIKChainBone; // this can be a remapped bone
  1836. }
  1837. }